[SalesForce] Is it possible to get the email subject string before sending it

I know for a fact that it is possible to render the email context without sending it, using the Messaging class' method renderEmailTemplate. This is great for getting the message content rendered, but I'm talking about the message's subject only, not its content.

Use case is: create a case, and with it send an email to the customer (that way the email sent already has a thread Id, and Salesforce can act as an email server*). Customer wants the Case Subject field filled with the same string which is sent in the email template (tricky part here is that the subject can vary, since it is using a visualforce template).

Since I'll be using Apex anyway, I might just ask: would it be easier to create a piece of code on the case's trigger to fill this field?

* Yes, I know this isn't what cases are for.

Best Answer

You'll probably want to use Messaging.renderStoredEmailTemplate instead:

Messaging.SingleEmailMessage m =
  Messaging.renderStoredEmailTemplate(template.Id, record.ContactId, record.Id);

Note that because the ID won't be available before insert, you won't be able to get a thread ID before insert, either; you'll need to use the after-insert, before-update trick, instead:

trigger SetCaseSubject on Case (after insert, before update) {
  if(Trigger.isAfter) {
    update Trigger.new.deepClone(true, false, false);
  } else {
    EmailTemplate template = [SELECT Id FROM EmailTemplate WHERE ...].Id;
    for(Case record: Trigger.new) {
      record.Subject = Messaging.renderStoredEmailTemplate(template.Id, record.ContactId, record.Id).getSubject();
    }
  }
}

Note: If you want the subject updated only the first time, you can use the after-insert trigger to update the records. You are allowed a single recursive update after insert to perform an update, but you cannot perform an update on a record in after-update.

N.B. You will want to limit yourself from doing mass inserts if you do this; each Messaging.renderStoredEmailTemplate will use at least one query, so this falls under the "query in a loop" anti-pattern.

Related Topic