Incorporating VTL in Email Template XML
All input arguments in the template signature are automatically loaded into the VelocityContext and are therefore accessible through the VTL reference notation for inclusion in the message text. Additionally, Velocity commands can be used in determining the text to print in the messages. Excerpts from the default email templates in IdentityIQ are used as examples throughout the rest of this section to illustrate how reference variables and various command syntaxes can be used.
Where to Use VTL
The Velocity Template Language syntax can be specified in any attribute or element that is used to build the email message. Most commonly, this means the <Subject> and <Body> elements of the message, but the cc and bcc recipients (as well as the from email address) are often dynamically specified through reference variables as well.
Reference Variables
Note
For HTML contained within variables, refer to HTML Escaping.
When a variable name is referenced within the text for any of the message elements, its value is substituted into the text in its place.
Example:
<Body>$certifierName has accepted the challenge for '$challengeItem' and will change the decision.
</Body>
Variable substitution results in the email message content:
John Smith has accepted the challenge for 'Entitlements on Financials' and will change the decision. Velocity can also access data values in fields within objects passed as arguments and replace the variable notation with those values. Consider the <subject> and <body> elements shown below. The argument list for this email template includes a Certification object (named certification) and an Identity object (named certifier).
<Subject>$certification.name requires approval</Subject>
<Body>$certification.name was signed by $certifier.displayableName and requires your
approval.
Login and view your work item inbox to complete this request.
</Body>
To resolve these variable references, Velocity calls the getName() method on the certification object and the getDisplayableName() method on the certifier's identity object. When the substitutions are made, the final email message looks like this:
Subject: Manager Access Review for Catherine Simmons requires approval
Manager Access Review for Catherine Simmons was signed by Catherine Simmons and requires your approval.
Login and view your work item inbox to complete this request.
Any attribute or method on any of a template's input arguments can be accessed through the reference variables.
Extended attributes on IdentityIQ objects can be accessed through the attributes hash map or by providing the attribute name as an argument to the appropriate getter method. Identity extended attributes, for example, are accessible through the Identity's attributes hash map or through the getAttribute() method on the Identity object (e.g. $certifier.attributes.region and $certifier.getAttribute("region") both return the value in the "region" extended attribute).
Note
The list of available methods for IdentityIQ objects (Identity, Certification, ProvisioningPlan, etc.) can be found in the SailPoint JavaDocs that ship with the IdentityIQ product. These can be viewed through a browser at URL: [IdentityIQ base URL]/doc/javadoc/.
HTML Escaping
Note
HTML escaping is applied to HTML that is passed into a HTML email template using a variable.
HTML escaping, or encoding, is the process of replacing any HTML reserved characters in a string, such as <: or >:, with their non-interpretable HTML entity representation. This is done to prevent unvalidated data from being included in a template and distributed through an email.
For example this:
<a href="http://www.sailpoint.com" onclick="steal_passwords();return false">Click here to
approve</a>
<a href=”http://www.sailpoint.com”onclick=”steal_passwords();return
false”>Click here to approve</a>
HTML content that is part of the template body itself is not escaped, it is rendered by any HTML email client correctly.
For security reasons, all HTML strings passed into a HTML email template using variables have their HTML escaped.
Refactoring HTML Email Templates
If you have already defined email templates to use HTML supplied by variables, they must be refactored so that all HMTL is contained within the email template itself.
For example if you have the following email template:
<html>
<body>
$header
You have a pending work item that requires attention. Work Item: $workItemDescription
--------------------------------------------------------------------------------
$!comment
</body>
</html>
Where the $header is a variable containing HTML, such as <h2>Hello, $identityname</h2>, the HTML part of the string needs to be moved directly into the email template.
For example:
<html>
<body>
<h2>Hello, $identityName</h2>
You have a pending work item that requires attention. Work Item: $workItemDescription
--------------------------------------------------------------------------------
$!comment
</body>
</html>
Where $header is an $identityName variable which contains only the name.
$(…) Variable Syntax
The $(…) variable syntax pre-dates the use of Velocity VTL templates. If you have templates that contain the $(…) variable syntax, two changes in IdentityIQ might affect you:
HTML passed to a template using $(…) syntax is escaped just like VTL.
VTL and the $(…) syntax can not coexist in the same template. If the $(…) syntax is found anywhere in the template, the entire template string is passed to IdentityIQ's non-Velocity resolver and any VTL scripting code or velocity reference variables are not be processed. SailPoint-provided context variables are still resolved as expected.
For example, if your email template contains VTL as follows:
#if (
!$workItem.get("fromSource").equalsIgnoreCase("QuickLink"))
$workflow.get("launcherDisplayName")
#else
$(managerName)
#end
The VTL if/else statements is not processed because of the existence of $(managerName), but instead rendered as literal strings.
In VTL, you should change any of the $(variableName) syntax to use the VTL $variableName syntax.
Conditional Statements
Conditional statements can be used to determine whether text should be included in the message or to choose alternate wording based on attribute values.
Whole paragraphs can be included or omitted based on conditional tests.
#if ($remindersRemaining > 0)
This work item will escalate after $remindersRemaining more reminder(s).
#end
Additionally, parts of a paragraph or sentence can be suppressed or altered based on conditional evaluations. In this example, if $requester is null, the portion of the text "requested by $requester.displayableName, and" is suppressed. Specifying the #if statement in-line with the rest of the text prevents extra line breaks in the middle of the sentence in the resulting email message.
<Body>This is your $ordinalNumReminders reminder that the work item $workItemName #if($requester)requested by $requester.displayableName, and #{end}created on
...
Attribute values can also be evaluated to determine which of multiple text selections to include in a message:
#if ( $launcher != $identityName )
$launcher requested the following password changes be made to your account(s).
#else
The following password changes were made to your account(s) at your request.
#end
Method Calls
Methods within object arguments can be accessed directly through the method reference syntax.
#if($expiration)
#if($expiration.getTime() > $nowDate.getTime())
is due on $spTools.formatDate($expiration,3,1).
#{else}
was due on $spTools.formatDate($expiration,3,1).
#{end}
#{else}
was due on $spTools.formatDate($oldDueDate,3,1).
#{end}
#if ( $item.level )
Priority: $item.level
#else
Priority: Normal
#end
This block checks to see if $expiration is null. If it is not null, it prints "is due on…" or "was due on…" based on whether the expiration date/time is before or after the current date/time. If $expiration is null, this is an older expired work Item so the message uses the $oldDueDate field as work item due date in the message. It also checks to see if the priority was set in. If the $item.level is null, the priority is set to Normal.
Throughout this example, the printed date/time is formatted with the spTools.formatDate() method. The spTools reference variable is discussed in the next section.
Note
This example was altered from its original format in the default Work Item Reminder email template. In the template, this #if statement was specified in-line to prevent unwanted line breaks in the message. Line breaks have been inserted here for readability and should not be included in the message body unless they are desired in the resulting message text.
SPTools Function Library
Immediately before any template is submitted for evaluation by the Velocity engine, the spTools argument is added to the VelocityContext so the template can access its methods. SPTools is a function library that contains a few localization utility methods to help with message formatting – primarily date formatting. The methods available within spTools are listed below:
String formatDate(Object date)
Formats the passed-in date object to a string representation using the IIQ default date and time styles (both the java.util.dateformat SHORT formats), formatted per the norms of the server's default locale and timezone
String formatDate(Object date, Integer dateStyle, Integer timeStyle)
Formats the passed-in date object to a string representation using the specified date and time styles, formatted per the norms of the server's default locale and timezone
Note
The styles are represented by constant values:
SHORT = 3
MEDIUM = 2
LONG = 1
FULL = 0
dateStyle and timeStyle correspond to java.text.DateFormat constants. See the Sun Javadocs for details
String formatDate(Object date, String formatString)
Formats the date according to the specified formatString (uses the java.text.SimpleDateFormat method)
String getMessage(String key)
Returns an internationalized message from the message catalog corresponding to the provided key
String escapeHtml(String string)
Converts HTML special characters to their entity equivalents
Example:
escapeHtml('<div class="article">This is an article</div>')
Returns:
<div class="article">This is an article</div>
String formatURL(String)
Reformats a URL to a format that can be used in contexts external to IdentityIQ such as an email. This is necessary since not all browsers will re-apply the fragment identifier (named anchor portion of the URL) after getting redirected though the login process.
For example, it can reformat
/ui/index.jsf#/myApprovals
to
<serverRootPath>/ui/rest/redirect?rp1=/ui/index.jsf&rp2=myApprovals
It also handles query parameters, for example reformatting
/ui/index.jsf?a=foo&b=bar#/myApprovals
to
<serverRootPath>/ui/rest/redirect?a=foo&b=bar&rp1=/ui/index.jsf&rp2=myApprovals
All URLs within emails should go through this reformat.
The '<serverRootPath>' added to the URL is contained in the serverRootPath entry in the SystemConfiguration object.
In the out-of-the-box email templates, the most commonly used method from this library is the formatDate() method that takes a date object and two integers as arguments:
$spTools.formatDate($expiration,3,1)
After the reference shown above is resolved by Velocity, the date/time value in the expiration argument is printed in the email message in MM/dd/yy hhssPM format (or the appropriate equivalent for the server's locale).
CDATA Blocks
When any component of the email message (body, subject, cc, etc.) contains characters that are illegal in XML text (e.g. characters like < and & that are interpreted by the parser as the start of an XML element or character entity, respectively), the entire component must be expressed in a CDATA block to prevent it from being parsed. For example, any message body written as HTML must be contained within a CDATA section.
<Body><![CDATA[
<html>
<body style="background:#FFF;margin:0;padding:0;text-align:left;">
<p style="margin:20px 0 0;padding:0;color:#333;font:bold 10pt
Arial;line-height:15pt;">$!{workItem.owner.firstname},</p>
<p style="margin:0 0 20px;padding:0;color:#333;font:normal 10pt
Arial;line-height:15pt;">As part of our periodic compliance efforts, you are
responsible for certifying the access your employees have to enterprise applications.
</p>
<p style="margin:0;padding:0;color:#333;font:normal 10pt Arial;line-height:15pt;">A
specific access certification is named <b>$!{workItemName}</b> has been created for
you, and is due on <strong>$spTools.formatDate(
$certification.expiration,3,3)</strong>. <a
href="http://localhost:8080/iiq/manage/certification/entityList.jsf?certificationId
=$!{certification.id}">Click here to get started on this task.</a></p>
</body>
</html>
]]> </Body>
The marked up text can then be passed to Velocity for variable substitution and can be rendered as an HTML email message.