---
schema_version: "1"
id: bb939dfd3116a8e9502aca6c47c811a80aa1221a6b0b765feef2101ee303ef03
title: Using Custom Controllers within Visualforce Email Templates
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/platform/salesforce-pages-developers-guide/guides/pages/email-and-templates/pages-email-templates-with-apex.md
canonical_url: https://developer.salesforce.com/docs/platform/salesforce-pages-developers-guide/guide/pages-email-templates-with-apex.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 904e50fc7024f77d5fdb411d4484e0c19c414b6d04506705b5c935ca9360af66
products:
  - Visualforce Developer Guide
  - Platform Developer Content
---

# 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”:

<!-- otherprops: apex_code set_clipboard -->
```controller
public class findSmithAccounts {
	private final List<Account> accounts;

	public findSmithAccounts() {
		accounts = [select Name from Account where Name LIKE 'Smith_%'];
	}

	public List<Account> getSmithAccounts() {
		return accounts;
	}
}
```

Next, create a custom component named `smithAccounts` that uses this controller:

<!-- otherprops: apex_page set_clipboard -->
```markup
<apex:component controller="findSmithAccounts" access="global">
	<apex:dataTable value="{!SmithAccounts}" var="s_account">
		<apex:column>
			<apex:facet name="header">Account Name</apex:facet>
			{!s_account.Name}
		</apex:column>
	</apex:dataTable>
</apex:component>
```

**tip:** Remember that all custom components used in Visualforce email templates must have an `access` level of `global`.

Finally, create a Visualforce email template that includes the `smithAccounts` component:

<!-- otherprops: set_clipboard -->
```apex_page
<messaging:emailTemplate subject="Embedding Apex Code" recipientType="Contact" relatedToType="Opportunity">
	<messaging:htmlEmailBody>
		<p>As you requested, here's a list of all our Smith accounts:</p>
		<c:smithAccounts/>
		<p>Hope this helps with the {!relatedToType}.</p>
	</messaging:htmlEmailBody>
</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.

**note:** Sharing settings are enforced if your email templates use a standard controller. If your organization-wide default for the user object is set to Private and you need to access user information such as name and email address in your Visualforce email template, you can use a custom component or custom controller with the `without sharing` keywords.

For information about sharing for the user object, see [User Sharing and Visibility](https://help.salesforce.com/s/articleView?id=platform.security_sharing_users.htm&type=5) in *Salesforce Help*.

Debug logs don’t contain information, such as `System.debug()` messages, from component controllers used in Visualforce email templates. This limitation occurs because of the [order of execution on the Salesforce Platform](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_order_of_execution.htm). Debug logs are written when Data Manipulation Language (DML) actions are committed to the database, but emails are sent after DML actions are committed to the database. In other words, writing debug logs is on-commit logic, but sending emails is post-commit logic. Therefore, if invoked from a Visualforce email template, custom components and their controllers don’t run until after the debug log is already generated, so they don’t appear in the debug log. As a workaround, use a [try-catch block](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_exception_statements.htm) to catch errors in the custom component rendering process.

