Table of contents
Introduction
I have been using APEX Email Templates since their release in APEX 18.1 (I think). They offer a clean way to separate the content of your email from the layout. In this post, I will review two advanced features of APEX Email Templates, which allow you to get even more from this excellent feature.
Template Directives - You can use Template Directives in APEX Mail Templates. They offer an excellent method of deciding what will be displayed from the UI instead of in the data source.
In-Line CSS Styling - Adding CSS to your template lets you style your email content to emphasize important information and give your emails a more professional look.
Email Templates Primer
With APEX Email templates, you provide a JSON document to the APEX_MAIL API via a parameter called p_placeholders
. APEX then takes the values in the JSON and replaces the placeholders in the template (identified by placeholders like #PO_NUMBER#
) with the associated values in the JSON.
Example APEX_MAIL API Call
begin
apex_mail.send
(p_to => 'jon@cloudnueva.com',
p_template_static_id => 'PO_APPROVALS',
p_application_id => 1020,
p_placeholders => '{' ||
' "PO_NUMBER":' || apex_json.stringify( '1000' ) ||
' ,"PO_STATUS":' || apex_json.stringify( 'PENDING' ) ||
' ,"SUBJECT":' || apex_json.stringify( 'Approval Required' ) ||
' ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
' ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
' ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
' ,"PO_AMOUNT":' || apex_json.stringify( '$12,000.00' ) ||
' ,"BUYER_NAME":' || apex_json.stringify( 'Bob the Builder' ) ||
'}' );
apex_mail.push_queue;
end;
Example Template
The email template contains the placeholder tags, e.g. #APPROVER_NAME#
Result
The result is a formatted email, which looks just OK.
Template Directives
Template Directives allow you to add conditional logic to Email Templates to conditionally display content in the resulting email.
Benefits
By injecting logic into the Template, Template Directives allow you to:
Reduce the number of Email Templates you need to create (and maintain).
Remove conditional logic from the code that generates the placeholders. You often only need one procedure instead of many to generate the placeholder JSON.
Example 'if' Directive
Let's improve the PO Approval Email template by adding bold red text to the email Header if the PO is over $12,000.
{if HIGH_VALUE_PO/}
<br><span class="po-high-value">#HIGH_VALUE_PO#</span>
{endif/}
The if
condition checks if the placeholder #HIGH_VALUE_PO#
has a value. If it has a value, it is displayed in the email. If it does not, no content is output to the email header.
Example case Directive
Next, let's display additional text in the email header indicating if the email is requesting approval or is being sent to confirm the PO has been Approved (or Rejected).
{case PO_STATUS/}
{when APPROVED/}
<br><span class="po-approved">PO Approved</span>
{when REJECTED/}
<br><span class="po-rejected">PO Rejected</span>
{otherwise/}
<br><span class="po-pending">PO Pending Approval</span>
{endcase/}
This directive checks the value of the placeholder #PO_STATUS# and emits different text depending on the PO Status. I will discuss the CSS classes in the next section.
In-Line Custom CSS
Now that we have made the template more dynamic, let's turn our attention to improving the look of the email. We can easily do this by adding some CSS.
You may have noticed some CSS classes in the Email Header Template Directives above, e.g., po-high-value, po-approved
. We can add our custom CSS to the Advanced section of the email template.
In a new template, the Advanced section is empty. However, if we click the 'Load Default HTML' button, we can populate it with the default HTML, giving us a starting point. We can then add our CSS in the <style>
section of the 'HTML Template' property.
I added the CSS (within the <style>
tags) to get the final email result described later in the post.
.subject {
font-size:2.0em;
font-weight: bold;
}
.po-high-value {
font-size:1.5em;
color: red;
font-weight: bold;
}
.po-approved {
font-size:1.25em;
color: green;
font-weight: bold;
}
.po-rejected {
font-size:1.5em;
color: red;
font-weight: bold;
}
.po-pending {
font-size:1.5em;
color: blue;
font-weight: bold;
}
.my-table td,
.my-table th {
padding: 5px;
border: 1px solid #000;
}
.my-table,
.my-table td,
.my-table th {
border: 1px solid #000;
}
.my-table {
width: 100%;
border-collapse: collapse;
font-size: smaller;
}
.my-table th {
background-color: #d3d3d3;
text-align: left;
width: 33%;
}
Formatting the PO Details HTML Table
You may notice some additional classes related to my-table
. These classes will style the table to show purchase order details. Here is a screenshot of the Body Section of the Email Template, where you can see the <table>
definition.
The Final Result
Let's look at three scenarios showing the different phases of PO Approval.
High-Value PO Pending Approval
begin
apex_mail.send
(p_to => 'jon@cloudnueva.com',
p_template_static_id => 'PO_APPROVALS',
p_application_id => 1020,
p_placeholders => '{' ||
' "PO_NUMBER":' || apex_json.stringify( '1001' ) ||
' ,"PO_STATUS":' || apex_json.stringify( 'PENDING' ) ||
' ,"SUBJECT":' || apex_json.stringify( 'Requires Approval' ) ||
' ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
' ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
' ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
' ,"PO_AMOUNT":' || apex_json.stringify( '$12,000.00' ) ||
' ,"BUYER_NAME":' || apex_json.stringify( 'Bob the Builder' ) ||
'}' );
apex_mail.push_queue;
end;
Regular PO Approved
begin
apex_mail.send
(p_to => 'jon@cloudnueva.com',
p_template_static_id => 'PO_APPROVALS',
p_application_id => 1020,
p_placeholders => '{' ||
' "PO_NUMBER":' || apex_json.stringify( '1001' ) ||
' ,"PO_STATUS":' || apex_json.stringify( 'APPROVED' ) ||
' ,"SUBJECT":' || apex_json.stringify( 'Approved' ) ||
-- ' ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
' ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
' ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
' ,"PO_AMOUNT":' || apex_json.stringify( '$9,000.00' ) ||
' ,"BUYER_NAME":' || apex_json.stringify( 'Bob the Builder' ) ||
'}' );
apex_mail.push_queue;
end;
PO Rejected
begin
apex_mail.send
(p_to => 'jon@cloudnueva.com',
p_template_static_id => 'PO_APPROVALS',
p_application_id => 1020,
p_placeholders => '{' ||
' "PO_NUMBER":' || apex_json.stringify( '1001' ) ||
' ,"PO_STATUS":' || apex_json.stringify( 'REJECTED' ) ||
' ,"SUBJECT":' || apex_json.stringify( 'Rejected' ) ||
-- ' ,"HIGH_VALUE_PO":' || apex_json.stringify( 'Please Review Carefully, this PO is over $10,000' ) ||
' ,"APPROVER_NAME":' || apex_json.stringify( 'Jon Dixon' ) ||
' ,"SUPPLIER_NAME":' || apex_json.stringify( 'ABC Materials INC' ) ||
' ,"PO_AMOUNT":' || apex_json.stringify( '$9,000.00' ) ||
' ,"BUYER_NAME":' || apex_json.stringify( 'Bob the Builder' ) ||
'}' );
apex_mail.push_queue;
end;
Conclusion
In this post, I explored the advanced features of APEX Email Templates, focusing on Template Directives and In-Line CSS Styling. Template Directives allow conditional content to be displayed within emails, reducing the need for multiple templates and simplifying placeholder JSON generation. In-line CSS Styling enhances the visual appeal of emails.
Finally, I demonstrated how these techniques can produce different email outputs for various Purchase Order (PO) statuses.