How to Avoid Governor Limits with sendEmail in Apex

You can send emails programmatically in Salesforce Apex, but if you’re not careful you can hit the measly governor limit of 10 in no time at all. You see, although your outbound email limit is 1000 with Apex, only a total of 10 sendEmail method calls are allowed in each context.

Obviously the way to avoid this is to gather up all emails you want to send and call the sendEmail method once from your Apex context. When passing an argument to the sendEmail method it must be of type Email. However, in order for each email to be a unique, (assuming you want that), they need to be of type SingleEmailMessage. If you don’t desire uniqueness, you may use the MassEmailMessage type. These objects all belong to a native Apex class called Messaging.

Let’s go through some code to illustrate some techniques —

public void sendTheEmail( String[] bunchOfAddresses, String[] bunchOfSubjectTags, String[] bunchOfMsgBodys, Integer numberOfSeparateEmails ) {
Messaging.SingleEmailMessage [] theEmails = new List();
for( Integer i = 0; i < numberOfSeparateEmails; i++ ){
String[] toAddress = new List(); // setToAddresses will only accept a List (array)
toAddress.add(bunchOfAddresses.get(i));
String subjectTag = bunchOfSubjectTags.get(i);
String msgBody = bunchOfMsgBodys.get(i);

Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses( toAddress ); // only takes a List (array) as noted above
mail.setReplyTo( replyAddress );
mail.setSenderDisplayName('My Company Email');
mail.setSubject(subjectTag);
mail.setPlainTextBody( msgBody );

theEmails.add(mail);
}

Now let’s populate an array of Email objects with each of our SingleEmailMessage objects.
Note: you can’t just pass the full SingleEmailMessage array. You MUST add each element separately.

Messaging.Email[] allMails = new List();
for( Integer j = 0; j < theMails.size(); j++ ){
allMails.add(theMails.get(j));
}

Now we can make the sendEmail call and pass in the array of Email objects

Always good to check for errors. So we use the object SendEmailError’s methods and build a little report (String)

Messaging.SendEmailError[] errors = new List();
for( Messaging.SendEmailResult currentResult : results ) {
errors = currentResult.getErrors();
if( null != errors ) {
for( Messaging.SendEmailError currentError : errors ) {
emailErrorReport = emailErrorReport + '(' + currentError.getStatusCode() + ') ' + currentError.getMessage() + 'r' ;
}
}
}

Well that’s one way to handle the programmatic sending of email in Apex.

Hope it makes your cloud computing less cloudy ~ ~ ~

13 thoughts on “How to Avoid Governor Limits with sendEmail in Apex”

  1. Helped me get around the 1000 outbound email limit as well. I just set the TargetObjectId in each Email object of the array. No need to use MassEmail or a tempate…complete autonomy. Just what I needed. Thanks!!!

  2. Suneel Kumar Mishra

    Hi,
    Please help me for the following queries
    On button click from Account i have opened a vf page with all related contact to that Account, now on selected contact from VF page i have to send email on Button Click from Page. Initially i have used Single Email method.

    for(Contact conObj : selectContactList) {
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    mail.setTargetObjectId(conObj.id);
    mail.setWhatId(conObj.AccountId);
    mail.setUseSignature(false);
    mail.setTemplateId(templateId);
    mail.setToAddresses(new String[] {conObj.Email});
    mailList.add(mail);
    }
    Messaging.sendEmail(mailList); sending email

    In this case if mailList Contains 1000 different email address. then will salesforce send 1000 email (i am on EE).

    some folks is saying i am testing this with same email address that why it is working in case of 1000 different email address it will fail, and saying use Mass email.

    in mass email case “setTemplateId(templateId)” limit 250 is occurring. Please help me regarding this.

  3. This didn’t work for me, still getting single email limit exceeded error. Is there anything I’m missing? Sending single email message to n contacts and its ending up in SINGLE_EMAIL_LIMIT_EXCEEDED error.

  4. Farrah Bannister

    Hello Chirag,

    I discussed your post with the team and was able to get some feedback; if the issue is persisting due to the template, it may be best to work without one. Please see below.

    Best – Farrah

    They can set an HTML body or a String body, as shown in the Docs:

    • setHtmlBody(String) 
      Optional. The HTML version of the email, specified by the sender. The value is encoded according to the specification associated with the organization. You must specify a value for setTemplateIdsetHtmlBody, orsetPlainTextBody. Or, you can define both setHtmlBody and setPlainTextBody.
    • setPlainTextBody(String) 
      Optional. The text version of the email, specified by the sender. You must specify a value for setTemplateIdsetHtmlBody, or setPlainTextBody. Or, you can define both setHtmlBody and setPlainTextBody.

    Here is the link the full docs:

    https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_email_outbound_single.htm

    The only other thing is, they should also not use the call to setTagetObjectId

    So, the solution:

    Don’t call setTemplateId

    Don’t call setTagetObjectId

     

    Do call setHtmlBody or setPlainTextBody

  5. Sandeep Chaudhary

    I am getting this error : SINGLE_EMAIL_LIMIT_EXCEEDED, Failed to send email: [] while using this approach. Please help me out. Below is the code :::

    public void sendmail()
    {

    String query = ‘SELECT Id,E_mail_Id__c,Name FROM Saint__c WHERE E_mail_Id__c != null’;
    system.debug(‘Query is : ‘+query);
    List saintList = database.query(query);
    system.debug(‘saintList is :: ‘+saintList);
    List toList = new List();
    List subjectList = new List();
    List messageList = new List();
    Map IdToName = new Map();
    Map IdToEmail = new Map();
    for(Saint__c s : saintList){
    toList.add((String)s.get(‘E_mail_Id__c’));
    IdToName.put((Id)s.get(‘Id’),(String)s.get(‘Name’));
    IdToEmail.put((Id)s.get(‘Id’),(String)s.get(‘E_mail_Id__c’));
    }

    for(Id i : IdToName.keySet()){
    subjectList.add(‘Sant Nirankari Magazine Subscription’);
    String msg = ‘My text here’;
    messageList.add(msg);
    }

    system.debug(‘To list is :: ‘+toList.size());
    system.debug(‘subjectList is :: ‘+subjectList.size());
    system.debug(‘messageList is :: ‘+messageList.size());
    sendTheEmail(toList, subjectList, messageList, toList.size());

    }

    public void sendTheEmail( String[] bunchOfAddresses, String[] bunchOfSubjectTags, String[] bunchOfMsgBodys, Integer numberOfSeparateEmails ) {
    Messaging.SingleEmailMessage [] theEmails = new List();
    for( Integer i = 0; i < numberOfSeparateEmails; i++ ){
    String[] toAddress = new List(); // setToAddresses will only accept a List (array)
    toAddress.add(bunchOfAddresses.get(i));
    String subjectTag = bunchOfSubjectTags.get(i);
    String msgBody = bunchOfMsgBodys.get(i);

    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    mail.setToAddresses( toAddress ); // only takes a List (array) as noted above
    mail.setReplyTo( ‘sandeepchaudhary.er@gmail.com’ );
    mail.setSenderDisplayName(‘SNM Bangalore’);
    mail.setSubject(subjectTag);
    mail.setPlainTextBody( msgBody );

    theEmails.add(mail);
    }

    Messaging.Email[] allMails = new List();
    for( Integer j = 0; j < theEmails.size(); j++ ){
    allMails.add(theEmails.get(j));
    }

    Messaging.SendEmailResult[] results = Messaging.sendEmail( allMails );
    system.debug('results is :: '+results);
    String emailErrorReport;
    Messaging.SendEmailError[] errors = new List();
    for( Messaging.SendEmailResult currentResult : results ) {
    errors = currentResult.getErrors();
    if( null != errors ) {
    for( Messaging.SendEmailError currentError : errors ) {
    emailErrorReport = emailErrorReport + ‘(‘ + currentError.getStatusCode() + ‘) ‘ + currentError.getMessage() + ‘\r’ ;
    }
    }
    system.debug(’emailErrorReport is :: ‘+emailErrorReport);
    }

    }

  6. What a lovely approach….Saved my time and fixed the issue without raising Limits…
    @John Mills, your response helped me to fix my 1000 emails limit as well…

Leave a Comment

Your email address will not be published. Required fields are marked *