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

3 Answers 3

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.

8
  • But a maximum of 5,000 per day per org so 10,000 in one transaction would not work.
    – Adrian Larson
    Commented Sep 19, 2017 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
    Commented Sep 19, 2017 at 13:58
  • Hmm, I missed that implication on my initial read.
    – Adrian Larson
    Commented Sep 19, 2017 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. Commented Sep 19, 2017 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... :( Commented Sep 19, 2017 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);
2
  • 1
    I've found a problem with this approach, that it is if you set the saveAsActivity as true then Salesforce will consume a DML call for each message you are trying to send. There's an idea for Salesforce to fix (bulkify) this: success.salesforce.com/ideaView?id=0873A000000CTXwQAO Commented Sep 19, 2017 at 15:01
  • Woah. Never heard of that before. Interesting find!
    – Adrian Larson
    Commented Sep 19, 2017 at 15:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .