Make your email system more efficient with bulk email sending
Messages such as password resets, one-time passwords (OTPs), and order confirmations are typically sent as soon as they are triggered by recipients. This is because they are sent in response to time-sensitive actions where speedy email delivery is crucial to the user experience or simply gives peace of mind and reassurance.
Other types of transactional emails, such as review requests or webinar access emails, don’t need to be sent immediately. This gives you a great opportunity to streamline your email sending, preserve sending quotas, and optimize your system by sending these emails in batches.
You can set up batch email sending using MailerSend’s bulk email endpoint and in this article, we’ll show you exactly how along with a code example to get you started.
What is batch email?
In transactional email sending, batch or bulk emails are messages sent to multiple recipients via a single API request instead of being sent individually (1 message per API request) as soon as the email is triggered by an action. They are sent in batches for optimal email deliverability and to avoid overloading email servers or, sometimes, to deliver the email at a more appropriate time.
When should you use bulk emailing?
You can use bulk email sending or email batching for any emails that aren’t time-sensitive or critical to recipients’ user experience. A good example of this is a daily account summary email. Since this type of message wouldn’t be triggered by an individual action but instead by overall daily account activity, they can be batched together for multiple users/recipients to be sent at the same time each day via a single API request.
You can also use batch emails to send messages at a time that makes more sense depending on their purpose. For example, if users sign up for a webinar and want to share the webinar link closer to the event, you can send these emails in bulk rather than individually.
Some other types of transactional emails that you can send in bulk are:
1. Account/product updates such as terms of service, privacy policy, and critical product updates.
2. System alerts such as service outages, scheduled maintenance, and other system updates.
3. Subscription expiry/renewal reminders when a paid subscription is about to expire or automatically renew.
4. Invoices or billing notifications.
5. Security alerts relating to issues affecting multiple users.
6. Updates and notifications about events such as schedule changes or venue information.
7. Shipping notifications for customers’ orders that are dispatched at the same time.
8. Survey requests for products, features, or events.
The benefits of sending transactional emails in bulk
The biggest benefit of sending emails in batches is that you can send multiple emails in a single API request, making it easier to scale your email sending by preserving your API quota as much as possible. What’s more, it:
Puts less strain on mail servers, allowing for consistent and reliable sending, even during periods of high-volume sending
Allows for timely communication during critical events by sending messages in the most efficient way possible
Allows you to automate repetitive tasks such as emails that go out daily, weekly, or monthly
Allows for email personalization at scale with dynamic tables, variables and more so you can send messages tailored to each recipient
Enables you to maintain a cleaner, more streamlined system that’s easier to scale and adapt
Bulk transactional emails vs. bulk marketing emails
Email marketing messages are sometimes referred to as bulk emails because, in many cases, campaigns are scheduled and sent in very large volumes. This shouldn’t be confused with bulk transactional emails, which are transactional in nature (therefore there’s no need for opt-in consent) and sent in bulk to optimize the email-sending system, improve deliverability, and maximize the user experience.
Put simply, it’s all about sending transactional emails in batches when appropriate to improve delivery performance, whereas with email marketing, sending emails in bulk is about getting campaigns in front of the widest audience possible (and opt-in consent is required!).
Learn more about the difference between transactional emails and marketing emails.
How to send batched emails
The best way to send batch email is with a reliable email service provider. Doing so will enable you to send higher volumes of email and ensure maximum deliverability. You’ll also be able to easily monitor the performance of the email with real-time engagement metrics (such as open rate and click-through rate).
For example, in MailerSend the bulk email functionality enables you to send a single personalized email to many recipients. You can use the endpoint by including it in a POST request like this:
POST https://api.mailersend.com/v1/bulk-email
If you’re on a Hobby plan or above, you can include 500 individual email objects in a single request, each containing up to 50 TO recipients, 10 CC, and 10 BCC, for a total of 35,000 emails. Otherwise, you are limited to 5 individual email objects.
For speedy sendings bulk emails are sent asynchronously without waiting for an API response. Email validation is also done after the request. You can check for failed emails and validation errors using the bulk_email_id parameter in a GET request:
GET https://api.mailersend.com/v1/bulk-email/{bulk_email_id}
How to send batch emails in PHP
Here’s an example to help you get started sending emails in bulk with MailerSend. Let’s say that you’re organizing an event and you want to follow up with everyone who signed up for it. An email reminder will be sent, along with the event schedule as a PDF file, to everyone a few days before the event.
A general workflow to send email notifications:
1. Identify the event and guests that you need to send a reminder to.
2. Prepare an email message for each guest.
3. Schedule emails to send later using a bulk request.
The email reminders are sent using the MailerSend PHP SDK, where a cron job will call the PHP routine every minute. Let’s see how you can set up all this in 5 steps!
PHP is used as an example since it’s one of the easiest scripting languages. If you prefer using another programming language, learn how to send emails using other MailerSend SDKs.
1. Set up the database structure
Start by organizing your event data into tables using the following database schema:
The events table stores the event name, event date, and the date and time we want to send the email reminders to our guests
The guests table contains the guest’s name, email address, the ID of the event that the guest belongs to, and a flag indicating whether a reminder was sent
The events table has a one-to-many relationship with guests as one event can have many guests attending it.
2. Create an email template
Compose the email reminder template in MailerSend using the drag & drop template builder. You can also use the rich-text email editor or create a custom design with the HTML editor.
Each email template will contain the following variables for advanced personalization:
{{guest_name}}, the name of the guest
{{event_name}}, the name of our event
{{date}}, the date of the event in the format Month Xth (e.g. October 1st)
{{time}}, the time of the event in 12-hour format (e.g. 1:00pm)
The email subject line is also customized with the following variables:
{{event_name}}, the name of the event
{{days_left}}, how many days are left for the event
{{days_label}}, which is “days” if the event is more than 1 day away or “day” if the event is tomorrow
Now that you have everything in place to start sending email reminders, let’s get coding!
3. Collect all the relevant information
Use the following PHP code to make an SQL-like query to your database. This will select the guests to the event to whom you haven’t sent a reminder.
/**
* Collect the guest and event information to send the reminder to
* We access the database using Illuminate but you can use whatever you want.
* The following is equivalent to this SQL query:
*
* SELECT guests.*, events.event_name, events.data FROM guests JOIN events ON events.id = guests.event_id
* WHERE guests.reminded = 0 AND events.remind_date <= NOW();
*/
$guestReminders = DB::table('guests')->select(['guests.*', 'events.event_name', 'events.date'])
->join('events', 'events.id', '=', 'guests.event_id')
->where('guests.reminded', '=', '0')
->where('events.remind_date', '<=', 'NOW()')
->get();
4. Prepare the email for each guest
To prepare the emails for sending, store each one in an array that you’ll use to make a bulk email request. Guest IDs are stored so you can keep track of which guests you have sent a reminder to. Also, the code is smart enough to know how many day(s) are left until the event, producing a grammatically correct subject line!
Setup
// This library is built atop PSR-7 and PSR-18. You will need to install some implementations for those interfaces.
composer require php-http/guzzle7-adapter nyholm/psr7
// Install the SDK:
composer require mailersend/mailersend
//We'll store the emails we want to send in an array that we'll use in the bulk email request
$emails = [];
//We'll store the guest IDs so that we can update the ones we sent the reminder to
$sentToGuestIds = [];
// We loop through the collected database records to set up the recipients and variables
foreach ($guestReminders as $guestReminder) {
$eventDate = DateTime::createFromFormat('Y-m-d H:i:s', $guestReminder->date);
$currentDate = new DateTime();
// We want to use a subject like "X days left for our event",
// so we calculate the number of days between the event data and now.
$daysLeft = $currentDate->diff($eventDate);
$daysLeft = (int)($daysLeft->days + ceil($daysLeft->h / 24));
$recipients = [
new Recipient($guestReminder->email, $guestReminder->name)
];
// If the event is 1 day away, we don't want the subject to be '1 days left for the our event',
// so we use a label for the word "days" which we change to "day" if the event is 1 day away.
$daysLabel = 'days';
if ($daysLeft == 1) {
$daysLabel = 'day';
}
// Set up the variables for our email
$personalization = [
new Personalization($guestReminder->email, [
'guest_name' => $guestReminder->name,
'event_name' => $guestReminder->event_name,
'date' => $eventDate->format('F jS'),
'time' => $eventDate->format('g:ia'),
'days_left' => (string)$daysLeft,
'days_label' => $daysLabel
])
];
// Set up the email
$email = (new EmailParams())
->setFrom('your from email address')
->setFromName('your from name')
->setRecipients($recipients)
->setSubject('Only {{days_left}} {{days_label}} left for {{event_name}}!')
->setTemplateId('your template id')
->setPersonalization($personalization);
// If we want also to include the event schedule, we can do the following:
/*
$attachments = [
new Attachment(file_get_contents('schedule.pdf'), 'schedule.pdf')
];
$email->setAttachments($attachments);
*/
$emails[] = $email;
// We store the id of each guest we sent the reminder to so that we can update its "reminded" field.
// That way we prevent sending duplicate reminders to the guests.
$sentToGuestIds[] = $guestReminder->id;
// there is a limit of 500 emails per bulk request, so if we reach 500 emails,
// we need to break to send the emails we prepared and continue in the next run
if (count($emails) == 500) {
break;
}
}
As seen in the code comments above, the event schedule can be attached as a PDF file named schedule.pdf. Simply uncomment the code to enable file attachments.
5. Send using the bulk email endpoint
Before sending, check if there are any emails left to send using the following PHP routine. If so, the bulk-email endpoint will be called using your MailerSend API token. Once sent, the reminder flag will be updated to show that an email has been sent.
// we check that we have emails to send and then do a request to the bulk email MailerSend endpoint
if (count($emails) > 0) {
// init the MailerSend SDK
$mailersend = new MailerSend(['api_key' => 'your MailerSend token']);
// send the email
$mailersend->bulkEmail->send($emails);
// update the guests that have been reminded
DB::table('guests')
->whereIn('id', $sentToGuestIds)
->update(['reminded' => 1]);
}
Since bulk emails are delivered in batches to avoid overloading mailbox providers, you need to check and send reminders every minute. To do this, create a method called checkReminders on a class called EventReminder, calling it from an index file or another entry point. Then start this automation using a cron job:
* * * * * php /home/user/check_reminders/reminders.php
To help you get started with scheduled email delivery, you can download all the sample code and files here.
Or schedule batch emails with the send_at parameter
Alternatively, instead of creating your own routine, you can schedule email sending by adding the send_at parameter to your Email request.
Add the scheduling parameter while setting up your email by adding:
->setSendAt(1665626400);
In the example above, it would give:
$email = (new EmailParams())
->setFrom('your from email address')
->setFromName('your from name')
->setRecipients($recipients)
->setSubject('Only {$daysleft} {$dayslabel} left for {$event_name}!')
->setTemplateId('your template id')
->setPersonalization($personalization);
->setSendAt(1665626400);
Make sure the send_at parameter has a Unix timestamp set in the future for up to a maximum of 3 days from when the call is made.
Once your emails have been sent, you can track their performance in the MailerSend Activity and Analytics pages, where you’ll be able to follow the entire journey of each email, from processed to sent to delivered and opened.
You can also retrieve activity and analytics data via the API. For example, you can fetch activity data for specific activities of your bulk email using the tags parameter (assuming you set a tag for your email).
GET https://api.mailersend.com/v1/analytics/date
use MailerSend\MailerSend;
use MailerSend\Helpers\Builder\ActivityAnalyticsParams;
use MailerSend\Common\Constants;
$mailersend = new MailerSend(['api_key' => 'key']);
$activityAnalyticsParams = (new ActivityAnalyticsParams(100, 101))
->setDomainId('domain_id')
->setGroupBy(Constants::GROUP_BY_DAYS)
->setTags(['event'])
->setEvent(['sent', 'delivered']);
$mailersend->analytics->activityDataByDate($activityAnalyticsParams);
Enable the “Precedence: Bulk” header for batch emails
The “Precedence: Bulk” header is a hidden header in your email that lets Gmail know that your email was sent to multiple recipients.
This simply informs Gmail that your bulk email was intentional, preventing your email from going to spam and your inbox from being overwhelmed with auto-responders, such as out-of-office notifications.
To enable the “Precedence: Bulk” header in MailerSend:
1. Go to Domains and click Manage next to the domain you want to enable the header for.
2. In the Advanced settings section, click More settings and toggle Add precedence bulk header on.
Best practices for sending transactional emails in bulk
1. Only send the right types of emails
Only use batch email sending for messages that recipients don’t necessarily expect to receive immediately as a response to an action they have taken. Compile a list of all of the transactional emails your system sends and determine which ones should be sent immediately and which ones are not time-sensitive so you can create the most efficient strategy.
2. Use personalization for ultra-relevant messaging
Even if you’re sending the same email template to thousands of recipients in a single HTTP request, you can tailor the message to each recipient. Make use of variables, dynamic tables, and conditional formatting to send personalized transactional emails at scale.
3. Monitor sendings for deliverability issues
Keep track of bounce rates, unsubscribes, and spam complaints to catch any unusual spikes that could harm your sender reputation and deliverability.
4. Use email address validation and verification
Maintain healthy sending practices and protect your sender reputation by regularly verifying recipients’ emails. Use an email validation API to catch invalid emails before they get added to your database.
5. Ensure compliance
Stay informed about any regulations that are applicable to your business, such as the GDPR or CAN-SPAM, and ensure you comply with them.
6. Think about timing
Although transactional emails you send in bulk are less time-sensitive, you should still consider how timing will affect their performance. For example, if you send a monthly account statement, you could send a batch for each timezone, maximizing opens by delivering the email at an optimum time no matter where the recipient is located.
7. Use a secure, reliable email infrastructure
Choose a provider that offers great deliverability for sending high volumes of email. Ensure that they implement the latest security protocols and offer features to help you keep your email sending safe.
To learn more about optimizing your email infrastructure for maximum performance, check out our guide. It’s aimed at developers and administrators looking to prepare for Black Friday or other high-traffic periods, but the advice applies to anyone looking to optimize their system.
Optimize your email sendings now
MailerSend’s bulk email endpoint lets you make the most of the API quota while maintaining an efficient and powerful email system. With more sending options to choose from, you can use triggered emails and scheduled email delivery to match your use case!
Improve your bulk email sending today!
Join MailerSend for free and get 3,000 emails/month.
Triggered or scheduled emails. Which ones do you use most often and why? Share in the comments below.
This article was originally published in March 2022 and has since been updated with additional insights and tips.