Attach Dynamic Attachment to Salesforce Email Template

Sometimes we need to attach dynamic attachment to a Salesforce email template. So, following are the steps to create dynamic attachments for an email template.

  • Create a Visualforce Page and an apex controller to generate a PDF document.
  • Create a Visualforce Page Component and an apex controller for Visualforce Email Template.

VF Page for PDF(ProposalPDF):

<apex:page controller="ProposalPDFController" applyHtmlTag="false" applyBodyTag="false" showHeader="false" sidebar="false">
    <html>
        Proposal Name:  <apex:outputText value="{!Opp.Name}" escape="false"/><br/>
        Proposal For:  <apex:outputText value="{!Opp.Account.Name}" escape="false"/><br/>
        Proposal Amount:  <apex:outputText value="{!Opp.Amount}" escape="false"/><br/>
    </html>
</apex:page>

Apex Controller for PDF VF Page(ProposalPDFController):

public class ProposalPDFController {
    
    public String OpportunityId {
        get{
            if(OpportunityId == null && ApexPages.currentPage().getParameters().get('id') != null){
                OpportunityId = ApexPages.currentPage().getParameters().get('id');
            }
            return OpportunityId;
        }
        set;
    }
    
    public Opportunity Opp {
        get{
            return [SELECT Id, Name, Account.Name, Amount  FROM Opportunity WHERE Id = :OpportunityId LIMIT 1];
        }
        set;
    }
}

VF Page Component for VF Page Email Template(ProposalAttachment):

<apex:component controller="ProposalAttachmentController" access="global">
    <apex:attribute name="oppId" description="Opportunity Record Id" assignTo="{!opportunityId}" type="Id" />
    <apex:outputText value="{!PagePDFContent}" escape="false" />
</apex:component>

Apex Controller for VF Page Component(ProposalAttachmentController):

global class ProposalAttachmentController {
    
    global String PagePDFContent{ get; set; }
    global String opportunityId{ 
        get; 
        set {
            UpdatePDFContent(value);
        } 
    }
    
    public void UpdatePDFContent(String opportunityId) {
        try {
            PageReference pageRef = Page.ProposalPDF;
            pageRef.getParameters().put('id', opportunityId);
            PagePDFContent = pageRef.getContent().toString().replace('<html style="display:none !important;">', '<html>');
        }catch(System.Exception ex){}
    }
}

Note: The Email Template can be used for Workflow Rule, Process Builder, Approval Process, Flow etc.