Sending Emails without a targetObject ID in Apex

November 20, 2014 Appirio

By Shailendra Shingh
techbl

The Salesforce1 platform has some robust functionality around emailing. Email templates are especially helpful in making sure emails look the way they need to look. Yet, when you implement Salesforce for enough clients, you will run into use cases for email functionality the platform can’t handle out of-the-box. For example, a company wants to email all users with a certain role from an opportunity record, and use the out of the box email templates.  Another reason to write Apex code for email is when a company wants to have a “send email” button, and fields on a page determine who receives the email.

When sending emails in apex, we must set the targetObject if we are using an email template. The Target object id must be a Contact, Lead or User record id. This becomes a problem when we want to use a template but the email is not being send to Contact, Lead or User record, but are sending the email to a particular email address. In many instances, developers create dummy contacts to achieve this, then delete the contact after email is sent. This approach works, but if the contact object requires validations then the programmer has to update dummy the contact insertion code as well. A second approach is to use find and replace after querying template body, and set the body in apex. This approach requires a lot of code and expertise in writing regex, and is not a good choice from a  maintenance point of view. This approach requires developers to update code each time an email template is updated with a new field.

With a little clever apex code, we can achieve what we want. Let’s consider this code:

1. ID whatID = 003J0000012oaXJ;

2. Contact cnt = [select id, Email from Contact where email != null limit 1];

3. List<Messaging.SingleEmailMessage> msgList= new List<Messaging.SingleEmailMessage>();

4. Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();

5. msg.setTemplateId( [select id from EmailTemplate where DeveloperName='My_EmailTemplate'].id );

6. msg.setWhatId(whatID);

7. msg.setTargetObjectId(cnt.id);

8. msg.setToAddresses(new List<String>{'shailendra.singh@appirio.com'});

9. msgList.add(msg);

// Send the emails in a transaction, then roll it back

10. Savepoint sp = Database.setSavepoint();

11. Messaging.sendEmail(msgList); // Dummy email send

12. Database.rollback(sp); // Email will not send as it is rolled Back

// Send Actual email

13. List<Messaging.SingleEmailMessage> msgListToBeSend = new

List<Messaging.SingleEmailMessage>();

14. for (Messaging.SingleEmailMessage email : msgList) {

15. Messaging.SingleEmailMessage emailToSend = new Messaging.SingleEmailMessage();

16. emailToSend.setToAddresses(email.getToAddresses());

17. emailToSend.setPlainTextBody(email.getPlainTextBody());

18. emailToSend.setHTMLBody(email.getHTMLBody());

19. emailToSend.setSubject(email.getSubject());

20. msgListToBeSend .add(emailToSend);

21. }

22. Messaging.sendEmail(msgListToBeSend);

In lines 1-9, we begin constructing an email message using a WhatID that refers to a Contact. As long as our email template doesn’t use “recipient” merge fields, it doesn’t matter which Contact we pick: we’re never going to actually send the email message to that Contact.

In lines 10-12, we set a savepoint, send the email, and then rollback the transaction. The key is to understand that Salesforce doesn’t send an email immediately when the sendEmail method is executed. Instead, Salesforce waits until the end of the transaction. So if you rollback the transaction, Salesforce doesn’t send the email at all.

If sendEmail doesn’t send the email message, why we are calling it? Because when you call sendEmail, Salesforce populates the email message’s Subject, Body, PlainTextBody, and HTMLBody based on the Email Template, TargetObjectId, and What ID. This is the key to the solution. When you roll back the transaction, Salesforce retains the populated values in the Subject, Body, and other fields. So after we rollback the transaction, we can construct a new SingleEmailMessage, and copy the Subject, Body, and other values from the populated message into the new message.

Our new message (Line no. 13-22)  does not refer to an email template, so we don’t need to provide a templateId. Instead, we copied the email body from dummy message. Because we are supplying the email body, we don’t have to worry about providing the whatId, emailTemplateID and TargetObjectID. You can send your email to whomever you want, leveraging email template contents.

Previous Article
De-Mystifying Apple's iOS Provisioning
De-Mystifying Apple's iOS Provisioning

by Brandon Jones When developing for the iOS Platform, the provisioning system is one of the biggest stumbl...

Next Article
Writing a Documentation-First API
Writing a Documentation-First API

By Neil Hastings While building our new micro-service based architecture for our Topcoder platform, we’ve l...