[SalesForce] Can’t set toAddresses on email when templateId defined

Question

Did something change recently with the SingleEmail methods that prevents using setToAddresses() when a template is used?

Background

I need to send an email to a user based and pass in the related record. However, you can't set targetObjectId to a user id if whatId has been set.

There used to be two known workarounds. First, to create a contact with the desired email address and use that for targetObjectId. Second, don't set targetObjectId and instead set toAddresses to the target user's email (see this answer). However, the docs seem to state this is no longer possible.

setToAddresses(String[]) Optional. A list of email addresses to which
you are sending the email. The maximum number of email addresses
allowed is 100. This argument is allowed only when a template is not
used.
via apex docs

I'm really hoping to avoid creating a dummy contact for this since we have a lot of triggers on that object. Am I taking crazy pills and it was never actually possible to use toAddresses with templateId or is this a recent change? If it's a recent change is there any other workaround?

Desired Usage

public static void send(Id recordId, Id templateId, String toAddress) {
    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    email.setWhatId(recordId);
    email.setTemplateId(templateId);
    email.setToAddresses(new String[] { toAddress });
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
}

Resulting Error Message

System.EmailException: SendEmail failed. First exception on row 0;
first error: REQUIRED_FIELD_MISSING, Missing targetObjectId with
template: []

Best Answer

Using Newly introduced method setTreatTargetObjectAsRecipient() in Winter 16, you can send email message to any email address.

    Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
    email.setWhatId(recordId);
    email.setTemplateId(templateId);
    email.setToAddresses(new String[] { toAddress });   

    //Set current user as target object 
    email.settargetObjectId(UserInfo.getUserId()); 
    email.setsaveAsActivity(false);

    //This method would make sure email will not be sent to user
    email.setTreatTargetObjectAsRecipient(false); 
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
Related Topic