Thursday 26 May 2022

Setting up merge fields and sending emails using email template on the custom object through apex


SCENARIO

While working on one of the requirements for a Service sector project for a client based out of Atlanta, GA, there was a requirement to send an email using an email template where the related entity type was the custom object.

CHALLENGE

In SingleEmailMessage, if we set template-id (using setTemplateId), then target object id is required. setTargetObjectId() can accept contact, lead, user or person account id only. We cannot pass the custom object id in the parameter of setTargetObjectId() - reference link. Also, the custom object is not having any relationship to any of these standard objects.

APPROACH

With a little magical Apex hand-waving, we can indeed send emails using custom email templates.

The key thing we used here is Salesforce doesn't send an email immediately when the sendEmail() method is executed, instead, Salesforce waits for the very end of the transaction. If we roll back the transaction, Salesforce doesn't send the email at all.

Below is the text value of the email template having some merge fields that we want to populate automatically,

Hi {{{Sourcing__c.Full_Name__c}}},

Good afternoon, I hope you are having a great day, and that this email finds you well. 

I just wanted to reach out to follow up with you about your application for one of
our Entry-Level IT Career Opportunities. We are very interested in speaking with you.

Our initial phone call takes less than 10 minutes. You can reach me on my direct line,
{{{Sender.Phone}}} If for some reason I do not answer please leave a voice mail
and reply to this email. 

Regards,
{{{Sender.Signature}}}

Below is a code we used for sending emails,

public class SendEmailSourcing{
    
    public void sendEmailMessage(){
	// Fetching email template
        EmailTemplate emailTemplate = [SELECT Id, DeveloperName, Subject, HtmlValue, Body
                                       FROM EmailTemplate WHERE Name = '1st Call - Email' LIMIT 1];
									   
	// Picking a dummy contact where email is not null
        Contact con = [SELECT Id, Email FROM Contact WHERE email <> NULL LIMIT 1];    
        
        List<Messaging.SingleEmailmessage> emailMessages = new List<Messaging.SingleEmailMessage>();
        List<Messaging.SingleEmailmessage> emailMessagesToSend = new List<Messaging.SingleEmailMessage>();
        Messaging.SingleEmailmessage email = new Messaging.SingleEmailmessage();  
        
	// For every sourcing record, creating email message and adding it to the list of email messages
        for (Sourcing__c sourcing :  sourcingList) {                
		email = new Messaging.SingleEmailmessage();
		email.setTemplateId(emailTemplate.Id);
		email.setTargetObjectId(con.Id);
		email.setWhatId(sourcing.Id);
		email.setToAddresses(new List<String>{sourcing.Email__c});
		email.setTreatTargetObjectAsRecipient(false);
		email.setUseSignature(false);
		emailMessages.add(email);
	}       
        
	// Setting save point to rollback the transaction after sending email message
        Savepoint sp = Database.setSavepoint();
        Messaging.sendEmail(emailMessages);
        Database.rollback(sp);
        
	// Copying content of the each email message that we just sent using sendEmail() and rolled back
	// and sending these new messages
        for (Messaging.SingleEmailMessage singleEmail : emailMessages) {
		email = new Messaging.SingleEmailMessage();
		email.setToAddresses(singleEmail.getToAddresses());
		email.setPlainTextBody(singleEmail.getPlainTextBody());
		email.setHTMLBody(singleEmail.getHTMLBody());
		email.setSubject(singleEmail.getSubject());
		email.setWhatId(singleEmail.getWhatId());
		email.setUseSignature(false);
		email.setSaveAsActivity(true);
		emailMessagesToSend.add(email);
        }
		
        Messaging.sendEmail(emailMessagesToSend);  
    }
	
}

In the above code, first, we created email message for each sourcing record and added it to the list of email messages. Then trying to send email messages in a transaction that can be rolled back.

After rolling back the transaction, we are iterating through all the emails we just sent and are copying the content of those emails into another list of emails.

That newly created list is then used to send the emails.

CONCLUSION

Using Apex effectively and rolling back the transaction, we are able to set merge fields and send email messages using email templates where a related entity type is a custom object.

If you have any questions you can reach out our Salesforce Consulting team here.

No comments:

Post a Comment