Using Custom Controller in Visualforce Email Template

To show some records or render customized content on a visualforce email template, we need to include a custom component in a Visualforce email template that uses the custom controller.

Here is an example of visualforce email template with list of contacts of one account record.

Apex Controller:

public class AccountEmailTemplate
{
    public Id accountId {get;set;}
    public List<Contact> getContactList()
    {
        List<Contact> conList;
        conList = [SELECT FirstName, LastName, Email, Phone FROM Contact WHERE AccountId =: accountId];
        return conList;
    }
}

Visualforce Component(ContactList):

<apex:component controller="AccountEmailTemplate" access="global">
    <apex:attribute name="AccId" type="Id" description="Id of the account" assignTo="{!accountId}"/>
    <table border = "2" cellspacing = "5">
        <tr>
            <td>First Name</td>
            <td>Last Name</td>    
            <td>Email</td>    
            <td>Phone</td>                
        </tr>
        <apex:repeat value="{!ContactList}" var="con">
            <tr>
                <td>{!con.FirstName}</td>
                <td>{!con.LastName}</td>     
                <td>{!con.Email}</td>     
                <td>{!con.Phone}</td>     
            </tr>
        </apex:repeat>        
    </table>
</apex:component> 

Visualforce Email Template:

<messaging:emailTemplate subject="List of Contacts" recipientType="User" relatedToType="Account">
    <messaging:htmlEmailBody >
        Hi,<br/>
        Below is the list of contacts for account {!relatedTo.Name}.<br/><br/>
        <!--Embedded Visualforce component here -->
        <c:ContactList AccId="{!relatedTo.Id}" /><br/><br/>
        <b>Regards,</b><br/>
        {!recipient.FirstName}
    </messaging:htmlEmailBody>
</messaging:emailTemplate>

Output: