7

If I need to send a huge amount of emails to 500+ contacts, each email using one of three visualforce templates (syntax needed for translations is available only on Visualforce templates, with outputPanel tags), how many single messages can I send in a transaction? Considering that the Visualforce template does not have a custom controller. It is used to just render things correctly for each contact.

I'm asking this here because the documentation isn't clear about this.

Also the same documentation states that:

You can specify up to 100 recipients for the To field and up to 25 recipients for the CC and BCC fields in each SingleEmailMessage.

So if I need to send 200 emails with the same template to 200 different people, can I create two instances of SingleEmailMessage in Apex and pass 100 contact ids to each one?

My main concern here is that I need each one of the 200 emails to render some Contact-related information correctly for its recipient. So all of them can use the same template, but the information should be different (the contact's name, for example).

Edit:

I've found that the SingleEmailMessage is not the issue here, since I can send more than a thousand messages if I want to, but if saveAsActivity is true for those messages, then I am limited to less than 100 messages because Salesforce inserts the related task one record at a time (counting towards the transaction DML limits).

I've found an idea for Salesforce to fix this here: https://success.salesforce.com/ideaView?id=0873A000000CTXwQAO

5

Messaging.SingleEmailMessage needs one contact per template in order to merge the data correctly (including Contact-specific information). The good news is that Messaging.sendEmail supports at least 10,000 emails in a list, so all you really need to do is create a list of messages and send them all at once:

Messaging.SingleEmailMessage[] messages = new Messaging.SingleEmailMessage[0];
for(Contact record: [SELECT ... FROM Contact ...]) {
    Messaging.SingleEmailMessage m = new Messaging.SingleEmailMessage();
    m.setTemplateId(templateId);
    m.setTargetObjectId(record.Id);
    messages.add(m);
}
Messaging.sendEmail(messages);

Note that there is a daily limit of 5,000 emails send to Leads and Contacts through Apex Code, so even though Messaging.sendEmail supports a much larger number of emails, you'll get a LimitException if you try to email more than 5,000 rate-limited records in a 24-hour period.

  • But a maximum of 5,000 per day per org so 10,000 in one transaction would not work. – Adrian Larson Sep 19 '17 at 13:53
  • @AdrianLarson Yes, that's the implication in my answer. Messaging.sendEmail can easily send 10,000 messages in a list (e.g. to 10,000 users), but the daily mass mail limit would cap the developer at 5,000 Lead- and Contact-related emails a day. – sfdcfox Sep 19 '17 at 13:58
  • Hmm, I missed that implication on my initial read. – Adrian Larson Sep 19 '17 at 14:01
  • But if I use a Visualforce template I get a SOQL limit exceeded exception (maybe because of the template type?). The error is thrown on the exact same line as the Messaging.sendEmails call. – Renato Oliveira Sep 19 '17 at 14:29
  • I think I figured out what is causing this. The setSaveAsActivity(true). Any idea on how to overcome this limitation? This could really be bulkified on Salesforce's end... :( – Renato Oliveira Sep 19 '17 at 14:34
2

Searching a little bit longer I've found that my issue is not related to the SingleEmailMessage class itself, but on how Salesforce handles the insertion of the email records when saveAsActivity is set to true on the message.

Salesforce does not bulkify this insertion, so when you try to send more than 100 emails and set them to be a record related to your object, the platform inserts one Task object after the other, and eventually it breaks its own DML limit of 100 transactions.

The solution is to send less than 100 emails for now, or use some kind of scheduled job to run multiple times successively, if you need to save the email on the platform. If you don't need the email stored, then you can set saveAsActivity to false.

If you are reading this and having the same issue, please vote for this idea which proposes that this insertion to be a bulkified process.

1

Outside of governor limits on CPU and heap, you should be able to send all the way up to the daily limit.

Emails Per Invocation Still Capped at 100?

You will need a separate instance of Messaging.SingleEmailMessage for each template/contact, and then you can send them all in one go:

List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
// populate with thousands of messages
Messaging.sendEmail(emails);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.