Salesforce Mass Email – How to Send and Test

On August 27, 2026
19min read
Veljko Ristić Content Manager @Mailtrap
This image is a symbolic graphic representation of the mass emails in Salesforce for an article that covers detailed tutorials on the topic

Welcome to our comprehensive guide on Salesforce mass email sending. Whether you’re a tech-savvy professional or someone new to the platform, this article has got you covered. 

We’ll explore various methods and techniques to send mass emails using Salesforce. 

Read on to learn how to send targeted marketing campaigns or important updates to your customers. This article walks you through the process step by step and uncovers various methods and features available to help you reach a large audience effortlessly. 

Note: This article is for existing Salesforce users. It assumes that you’ve already set up Salesforce, so those steps won’t be covered. 

Ready to deliver your emails?
Try Mailtrap for Free

Salesforce mass email limits

Knowing your Salesforce limits helps secure a smooth and efficient emailing experience. Here are the highlights at the time of this writing. 

  1. Daily send limit

Salesforce caps mass email at 5,000 external email addresses per day, per licensed org, counted on Greenwich Mean Time. The cap is flat. It does not change with your edition or with the number of user licenses you hold. 

Mass email and list email draw on that same 5,000. Single email has its own separate 5,000 a day, and single emails sent through the API or Apex count against that one. 

As per the Salesforce Help Center, the number counts recipients rather than messages. One email to 5,000 addresses exhausts the day just as completely as ten emails to 500 addresses each, so plan a campaign against its recipient count instead of against how many sends it takes.

One case does differ. Developer Edition orgs, and orgs still evaluating Salesforce during a trial, can send to no more than 10 external recipients per org per day across mass and list email. If you are following this tutorial in a Developer org, that is the ceiling you will meet first. 

  1. Who counts toward the limit:

Only external addresses do. You can send to your own org’s internal users, portal users included, without touching the daily cap.

Mass email also has a fixed set of possible recipients: contacts, person accounts, leads, and your org’s internal users. It will not send to an arbitrary list of addresses, which is why the tutorial below starts by building a list of Contacts or Leads. 

One more restriction is worth knowing before you design a campaign: mass email cannot be sent from a Visualforce email template. 

Taken together, that puts the practical ceiling on a Salesforce campaign at 5,000 external recipients a day, drawn from records that already exist in your org. Both figures come from the email allocations per edition page. 

Pro Tip: duplicates count. If the same external email address appears under different email marketing lists or campaigns, it is counted toward the limit each time it appears. 

  1. Data Size Limit:

Each email you send has a maximum data size limit, which includes the combined size of the email content, attachments, and merged fields. Total file attachments cannot exceed 25 MB, and that figure is the same across editions.

The max limit is the same in Lightning Experience and Salesforce Classic, but there’s a difference in the number of attachments you can include. 

  • Salesforce Classic – 10+ attachments, not exceeding 25MB
  • Lightning Experience – up to 10 attachments, not exceeding 25MB 
  1. Email Template Limitations

Salesforce caps the number of templates at 500 for all organizations under Trial or Free plans. For more information on Salesforce platform limitations with paid editions, you’ll need to reach out to Salesforce support.

Templates are capped by size as well as by count. Salesforce allows 384 KB for text, HTML and Lightning templates, and 1 MB for Visualforce templates, per its email template allocations

Bonus Tip: Deliverability Considerations

Even though you can send mass emails with Salesforce integration, it’s crucial to maintain good deliverability and avoid practices that may result in your emails being marked as spam. If you want the details, check our blog post – “Email deliverability: everything you need to know” as well as our YouTube video on keeping spam rates low as a bulk sender:

Lastly, the limitations mentioned above could be subject to change, and it’s advisable to refer to the official Salesforce documentation for the most up-to-date information regarding mass email limits.

One more thing worth saying about that ceiling: it is Salesforce’s, not the internet’s. If 5,000 a day is the constraint on your campaigns rather than a comfortable margin, the usual answer is to stop sending through Salesforce and route through a dedicated provider instead. Mailtrap Email API/SMTP carries two streams, one for transactional email and one for bulk, so a password reset and a campaign do not share a reputation. We cover that setup near the end of this article.

How to preview a mass email inside Salesforce before sending

The section above is what makes mass email different from single email. One bad single send costs you one message and one apology. One bad mass send costs you up to 5,000 of them, all at once, to people who are on your Contacts and Leads because they matter.

Salesforce will not show you that message before it goes. You can preview a template in the template editor, but that is not the object that leaves the org. Merge fields have not resolved, the rendered HTML is not final, and nothing has passed through the relay yet. An Apex test class does not help either: it checks that your code ran, not what it produced.

Beyond confirming the thing works at all, you will want to:

  • Determine how much different mailbox providers support your HTML and CSS templates. 
  • Check the spam score before the campaign goes out, not after.
  • Debug an email notification in staging without risking your sender’s reputation.
  • Fully automate test flows and scenarios.
  • Minimize the chance to experience a lot of bounces. 

Mailtrap Email Sandbox for Salesforce closes that gap from inside the org. It is a managed package on the AppExchange. Turn Testing Mode on and outbound email from Salesforce is routed to a Mailtrap sandbox instead of your Contacts and Leads. Run the mass send you were about to run for real, then open what was captured: the rendered HTML across clients, the headers, the merge fields as they actually resolved, and the spam score.

Nothing reaches a recipient, and nothing touches your sending reputation, because nothing leaves Mailtrap Email Sandbox. For a full walkthrough of testing Salesforce email this way, see our step-by-step guide.

Mailtrap’s Email Sandbox for Salesforce setup guide walks through the connection screen by screen. In short, it is a one-time admin job: install Mailtrap Email Sandbox for Salesforce from the AppExchange listing, assign the permission set, configure a Named Credential, then connect your Mailtrap API token and choose which Mailtrap sandbox to route into. After that, testing a campaign is two steps for whoever is sending it: turn Testing Mode on, then send your mass email exactly as you normally would and read it in the Mailtrap sandbox. Turn the toggle back off and Salesforce returns to delivering for real. Two things to plan for:

  • Testing Mode is org wide. While it is on, every outbound email from that org goes to the Mailtrap sandbox, not only the campaign you are testing. Turn it on deliberately, and turn it off when you are done.
  • Turning it off does not release what was captured while it was on. Those messages stay in the sandbox. If a send was meant to be real, run it again after switching off.

If you already send through Mailtrap Email API/SMTP, your relay configuration stays as it is. Just install the package into a Salesforce sandbox org first rather than straight into production.

It works with Sales Cloud, Service Cloud, and platform email, which covers both the List Email path and the Batch Apex path described below. It is free to use with the Mailtrap Free plan, which covers 50 test emails a month, one sandbox, and one email every 10 seconds, and does not support multiple recipients on a single email — worth knowing before you point a 500-contact batch at it. Connecting Salesforce to a paid Mailtrap plan requires the paid add-on.

How to send mass emails in Salesforce?

Here, we’ll talk about sending mass emails in Salesforce Classic, so it’s more geared to legacy users (those who began using Salesforce prior to 2018 but still haven’t switched). However, we also cover Lightning Experience later in the article. 

Note: Make sure to enable mass email with your Salesforce implementation. If that’s not done, you’re likely to get a message similar to the one below. 

System.EmailException: SendEmail failed. First exception on row 0; first error: NO_MASS_MAIL_PERMISSION, Single email is not enabled for your organization or profile.: []

Create a mass mailing list of Contacts or Leads

  1. Navigate to Contacts or Leads

Click the Contacts or Leads tab, depending on the type of recipients you want to include in your mass email.

Salesforce contacts or leads menu
Source: Salesforce support

Scroll down to the Tools section, and click Mass Email Contacts

Salesforce tools section
Source: Salesforce support
  1. Follow the Mass Email tool wizard

After clicking Mass Email Contacts, you enter a four-step process to set up and customize your mass email campaigns. 

Salesforce recipient selection menu
Source: Salesforce support

First, you need to choose the recipients for the campaign. Then, choose a View from the drop-down menu, or click Create New View. For the purposes of this tutorial, we’ll choose the latter. 

Salesforce create new view menu
Source: Salesforce support

Next, add the View name, and use filters, such as specific fields, campaign membership, or custom criteria, to narrow down your target audience.

Make sure to leverage specific Salesforce customization options and select filters and criteria only for the mass email leads you’d like to contact. 

Salesforce offers quite a few filtration options and allows you to choose fields to display and filter by specific fields. That allows you to create a mass email list, zeroing in only on the user cohort you wish to contact. 

Also, you can change the visibility of your campaign under Step 4. 

Salesforce restrict visibility options
Source: Salesforce support
  1. Save the Mailing List:

Once you have defined your criteria, save the mailing list. Upon clicking the button, you’ll see the filtered list of recipients. You can add or remove recipients by checking or unchecking the box in front of their names. 

Salesforce mailing list selection
Source: Salesforce support

Reminder: The number of recipients per single email varies based on the Salesforce edition you use. 

  1. Choose an email template

After saving the list, you move to Step 2 of Mass Email with Salesforce. Here, you choose the email template. Keep in mind that you can’t create a new template at this step. 

Salesforce template selection
Source: Salesforce support
  1. Confirm your choice and send

Step 3 gives you the option to BCC an email copy to yourself, you can create a custom Mass Email Name, and send it immediately, or schedule the campaign. 

A scheduled email has a “pending” status until sent, and you can cancel it anytime prior to the due date/time. 

Salesforce review and confirm menu
Source: Salesforce support

Should you choose to hit the Send button, your email gets sent immediately, and you’ll get the confirmation window. 

Salesforce complete successful setup message
Source: Salesforce support
  1. Check status and manage

To see the status of your emails and manage campaigns, you need to do the following. 

  1. Click your account name in the upper right section and choose My Settings
  2. Select Email in the side menu, then click Mass Email
Salesforce check status of mass emails
Source: Salesforce support
  1.  Check the list of all your campaigns per the selected View.  This is also where you can cancel pending campaigns. 

Sending bulk emails in Lightning Experience

Overall, the processes and functionalities are mostly consistent across Salesforce Classic and its revamped sibling. Though, we should stress that Salesforce Lightning is more feature-rich, particularly in the area of data management, analytics, and marketing automation. And sending bulk emails in Lightning Experience is faster and more user-friendly.

However, we won’t focus on features comparison here. Instead, we’ll show you the most effective way to send mass emails and highlight any significant differences, if necessary. 

  1. Create an email template

Click the App Launcher (nine colorful dots) in the upper left corner of the screen, type ‘Email Templates’, and hit enter.  

Salesforce Lightning navigate to Email Templates
Source: Salesforce Support YouTube

Click the New Email Template button, and create your template. Make sure to include the subject, message body, and any merge fields or templates you wish to utilize, then Save it. 

Salesforce Lightning new email template popup
Source: Salesforce Support YouTube

Note: You don’t have to start by creating a template, you can do it later, or select one of the existing templates. 

  1. Navigate to Send List Email

In Lightning Experience, the feature is actually called Send List Email, instead of  Mass Email. And it appears under the Contacts, Leads, or Campaign Member view. And the steps are largely the same regardless of the method you choose. 

Salesforce Lightning All Contacts menu
Source: Salesforce Support YouTube

Click Send List Email and, under New List View, type List Name and List API Name into the designated fields. Then, choose ‘view permissions’ and click Save

Salesforce Lightning New List View menu
Source: Salesforce Support YouTube
  1. Select the Recipients

Hover over the Filter by Owner box and choose the contacts to send bulk email to. 

Salesforce Lightning filter contacts options
Source: Salesforce Support YouTube

Proceed to Add Filter and segment your recipients based on the given Field, Operator, and Value criteria. 

Salesforce Lightning adding filters
Source: Salesforce Support YouTube

Depending on your requirements, you can opt to send the email to specific campaign members, contacts, or leads from a report, or custom lists. Plus, you can use the Add Filter Logic option to give your list another dimension. 

  1. Review and Send

Before sending the email, take a moment to review the recipient list, email content, and any attached files. Ensure everything is accurate and aligns with your intended communication. 

Afterward, click the Send List Email button, then the Insert, create, or update template icon. Insert the template you created in the first step; here you can also add merged fields by clicking on the ‘braces’ icon. 

Salesforce Lightning Send List Email popup
Source: Salesforce Support YouTube

Once you confirm all’s well and you’re sending to the right recipients, hit Send, and your campaign will be deployed. 

How to send mass email through Batch Apex in Salesforce

In addition to the built-in Mass Email or Send List Email functionality, Salesforce provides Apex, a versatile object-oriented language, similar to Java. 

By leveraging Apex, you can automate the process of sending bulk emails, enabling you to handle larger volumes of email communications. 

Let’s explore how you can send mass emails through Apex in Salesforce.

  1. Import statements and create an Apex class:

Begin by importing statements and creating an Apex class that implements the ‘Batchable’ interface. This class will define the logic and behavior for sending the mass email.

Here are the import statements. 

import Database;
import Messaging;

Note: Importing Database and Messaging is optional. 

And you define the class using the following line. 

public class MassEmailBatch implements Database.Batchable<sObject> {

This declares a class named MassEmailBatch that implements the Database.Batchable<sObject> interface. It signifies that this class can be used as a batch job for processing records.

  1. Implement the Start, Execute, and Finish Methods

In the Apex class, implement the Start method, which retrieves the collection of records to process (your recipients, in this particular case). This can be based on criteria or queries.

public Database.QueryLocator start(Database.BatchableContext context) {
    String query = 'SELECT Email, Name FROM Contact WHERE Email IN (\'fd547125b4-5ea78e@inbox.mailtrap.io\')'; //SELECT Id, Email, Name FROM Contact WHERE <your_criteria_here>
    return Database.getQueryLocator(query);
}

To stress, the start method is required for a batch job and specifies the initial step of the batch process. It returns a Database.QueryLocator object that defines the records to be processed. 

In this case, the method queries the Contact records based on specific criteria and returns a query locator for those records.

Reminder: Don’t forget to specify the criteria under <your_criteria_here>

That out of the way, you can implement the Execute method, where the script iterates through the collection of records and constructs personalized email messages using Apex Email Messaging classes.

public void execute(Database.BatchableContext context, List<sObject> scope) {
    List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

    for (sObject record : scope) {
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setSubject('Your Subject Here');
        email.setPlainTextBody('Hello,\n' + String.valueOf(record.get('Name')));
        email.setToAddresses(new String[] { (String) record.get('Email') });

        emails.add(email);
    }

    Messaging.SendEmailResult[] results = Messaging.sendEmail(emails);

    for (Messaging.SendEmailResult result : results) {
        if (result.isSuccess()) {
            // Email sent successfully
            System.debug('Email sent successfully');
        } else {
            // Handle any errors or exceptions
            System.debug('Error sending email: ' + result.getErrors()[0].getMessage());
        }
    }
}

This is where the actual record processing takes place. The script receives a batch of records (a scope) to process. In our example, it iterates through each record and constructs a personalized email message using the Messaging.SingleEmailMessage class. 

The script then sets the email subject, plain text body, and recipient’s email address based on the record’s data.

The constructed email messages are added to the email list. After all the records are processed, the Messaging.sendEmail method is used to send the batch of email messages. The Messaging.SendEmailResult array contains the results of the email-sending operation, which are then processed to check for any errors or exceptions.

Lastly, you’ll need to implement the Finish method, which handles any necessary cleanup tasks or post-processing actions.

public void finish(Database.BatchableContext context) {
    // Perform any necessary cleanup tasks or post-processing actions
}

For your reference, here’s the full script. 

import Database;
import Messaging;

public class MassEmailBatch implements Database.Batchable<sObject> {

    public Database.QueryLocator start(Database.BatchableContext context) {
        // Retrieve the collection of records to process based on specific criteria or queries
        String query = 'SELECT Email, Name FROM Contact WHERE Email IN (\'fd547125b4-5ea78e@inbox.mailtrap.io\')'; //SELECT Id, Email, Name FROM Contact WHERE <your_criteria_here>
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext context, List<sObject> scope) {
        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

        // Iterate through the collection of records and construct personalized email messages
        for (sObject record : scope) {
            // Construct the email message using Apex Email Messaging classes
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setSubject('Your Subject Here');
            email.setPlainTextBody('Hello, ' + String.valueOf(record.get('Name')));
            email.setToAddresses(new String[] { (String) record.get('Email') });

            emails.add(email);
        }

        // Send the batch of email messages
        Messaging.SendEmailResult[] results = Messaging.sendEmail(emails);

        // Process the results if needed
        for (Messaging.SendEmailResult result : results) {
            if (result.isSuccess()) {
                // Email sent successfully
                System.debug('Email sent successfully');
            } else {
                // Handle any errors or exceptions
                System.debug('Error sending email: ' + result.getErrors()[0].getMessage());
            }
        }
    }

    public void finish(Database.BatchableContext context) {
        // Perform any necessary cleanup tasks or post-processing actions
    }
}
  1. Send with email template

Create and customize the template according to your needs and include any merge fields as required. You can do all that within the Salesforce interface, but make sure to save the template ID to reference it in the code.  

Now, we’d need to rework the ‘execute’ method so it references a template, here’s the snippet. 

public class MassEmailBatchWithTemplate implements Database.Batchable<sObject> {

    public static final String EMAIL_TEMPLATE_NAME = 'MyTemplate';

    public Database.QueryLocator start(Database.BatchableContext context) {
        // Retrieve the collection of records to process based on specific criteria or queries
        String query = 'SELECT Email, Name FROM Contact WHERE Email IN (\'fd547125b4-5ea78e@inbox.mailtrap.io\')'; //SELECT Id, Email, Name FROM Contact WHERE <your_criteria_here>
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext context, List<sObject> scope) {
        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

        // Get the email template
        EmailTemplate emailTemplate = [
            SELECT Id, Subject, Body, HtmlValue
            FROM EmailTemplate
            WHERE Name = :EMAIL_TEMPLATE_NAME
            LIMIT 1
        ];

        // Iterate through the collection of records and construct personalized email messages
        for (sObject record : scope) {
            // Construct the email message using Apex Email Messaging classes
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

            // Set the email template ID
            email.setTemplateId(emailTemplate.Id);
            // Set the email template Subject
            email.setSubject(emailTemplate.Subject);
            // Set the email html Body
            email.setHtmlBody(emailTemplate.HtmlValue);
            email.setToAddresses(new String[] { (String) record.get('Email') });

            // Set the target object ID
            email.setTargetObjectId((Id) record.get('Id'));

            emails.add(email);
        }
    }
}

Here’s what we did:

  1. Added the line email.setTemplateId('<your_template_id_here>'); to set the ID of the email template you want to use. Replace <your_template_id_here> with the actual ID of your email template.
  2. Added the line email.setTargetObjectId((Id) record.get('Id')); to set the ID of the recipient object. This can be the ID of the contact, lead, or user to whom you want to send the email.

Check the full reworked script. 

import Database;
import Messaging;

public class MassEmailBatchWithTemplate implements Database.Batchable<sObject> {

    public static final String EMAIL_TEMPLATE_NAME = 'MyTemplate';

    public Database.QueryLocator start(Database.BatchableContext context) {
        // Retrieve the collection of records to process based on specific criteria or queries
        String query = 'SELECT Email, Name FROM Contact WHERE Email IN (\'fd547125b4-5ea78e@inbox.mailtrap.io\')'; //SELECT Id, Email, Name FROM Contact WHERE <your_criteria_here>
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext context, List<sObject> scope) {
        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

        // Get the email template
        EmailTemplate emailTemplate = [
            SELECT Id, Subject, Body, HtmlValue
            FROM EmailTemplate
            WHERE Name = :EMAIL_TEMPLATE_NAME
            LIMIT 1
        ];

        // Iterate through the collection of records and construct personalized email messages
        for (sObject record : scope) {
            // Construct the email message using Apex Email Messaging classes
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

            // Set the email template ID
            email.setTemplateId(emailTemplate.Id);
            // Set the email template Subject
            email.setSubject(emailTemplate.Subject);
            // Set the email HTML Body
            email.setHtmlBody(emailTemplate.HtmlValue);
            email.setToAddresses(new String[] { (String) record.get('Email') });

            // Set the target object ID
            email.setTargetObjectId((Id) record.get('Id'));

            emails.add(email);
        }

        // Send the batch of email messages
        Messaging.SendEmailResult[] results = Messaging.sendEmail(emails);

        // Process the results if needed
        for (Messaging.SendEmailResult result : results) {
            if (result.isSuccess()) {
                // Email sent successfully
                System.debug('Email sent successfully');
            } else {
                // Handle any errors or exceptions
                System.debug('Error sending email: ' + result.getErrors()[0].getMessage());
            }
        }
    }

    public void finish(Database.BatchableContext context) {
        // Perform any necessary cleanup tasks or post-processing actions
    }
}
  1. Schedule and execute an Apex batch

To schedule and execute a batch, and then send mass email from custom object, we’ll need to go back to the script above and add yet another layer of functionality. 

import Database;
import Messaging;
import System;

public class MassEmailBatch implements Database.Batchable<sObject>, Database.AllowsCallouts, Schedulable {

    public Database.QueryLocator start(Database.BatchableContext context) {
        // Retrieve the collection of records to process based on specific criteria or queries
        String query = 'SELECT Email, Name FROM Contact WHERE Email IN (\'fd547125b4-5ea78e@inbox.mailtrap.io\')'; //SELECT Id, Email, Name FROM Contact WHERE <your_criteria_here>
        return Database.getQueryLocator(query);
    }

    public void execute(Database.BatchableContext context, List<sObject> scope) {
        List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

        // Get the email template
        EmailTemplate emailTemplate = [
            SELECT Id, Subject, Body, HtmlValue
            FROM EmailTemplate
            WHERE Name = :EMAIL_TEMPLATE_NAME
            LIMIT 1
        ];

        // Iterate through the collection of records and construct personalized email messages
        for (sObject record : scope) {
            // Construct the email message using Apex Email Messaging classes
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

            // Set the email template ID
            email.setTemplateId(emailTemplate.Id);
            // Set the email template Subject
            email.setSubject(emailTemplate.Subject);
            // Set the email HTML Body
            email.setHtmlBody(emailTemplate.HtmlValue);
            email.setToAddresses(new String[] { (String) record.get('Email') });

            // Set the target object ID
            email.setTargetObjectId((Id) record.get('Id'));

            emails.add(email);
        }

        // Send the batch of email messages
        Messaging.SendEmailResult[] results = Messaging.sendEmail(emails);

        // Process the results if needed
        for (Messaging.SendEmailResult result : results) {
            if (result.isSuccess()) {
                // Email sent successfully
                System.debug('Email sent successfully');
            } else {
                // Handle any errors or exceptions
                System.debug('Error sending email: ' + result.getErrors()[0].getMessage());
            }
        }
    }

    public void execute(SchedulableContext context) {
        // Create an instance of the batch class
        MassEmailBatch batch = new MassEmailBatch();
       
        // Schedule the batch job
        Database.executeBatch(batch);
    }
}

With these additions, the class now implements the ‘Schedulable’ interface, allowing you to schedule and execute the batch job using the Salesforce scheduler. The execute() method from the ‘Schedulable’ interface is implemented, where you create an instance of the batch class and call Database.executeBatch() to schedule the batch job.

Thereon, you can use the System.schedule() method in Salesforce to schedule the execution of the MassEmailBatch class based on your desired schedule. For example:

String scheduleExpression = '0 0 0 1 1 ? 2024'; // Schedule for January 1, 2024
MassEmailBatch scheduler = new MassEmailBatch();
System.schedule('Mass Email Job', scheduleExpression, scheduler);

In the above example, the MassEmailBatch class is scheduled to run on January 1, 2024. You can modify the scheduleExpression to define your desired schedule.

Make sure to adjust the schedule expression and any other parameters to fit your specific requirements.

  1. Monitor the Progress and Results

Keep an eye on the progress of the Batch Apex job by reviewing the Apex job queue or monitoring logs.

Once the job completes, analyze the results and track any errors or exceptions for troubleshooting purposes.

Remember to ensure that your Apex implementation adheres to Salesforce’s best practices, follows email regulations and permissions, and respects the privacy and preferences of your recipients.

And if you need more information on sending emails using Apex, check our “In-Depth Gide on Sending Emails With Apex”. 

Sending with 3rd party email providers: why and how?

As we already covered sending emails natively with Salesforce, this section focuses on third-party email providers. We cover the reasons to use third-party providers, as well as some downsides to keep in mind. 

Also, the exemplary integration is geared toward Mailtrap users. Mailtrap Email API/SMTP handles both streams, so transactional email and bulk campaigns each go out on their own stream with their own reputation. 

The division of labour is clean: Salesforce holds the contact data and decides who gets the message, and Mailtrap Email API/SMTP delivers it and reports back on what happened to it. 

The Whys

When it comes to sending emails from Salesforce, you have a couple of options. You can use Salesforce’s built-in email services, or you can use a third-party email service provider. 

While Salesforce’s built-in services are convenient, there are several compelling reasons to consider using a third-party service:

  • Deliverability: Third-party email service providers such as Mailtrap specialize in email deliverability. They have dedicated teams and technologies to ensure your emails reach the recipient’s inbox and not their spam folder.
  • Scalability: If you’re sending at a volume, third-party services are designed to handle and balance that load. Salesforce has daily limits on the number of emails you can send, which can be a constraint for some businesses.
  • Features: Third-party services often come with additional features such as email templates, analytics, A/B testing, automation, and more. These can be valuable tools for optimizing your email campaigns.
  • Cost-effectiveness: Depending on your volume of emails and the specific features you need, third-party services can often be a more cost-effective solution.

However, there are also some potential downsides to consider:

  • Integration: You’ll need to integrate the third-party service with Salesforce, which can require some technical setup. But at Mailtrap, we ensured the integration process is as smooth as possible. 
  • Dependency: You’re relying on another service, which could potentially have its own downtime or issues.
  • Cost: While often cost-effective, there is still a cost associated with third-party services. You’ll need to evaluate this against your budget and needs.

The How 

As a reminder, the quick tutorial below is geared toward transactional emails that you can send at scale with Mailtrap Email API/SMTP. 

Also, unlike Mailtrap Email Sandbox, Email API/SMTP requires you to add and verify a domain. And, in the sections below, we assume you already did it.  

If you need any help adding or verifying your domain, check our getting started guide

  1. Add Email Relay

To send through Mailtrap Email API/SMTP, you point a Salesforce email relay at Mailtrap’s sending servers. Our guide to setting up a Salesforce email relay covers that end to end, so we won’t repeat it here. The one thing worth knowing up front: Salesforce picks a relay by domain filter priority rather than by your edition, so which relay handles a given message depends on the domains you scope it to. 

Keep in mind that the credentials for Email API/SMTP are separate from your Mailtrap sandbox credentials. Take the following path to get to them. 

Sending Domains > Choose a domain > SMTP/API Settings

Mailtrap Email Sending SMTP Settings
  1. Send test email

To stress, the ‘test email’ you’ll be sending is there to confirm your configuration. By default, the ‘test email’ gets sent to the email address you use to sign into Mailtrap. 

Here’s the code snippet to send a test email. 

public class MailTrapEmailAPI {
  public static void sendMail(){
      String body = '{"to": [{"email": "john.doe@example.com", "name": "Mailtrap Inbox"}], "from": {"email": "mailtrap@example.com", "name": "Magic Elves"}, "subject": "You are awesome!", "html": "<!doctype html><html><head><meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=UTF-8\\"></head><body style=\\"font-family: sans-serif;\\"><div style=\\"display: block; margin: auto; max-width: 600px;\\" class=\\"main\\"><h1 style=\\"font-size: 18px; font-weight: bold; margin-top: 20px\\">Congrats for sending test email with Mailtrap!</h1><p>Inspect it using the tabs you see above and learn how this email can be improved.</p><img alt=\\"Inspect with Tabs\\" src=\\"https://assets-examples.mailtrap.io/integration-examples/welcome.png\\" style=\\"width: 100%;\\"><p>Now send your email using our SMTP endpoint and integration of your choice!</p><p>Good luck! Hope it works.</p></div></body></html>", "text": "Congrats for sending test email with Mailtrap!\\n\\nInspect it using the tabs above and learn how this email can be improved.\\nNow send your email using our SMTP endpoint and integration of your choice!\\n\\nGood luck! Hope it works."}';
     
      Http http = new Http();
      HttpRequest request = new HttpRequest();
      request.setEndpoint('https://send.api.mailtrap.io/api/send');
      request.setMethod('POST');
      request.setHeader('Api-Token', 'YourMailtrapAPIToken');
      request.setHeader('Content-Type', 'application/json;charset=UTF-8');
      request.setBody(body);
      System.debug('1 ' + request);
      HttpResponse response = http.send(request);
      System.debug('2 ' + response);
  }
}

That snippet sends to one hard-coded recipient. To send the same message to a list of addresses, build the to array from the list and let Apex serialise the payload rather than concatenating the JSON by hand. One setup note before you run it: an Apex callout only works once the endpoint is registered in Setup, either under Remote Site Settings or as a Named Credential. 

public class MailtrapBulkSend {
    public static void sendMail(List<String> recipients) {
        List<Map<String, Object>> toList = new List<Map<String, Object>>();
        for (String address : recipients) {
            toList.add(new Map<String, Object>{ 'email' => address });
        }

        Map<String, Object> payload = new Map<String, Object>{
            'to'      => toList,
            'from'    => new Map<String, Object>{ 'email' => 'campaigns@example.com', 'name' => 'Magic Elves' },
            'subject' => 'You are awesome!',
            'text'    => 'Congrats for sending a test email with Mailtrap!'
        };

        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://send.api.mailtrap.io/api/send');
        request.setMethod('POST');
        request.setHeader('Api-Token', 'YourMailtrapAPIToken');
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setBody(JSON.serialize(payload));

        HttpResponse response = new Http().send(request);
        System.debug(response.getStatusCode() + ' ' + response.getBody());
    }
}

Mass Send to the Rescue

We’ve covered a lot of ground in this article, diving deep into the process of Salesforce mass email sending. From Apex to testing, and the nuances of Salesforce Classic and Lightning Experience, we’ve seen that Salesforce offers a range of powerful tools for mass emailing.

As we wrap up our exploration of sending mass emails in Salesforce, keep in mind that each method has its own strengths and considerations. If what you actually need is the single-send path rather than a campaign, our guide to sending email in Salesforce covers the composer, workflow and Apex routes side by side. 

Remember, the world of Salesforce is vast and ever-evolving, so keep exploring, keep learning, and most importantly, keep emailing!

Article by Veljko Ristić Content Manager @Mailtrap

Linguist by trade, digital marketer at heart, I’m a Content Manager who’s been in the online space for 10+ years. From ads to e-books, I’ve covered it all as a writer, editor, project manager, and everything in between. Now, my passion is with email infrastructure with a strong focus on technical content and the cutting-edge in programming logic and flows. But I still like spreading my gospels while blogging purely about marketing.