Newer Version Available
Using Custom Controllers within Visualforce Email Templates
Visualforce email templates can leverage custom controllers to render highly customized content. To do so, include a custom component in a Visualforce email template that uses that custom controller.
For example, suppose you want to display a list of all accounts
beginning with the word “Smith” in an email template.
To do this, first write a custom controller that uses a SOSL call
to return a list of accounts that begin with “Smith”:
1public class findSmithAccounts {
2 private final List<Account> accounts;
3
4 public findSmithAccounts() {
5 accounts = [select Name from Account where Name LIKE 'Smith_%'];
6 }
7
8 public List<Account> getSmithAccounts() {
9 return accounts;
10 }
11}Next, create a custom component named smithAccounts that uses this controller:
1<apex:component controller="findSmithAccounts" access="global">
2 <apex:dataTable value="{!SmithAccounts}" var="s_account">
3 <apex:column>
4 <apex:facet name="header">Account Name</apex:facet>
5 {!s_account.Name}
6 </apex:column>
7 </apex:dataTable>
8</apex:component>Finally, create a Visualforce email template that includes the smithAccounts component:
1<messaging:emailTemplate subject="Embedding Apex Code" recipientType="Contact" relatedToType="Opportunity">
2 <messaging:htmlEmailBody>
3 <p>As you requested, here's a list of all our Smith accounts:</p>
4 <c:smithAccounts/>
5 <p>Hope this helps with the {!relatedToType}.</p>
6 </messaging:htmlEmailBody>
7</messaging:emailTemplate>Notice that although the relatedToType attribute is required by the emailTemplate component, it does not have any effect on this example. It has the value of "Opportunity" only to show that it can take an object value that is different than the object used in the custom component.