Sending Emails in Salesforce to Non-Contacts Using Apex

Emailing to Non-Contacts

Why won’t the following code work? (Assume that there is an active email template with the given name.)

List<Messaging.SingleEmailMessage> lstMsgs =
new List<Messaging.SingleEmailMessage>();
Messaging.SingleEmailMessage msg =
new Messaging.SingleEmailMessage();
msg.setTemplateId( [select id from EmailTemplate
where DeveloperName='My_Email_Template'].id );
msg.setWhatId( [select id from Account limit 1].id );
msg.setTargetObjectId(UserInfo.getUserId());
lstMsgs.add(msg);
Messaging.sendEmail(lstMsgs);

Did you find the problem? If not, try running it yourself, substituting your own Email Template name. You’ll get this error:
WhatID is not available for sending emails to UserIds

The problem is that if you specify a TargetObjectId (the record from which the Email Template will probably draw most of its merge fields), Apex’s Messaging classes require you to specify a WhatID that refers to a Contact, not a User.

But what if you don’t want to send your email to a Contact? What if you want to use an Email Template with a TargetObjectId to send an email to a User? Or to an email address that isn’t associated with a Contact or a User? Are you out of luck?

With a little magical Apex hand-waving, you can indeed send your email just the way you want to.
Consider this code:

1 // Pick a dummy Contact
2 Contact c = [select id, Email from Contact where email <> null limit 1];
3
4 // Construct the list of emails we want to send
5 List<Messaging.SingleEmailMessage> lstMsgs = new List<Messaging.SingleEmailMessage>();
6
7 Messaging.SingleEmailMessage msg = new Messaging.SingleEmailMessage();
8 msg.setTemplateId( [select id from EmailTemplate where DeveloperName='My_Email_Template'].id );
9 msg.setWhatId( [select id from Account limit 1].id );
10 msg.setTargetObjectId(c.id);
11 msg.setToAddresses(new List<String>{'random_address@opfocus.com'});
12
13 lstMsgs.add(msg);
14
15 // Send the emails in a transaction, then roll it back
16 Savepoint sp = Database.setSavepoint();
17 Messaging.sendEmail(lstMsgs);
18 Database.rollback(sp);
19
20 // For each SingleEmailMessage that was just populated by the sendEmail() method, copy its
21 // contents to a new SingleEmailMessage. Then send those new messages.
22 List<Messaging.SingleEmailMessage> lstMsgsToSend = new List<Messaging.SingleEmailMessage>();
23 for (Messaging.SingleEmailMessage email : lstMsgs) {
24 Messaging.SingleEmailMessage emailToSend = new Messaging.SingleEmailMessage();
25 emailToSend.setToAddresses(email.getToAddresses());
26 emailToSend.setPlainTextBody(email.getPlainTextBody());
27 emailToSend.setHTMLBody(email.getHTMLBody());
28 emailToSend.setSubject(email.getSubject());
29 lstMsgsToSend.add(emailToSend);
30 }
31 Messaging.sendEmail(lstMsgsToSend);

In lines 1-14, we begin by constructing an email message using a WhatID that refers to some random 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 16-18, we set a savepoint, send the email, and then roll back the transaction. The key here is to understand that Salesforce doesn’t send an email immediately when the sendEmail method is executed. Instead, Salesforce waits until the very end of the transaction. If you roll back the transaction, Salesforce doesn’t send the email at all.

If sendEmail doesn’t actually send the email message, why bother 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. When you roll back the transaction, Salesforce retains the populated values in the Subject, Body, and other fields. So after you roll back the transaction, you can construct a new SingleEmailMessage, and copy the Subject, Body, and other values from the populated message into the new message. Your new message is able to leverage the work that the email template did, but because your new message doesn’t refer to the email template, you don’t have to provide the emailTemplateId, TargetObjectId or WhatID, and you’re no longer bound by the requirement to specify a Contact for the WhatID. You can send your email to whomever you want, leveraging a Subject and Body that were created by an Email Template.

This trick of rolling back transactions can be useful in other ways as well. Last year, I wrote about how you can create Opportunity Assignment Rules by rolling back transactions in conjunction with Lead Assignment rules. What other uses can you find for rolling back transactions?

If your team is overwhelmed or you’re looking to fast track your upcoming projects, our team of consultants is here to help. Connect with a member of our team to discuss your project, then access a deep bench of Salesforce consultants to meet your needs. Are you ready to reach for operational excellence?

MJ Kahn, SVP of Technology at OpFocus

about the author

MJ Kahn

At OpFocus, MJ architects and constructs solutions that would impress the builders of the pyramids. She solves technical puzzles that would frustrate daVinci. She leaps tall buildings (like the new Salesforce tower) in a single bound.

Well ok, maybe she doesn’t. But she does help lead an amazing team of smart, talented, and dedicated consultants who do. MJ’s job at OpFocus is provide technical leadership and guidance to OpFocus clients and team members so that, working together, we can create innovative yet practical solutions to real-world business problems within the Salesforce ecosystem.

Prior to OpFocus, MJ built an extensive background in technology and has held a variety of development, consulting, and management positions at companies like Sybase, Vignette, and Honeywell, among others. In these roles, MJ’s focus was helping companies effectively and intelligently use technology to solve business problems. An Apex and Visualforce consultant since mid-2008, MJ has worked with scores of companies to help them understand and utilize platforms like Force.com to solve business issues and also guide them in developing their own AppExchange product offerings.