Salesforce, as a powerful CRM platform, offers the ability to automate many tasks, including sending emails. However, Salesforce enforces strict governor limits to ensure system stability and prevent performance bottlenecks. One common error you might encounter is the “Too Many Email Invocations” error. This error occurs when an Apex transaction attempts to send more emails than Salesforce allows.

In this article, we’ll explore the causes of this error, discuss how you can avoid it, and provide best practices and code examples to help you resolve the issue. We’ll also dive into alternative solutions for large-scale email sending and explain the most efficient methods to manage emails in Salesforce.
Too Many Email Invocations
What are Too Many Email Invocations?
The “Too Many Email in” error occurs when you exceed the platform’s limits for email Invocations-sending operations. This limit is enforced to prevent system abuse, such as excessive email traffic, which could degrade performance.
When this error happens, your code or process attempts to send more emails than allowed in a single transaction or bulk. The goal is to optimize your email-sending strategy by consolidating emails, checking invocation limits, and employing alternative methods where necessary.
How Salesforce Controls Email Sending?
Salesforce governs the number of emails you can send in various ways. These limits include:
- Daily Single Email Limits: The Enterprise Edition limit is 5,000 emails per day, while the Developer Edition is limited to 15 emails per day.
- Mass Email Limits: You can send a maximum of 500 recipients per day for Enterprise Edition users.
- Invocation Limits per Transaction: You can invoke email methods only 10 times in a single transaction.
These limits exist to safeguard Salesforce’s shared resources and to ensure the platform runs efficiently.
Simple Ways to Send Emails with Code
Checking Too Many Email Invocation Limits
public void sendEmailIfPossible() {
if (Limits.getEmailInvocations() < Limits.getLimitEmailInvocations()) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Test Email');
mail.setPlainTextBody('This is a test email.');
mail.setToAddresses(new List<String>{'example@test.com'});
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
} else {
System.debug('Email limit reached. Cannot send more emails in this transaction.');
}
}
Using Future Methods to Send Emails
public class EmailUtility {
@future
public static void sendFutureEmail(String emailAddress) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Future Email');
mail.setPlainTextBody('This email was sent using a future method.');
mail.setToAddresses(new List<String>{emailAddress});
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}
Consolidating Emails to Avoid Multiple Invocations
public void sendConsolidatedEmails(List<Contact> contacts) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Consolidated Email');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this is a consolidated email.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails);
}
}
Using Email Queue for Bulk Email Sending
public class EmailQueue {
public static void queueEmails(List<Contact> contacts) {
System.enqueueJob(new BulkEmailJob(contacts));
}
}
public class BulkEmailJob implements Queueable {
private List<Contact> contacts;
public BulkEmailJob(List<Contact> contacts) {
this.contacts = contacts;
}
public void execute(QueueableContext context) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Queued Email');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this email was sent from a queue.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
}
Messaging.sendEmail(emails);
}
}
Sending Bulk Emails Using Batch Apex
public class BulkEmailBatch implements Database.Batchable<SObject> {
public Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator([SELECT Id, FirstName, Email FROM Contact WHERE Email != null]);
}
public void execute(Database.BatchableContext BC, List<Contact> contacts) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Batch Email');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this email was sent from a batch.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
}
Messaging.sendEmail(emails);
}
public void finish(Database.BatchableContext BC) {
System.debug('Batch email job finished.');
}
}
Common Scenarios That Lead to the Error
Understanding the situations that trigger the “Too Many Email Invocations” error can help you preemptively avoid it. Some common causes include:
- Apex Triggers: Sending emails within triggers, especially in bulk updates, can easily exceed the email invocation limit.
- Batch Processing: If a batch job tries to send too many emails in a single transaction, it will hit the email limit.
- Loops in Code: Sending emails inside loops without checking limits often causes the invocation error.
- Automated Workflows: Using workflow rules or Process Builder to trigger multiple emails can result in hitting the daily or per-transaction limits.
Impacts of the Error on Your Salesforce Org
When you exceed the email invocation limit, it can have a significant impact:
- Transaction Failure: The entire transaction may fail, leading to incomplete updates and other workflow issues.
- Negative User Experience: Customers or team members may not receive critical notifications or communications, harming their experience.
- Compliance Risks: For organizations under strict communication regulations, missing emails could lead to non-compliance.
Best Practices to Avoid Too Many Email Invocations Errors
Here are some best practices to ensure you don’t run into the “Too Many Email Invocations” error:
- Consolidate Emails: Instead of sending individual emails for each update, try to group and summarize emails into fewer messages.
- Leverage Future Methods: Offload email sending to future methods or Queueable Apex to distribute the load across transactions.
- Batch Apex for Large Email Jobs: Use Batch Apex for sending large volumes of emails to spread the workload.
- Monitor Governor Limits: Continuously check email invocation limits in your Apex code to ensure you stay within the allowed range.
- Use External Email Services: If you often exceed limits, consider integrating with external email services like SendGrid or Amazon SES.
Debugging and Resolving Too Many Email Invocations
If you’ve already encountered the error, here are some steps to resolve it:
- Debug Logs: Use Salesforce’s Debug Logs and Apex Exception Emails to find where your code exceeds limits.
- Optimize Your Code: Refactor your code to move email-sending logic out of loops and into batch processes or future methods.
- Error Handling: Implement error handling with try-catch blocks to ensure that failing to send an email doesn’t stop the entire transaction.
Alternatives for Bulk Email Solutions
If your organization needs to send a large number of emails beyond Salesforce’s limits, here are alternative solutions:
- Salesforce Marketing Cloud: A robust solution for large-scale email marketing campaigns. It bypasses the standard Salesforce email limitations.
- Third-Party Email Providers: Use external email platforms like SendGrid or Amazon SES for sending large volumes of transactional or marketing emails.
- Pardot: A great solution for B2B marketing that allows advanced email segmentation, automation, and reporting while integrating seamlessly with Salesforce.
Additional Code Examples for Managing Too Many Email
To further solidify your understanding of how to avoid the “Too Many Email Invocations” error, here are more examples covering specific use cases. These examples highlight various strategies to efficiently handle email sending in Salesforce.
Using Mass Email Limits to Avoid the Invocation Error
When sending a large number of emails, you can make use of the mass email functionality provided by Salesforce. However, you need to be mindful of the recipient limits, especially in the Enterprise Edition.
public void sendMassEmail(List<Contact> contacts) {
List<String> emails = new List<String>();
for (Contact contact : contacts) {
if (emails.size() < 500) { // Salesforce mass email limit for Enterprise edition
emails.add(contact.Email);
}
}
if (!emails.isEmpty()) {
Messaging.MassEmailMessage massEmail = new Messaging.MassEmailMessage();
massEmail.setSubject('Mass Email Subject');
massEmail.setPlainTextBody('This is a mass email.');
massEmail.setToAddresses(emails);
Messaging.sendEmail(new Messaging.MassEmailMessage[] { massEmail });
}
}
This example ensures that you don’t exceed the mass email recipient limit for your edition of Salesforce. It’s essential to manage the number of recipients per email batch effectively to avoid errors.
Avoiding Email Invocation Inside Loops
Placing email-sending logic inside loops is a common mistake that can easily trigger the email invocation limit. By restructuring your code, you can avoid hitting the limit.
public void sendEmailOutsideLoop(List<Contact> contacts) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Contact Email');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this is a personalized email.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails); // Send all emails at once to avoid loop issues
}
}
Handling Email Invocation in a Trigger
When writing triggers, it’s easy to send too many emails in response to record updates. Here’s an example of handling email notifications efficiently within an Opportunity trigger:
trigger OpportunityEmailTrigger on Opportunity (after insert, after update) {
if (Trigger.isAfter) {
List<Opportunity> opps = [SELECT Id, Name, Owner.Email FROM Opportunity WHERE Id IN :Trigger.new];
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Opportunity opp : opps) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('New Opportunity Created');
mail.setPlainTextBody('A new opportunity has been created: ' + opp.Name);
mail.setToAddresses(new List<String>{opp.Owner.Email});
emails.add(mail);
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails);
}
}
}
Using Limits Class to Avoid Transaction Failures
You can use Salesforce’s Limits class to dynamically check how many emails you have already sent in a transaction, helping to prevent invocation limits from being exceeded.
public void sendEmailWithLimitCheck(List<Contact> contacts) {
Integer maxEmails = Limits.getLimitEmailInvocations();
Integer usedEmails = Limits.getEmailInvocations();
Integer availableEmails = maxEmails - usedEmails;
if (availableEmails > 0) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
if (availableEmails == 0) break;
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Email With Limit Check');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this is a limit-checked email.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
availableEmails--;
}
Messaging.sendEmail(emails);
}
}
This method ensures that the number of email invocations in your current transaction stays within Salesforce’s limits.
Trigger Email Notification for Specific Record Changes
In certain scenarios, you may want to send email notifications only when a record meets specific criteria, like when an Account exceeds a certain revenue threshold.
trigger AccountEmailNotification on Account (after update) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Account acc : Trigger.new) {
if (acc.AnnualRevenue > 1000000) { // Notify when revenue exceeds a threshold
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('High Revenue Account Update');
mail.setPlainTextBody('Account ' + acc.Name + ' has exceeded 1 million in revenue.');
mail.setToAddresses(new List<String>{acc.Owner.Email});
emails.add(mail);
}
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails);
}
}
Advanced Techniques for Handling Bulk Emails
When sending bulk emails, you often run into daily or transaction limits. Here are some advanced techniques to handle larger email volumes efficiently:
Batch Apex for Bulk Email Jobs
Using Batch Apex is an excellent method for sending large amounts of emails while staying within limits. Batch Apex allows you to process records asynchronously in chunks, thus reducing the risk of hitting transaction limits.
public void sendEmailOutsideLoop(List<Contact> contacts) {
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
for (Contact contact : contacts) {
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setSubject('Contact Email');
mail.setPlainTextBody('Dear ' + contact.FirstName + ', this is a personalized email.');
mail.setToAddresses(new List<String>{contact.Email});
emails.add(mail);
}
if (!emails.isEmpty()) {
Messaging.sendEmail(emails); // Send all emails at once to avoid loop issues
}
}
Batch Apex is a scalable solution for sending large volumes of emails and allows for flexible processing in the background.
Leveraging External Services for Email Invocations Sending
In cases where Salesforce’s native email limits are not sufficient, you can integrate Salesforce with external email services like SendGrid, Amazon SES, or MailChimp. These platforms allow you to send thousands of emails without worrying about hitting Salesforce limits.
By using APIs provided by these services, you can send large volumes of emails while maintaining Salesforce’s transactional integrity.


