Showing results for 
Show  only  | Search instead for 
Did you mean: 

Email template customization - Using velocity and loops for lifecycle manager (LCM) requester notification

Email template customization - Using velocity and loops for lifecycle manager (LCM) requester notification



Hello Sailors,

We had a requirement where we had to create a custom Requester and User Notification email template that is according to the company policy and has appropriate data for both the requester and the user. There were ways to do it and we could have either modified the LCM workflows/sub processes or directly update the email templates. We finally went with the latter approach as we did not want to customize the OOTB workflows and sub processes a lot and make them more complex as we thought that customizing email templates for the same is the better approach. I mean it depends on the architecture and the design from company to company but I hope this is helpful to all the other developers who are trying to follow the similar approach.


Whenever there is access request made from the Manage User Catalog we have configured these email templates in the LCM Provisioning workflow. We use them during notification to users and requester.


Email template sample

Below is the sample XML for the custom Email Template. Hope this makes sense and will be helpful to other Sailors if they run into similar requirement or if they need to customize the email templates.


<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE EmailTemplate PUBLIC "sailpoint.dtd" "sailpoint.dtd">

<EmailTemplate name="LCM Requester Notification - Custom">




#set ( $spctx = $spTools.class.forName("sailpoint.api.SailPointFactory").getMethod("getFactory", null).invoke(null, null).getCurrentContext() )  

#set ( $identity = $spctx.getObjectByName($spTools.class.forName("sailpoint.object.Identity"), $identityName) )

#set ( $launcherIdentity = $spctx.getObjectByName($spTools.class.forName("sailpoint.object.Identity"), $launcher) )

&lt;style type="text/css">

   .body {

    font-family: Arial;

    font-size: 13px;




&lt;img src="image URL" alt="Company Logo" width="1000" height="120">





&lt;b>To:&lt;/b> Identity Management Requester&lt;br/>

&lt;b>From:&lt;/b>Identity and Access Management System&lt;br/>

&lt;b>Re:&lt;/b> Access Request Status&lt;br/>


Hello $launcherIdentity.DisplayName,&lt;br/>

The following account changes that you have requested for $identityDisplayName, have been successfully completed.&lt;br/>

#if ( $approvalSet.items )

#set ($approvalSetScanned = [] )

#foreach ($approvalItem in $approvalSet.items)

#set($addList = [])

#set($removeList = [])

#if (!$approvalSetScanned.contains($

&lt;br/>&lt;b>Application:&lt;/b> $approvalItem.applicationName &lt;br/>

#if ( $approvalItem.nativeIdentity ) 

&lt;b>Account:&lt;/b> ($identityDisplayName), $approvalItem.nativeIdentity &lt;br/>


  #foreach ($subApprovalItem in $approvalSet.items)

#if ( !$approvalSetScanned.contains($ &amp;&amp; $approvalItem.applicationName == $subApprovalItem.applicationName)

#set ($result = $approvalSetScanned.add($

#if( $subApprovalItem.operation == "Add")


&lt;b>Added Role/Entitlement:&lt;/b> &lt;br/>


#if ( $subApprovalItem.displayValue )

#set ( $result = $addList.add($subApprovalItem.displayValue))

&lt;li>Entitlement Name/Value: $subApprovalItem.displayValue&lt;/li>&lt;br/>


#elseif( $subApprovalItem.operation == "Remove")


&lt;b>Removed Role/Entitlement:&lt;/b> &lt;br/>


#if ( $subApprovalItem.displayValue )

#set ( $result = $removeList.add($subApprovalItem.displayValue))

&lt;li>Entitlement Name: $subApprovalItem.displayValue&lt;/li> &lt;br/>

#elseif ( $subApprovalItem.csv )

#set ( $result = $removeList.add($subApprovalItem.csv))

&lt;li>Entitlement Name/Value: $subApprovalItem.csv&lt;/li> &lt;br/>










Thank you,&lt;br/>

The Identity and Access Management Team







      Email Template for notifying requesters when their employee's account(s) are modified.

      Note that in addition to the declared arguments, all workflow variables,

      Step arguments, and Approval arguments defined in the Workflow are

      also available.




      <Argument name="workflow" type="Workflow">

        <Description>The Workflow object being executed.</Description>


      <Argument name="approvalSet" type="ApprovalSet">

        <Description>The ApprovalSet object contained in the workflow.</Description>


      <Argument name="launcher" type="string">

        <Description>The name of the Identity that launched the workflow.</Description>


      <Argument name="identityDisplayName" type="string">

        <Description>The display name of the Identity that is being changed.</Description>




  <Subject>Account changes you requested for $identityDisplayName were processed</Subject>




Email send to the requester from the GMB



Sorry for bad indexing and edits on the email image.



Sumit Gupta


Just for awareness, with IdentityIQ version 8.1p3, 8.2+, you will only be allowed to use Velocity templates in the body of an EmailTemplate. It will not be allowed in the cc field, Subject, etc.

    [SECURITY] IdentityIQ now restricts class loading from within Velocity templates
    except for email bodies.


Thanks for the above information that we can not use velocity in cc and subject from IdentityIQ version 8.1p3, 8.2+

We are upgrading our IdentityIQ instance on 8.1p3 and we have some email templates where we are loading a class in Subject to clean the special characters from the user's disaplayName.

Can you please suggest how we can handle this case in EmailTempalet itself without changing the Workflow?






Version history
Revision #:
3 of 3
Last update:
‎Jul 05, 2023 02:43 PM
Updated by: