Salesforce: Using basic email templates from Apex code

A few weeks ago I noticed a number of questions in the forums around how to use email templates from Apex classes. I Googled a few keywords and come up with very little. I then trawled the documentation but came up empty-handed. Eventually it was Eclipse that provided the knowledge required, and I thought I’d share it with the good ol’ developer community.

One part of the process is discovering that Salesforce stores all sorts of items as records in objects; some of them being email templates, user information and even Apex class bodies (scandalous). All you have to do is query them. The other major part is finding that the method you need is missing from the Apex documentation.

There are a number of email template types, and if you’ve found this post because you’re stuck, I’m sure you’re aware that they are:

  • Text
  • HTML
  • Custom
  • Visualforce

Each has its own application and you can make them looking very spiffy if you, or someone you know has mad design skillz. But we’re getting off-topic here. The largest difficulty I found is that the method used to associate a template with an email isn’t listed in the Apex documentation, but with the ever useful Auto-Complete capabilities of Eclipse you’ll notice a method called ‘setTemplateId’. How should we use it? It’s easy-peasy really, just like this:

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

Contact recipient = [SELECT id, firstname FROM Contact LIMIT 1];
EmailTemplate et = [SELECT id FROM EmailTemplate WHERE developerName = 'MyTemplate'];

mail.setSenderDisplayName('Your Loving Administrator');

mail.setTargetObjectId(recipient.id); // Specify who the email should be sent to.
mail.setTemplateId(et.id);

Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});

As you can see, it’s quite straight forward. Notice how there’s no need to specify the to-addresses, the subject, or the email body, they’re all pulled from the template. Nice huh?

A few other tips that I have on offer are:

  • When querying for an email template always use the ‘developerName’ field. If a power user decides to change the name of the template they’re less likely to change the unique name too, this way you have a tiny bit of a safety net. Of course you should always wrap this query in an exception handler.
  • Visualforce templates can’t be used in bulk emails (don’t shoot! I’m just the messenger).
  • After you’ve created a template you need to make sure that you set it as ‘Available to Use’ (an option on the template detail page), or emails won’t be sent.

23 thoughts on “Salesforce: Using basic email templates from Apex code”

  1. I would murder a hobo for the ability to add CCs to email templates. Trying to email a group of people from apex redefined the meaning of pain for me.

    Reply
    • Yeah things like email and async calls are still a bit young on the platform, are there any Ideas around this stuff? Let’s vote em up.

      Reply
      • I am working on comparing an account owner list of id’s with a list of id’s from the AccountTeamMember object to ensure when sending out the email notifications to the accountteammembers on updates to the events on an account thay belong to, I don’t send duplicates in the rare case that the owner of the account is also in fact, listed as an accoutteammember. Any ideas on how to set if statement up for this??

        Reply
  2. @Patrick you can store the Ids in a Set which is like a list but only contains unique values. That way if you do try to add a duplicate it get’s ‘thrown away’.

    Reply
  3. Wes,

    Is it possible for a Customer Portal user to send emails through this API code ?
    Am facing this problem and stumble upon your blog.
    The error I get is “FIELD_INTEGRITY_EXCEPTION, Portal user can’t own an activity” .

    Reply
    • There are some objects that Portal users can’t create and it seems activity is one of them. These are created by default when you send emails but you can turn this functionality off by calling the email class method setSaveAsActivity with a argument value of false.

      Reply
  4. Hi, I would like to check is there any apex code that allow email to directly insert to “Notes & Attachment” in the Custom Object Section?

    As currently I understand the email will be insert in “Active History”. But i would like those email to be trigger to “Noted & attachment”

    Sorry for the trouble and thanks in advance.

    Reply
  5. I just found this post and I had done all the things you say but I am getting the following error:

    INVALID_FIELD_WHEN_USING_TEMPLATE, When a template is specified the plain text body, html body, subject and charset may not be specified

    I am setting the same fields you set and no more! I’ve tried using different templates with no luck. None of the templates are VF.

    Any thoughts on my problem?

    Thanks

    Reply
  6. Hi, Wes. I am writing a email for my firm that involves couple objects:

    o2bc__Subscription__c subs = [SELECT o2bc__Account__c, Campaign__c, Discount_Start_Date__c, Discount_End_Date__c, o2bc__Discount__c, o2bc__Item__c,
    o2bc__Billing_Start_Date__c, o2bc__Next_Bill_Date__c, o2bc__Bill_Cycle__c, o2bc__Rental__c, Free_Trial_Finish_Date__c
    FROM o2bc__Subscription__c WHERE Id = :sc.Id LIMIT 1 ];

    Account a = [ SELECT Id, FirstName FROM Account WHERE Id = :subs.o2bc__Account__c LIMIT 1 ];
    Campaign cp = [ SELECT Id, Name from Campaign WHERE Id = :subs.Campaign__c LIMIT 1 ];

    Datetime cDT = System.now();
    tDay = dateFormat(cDT);
    free_Start_Date = dateFormat(subs.o2bc__Billing_Start_Date__c);
    free_End_Date = dateFormat(subs.Free_Trial_Finish_Date__c);
    next_Bill_Date = dateFormat(subs.Discount_End_Date__c);

    // check the condition if there is only one contact
    Contact c = [ SELECT Id, FirstName, Email FROM contact WHERE AccountId = :subs.o2bc__Account__c LIMIT 1];

    Credit_Card__c cd = [ SELECT CC_Last_Name__c, CC_First_Name__c, Credit_Card_Number__c, Credit_Card_Type__c,
    Expiry_Year__c, Expiry_Month__c
    FROM Credit_Card__c WHERE Account__c = :a.Id ];
    if ( cd.Credit_Card_Number__c != NULL ) {
    last4 = cd.Credit_Card_Number__c.subString(8, 12);
    }

    // looking for the price
    Campaign_Discount__c cDisc = [ SELECT c.Campaign__c, c.Item__c, c.Free_Trial_Type__c, c.Discount_Final_Price__c
    FROM Campaign_Discount__c c WHERE c.Campaign__c = :subs.Campaign__c AND c.Seq__c = ‘1’];

    Actually I am not sure why so many project involved.
    I did the code in the trigger –

    htmlInvoice =
    ‘[During your free trial, you may cancel your subscription by contacting our Customer Service Department at ‘
    + ‘1-866-321-8726 Monday through Friday from 8am-6pm, ET (note: from outside the U.S. or Canada, please call ‘
    + ‘212-321-5200). Once your free trial ends and your subscription begins, the subscription fee will not be’
    + ‘reimbursed or refunded. ‘
    + ‘When your free trial expires, your subscription will automatically convert to the following payment plan:] ‘
    + ‘Subscription Period: ‘ + subs.o2bc__Bill_Cycle__c + ”
    + ‘Paid Subscription Start Date: ‘ + next_Bill_Date + ‘ ‘ …

    But due we want build friendly user interface let force user to use them as email templates – I am not sure if you have any suggestions – due I am a new backend coder. thanks in advace.

    Apple

    Reply
  7. Im a trying to create a visualforce email template pulling in a rich text field that contains an image, when i send the email the image does not appear do you know why?

    Reply
  8. Not to resurrect a dead thread, but you can get the template ID without SOQL by just looking at the page address when you view it in the GUI (under Communication Templates | Email Templates). This saves a query and processing time.

    Reply
  9. Thanks Wes,
    It was very helpful
    Also I wanted to know how we can add user defined body to the mail template and the reciever’s mail id also is entered from the user’s side and not from the contact list already present.Just as the details asked before posting to this page.

    Reply

Leave a Comment