How to send bulk email using laravel using Aws SNS

This tutorial will help you to send bulk mail using aws sns. Best solution for notification and newsletters features in your application.

tutorials - 16 July, 2019

How to send bulk email using laravel using Aws SNS

Considering that this is something that nearly every business does these days, there seems to be very little documentation on how to do it. Obviously one solution is to outsource it and send through Mailchimp or Constant Contact but these can get quite expensive and if you are building an application where contacting your customer base is integral then building your own is a good solution. And it’s really not that difficult!

For this I used Amazon’s Simple Email Service (SES) and I use the Laravel Framework although most of the article would be suitable for anyone writing in any language or any Framework.

Amazon AWS

You will need to start by setting up Amazon Simple Email Service (SES) in your AWS account. When you open an account you will only be given sandbox status, which basically means you have to list the email addresses you send to. You can immediately apply to increase your limits and normally that request is active within 24 hours. They will give you two limits. One will be the number of emails you can send in a day and the other will be how many emails you can send per second.

You will also need to set up Amazon Simple Notification Service (SNS). This will allow notifications to be sent back to an endpoint in your software to manage bounces, complaints and to track open rates etc.


I wanted the option to send bulk email immediately and schedule it to send at a later time and so I created a table to handle this. If you are only going to send immediately, you could forward it to a Queue instead. Checkout Redis or Amazon SQS and then you can jump to “Sending the Email” section.

The key columns were as follows:

“scheduled_date_time”, “status”

I also wanted the option to be able to send recurring emails so I added an “interval” column.

I then created a mail tracking table which basically records the response from amazon on each email delivered, bounced and complaint (spam). The fields correspond with the JSON notifications from SNS. This allows me to view stats for each of the emails sent.

“type”, “sub_bounce_type”, “complaint_type”, “email_address”, “email_label”

Lastly, I create a suppression list table so any emails that are returned from SES as bounces or complaints are inserted into this table.

“email_address”, “reason”, “tries”, “permanent”

Whenever I send emails I query against this list making sure the email is not invalid. I will cover this in more detail in the “Amazon Notifications” section.

Creating the email

If you are creating a newsletter, I would suggest using a builder to create it. I use and would recommend Bee Free as it’s a great option and easy to integrate into your backend. It’s not free as the title suggests but it is very good value and the guys that created it are extremely helpful.

Scheduling the email

After I have created the email in my administration panel, I then send it to my email scheduling table with either the current date or a date in the future and the status set as “scheduled”.

If I want to send it as a recurring email, I mark it as recurring along with the interval time in the table and then every time an email is sent I recalculate the “scheduled_date_time” using the “interval” value. So if the interval was “1 month” it would add 1 month to the current “scheduled_date_time”column and so on.

I then use the Task Scheduling feature with Laravel to check if there is an email scheduled to be sent. Basically I have a cron job on my server to run all the the scheduled jobs I have every minute then the scheduler will check my scheduled email table every minute to see if there is an email scheduled. As soon as one exists the email will be sent.

Sending the email

First you will need to add headers to the email you are going to send out so you can track the emails.

You will need to create a configuration set in your SES account to be able to forward this to Amazon Simple Notification Service (SNS) then add ‘X-SES-CONFIGURATION-SET’ along with the reference you have used when setting it up.

You will also need to add another to be able to track the email when it comes back to you. When I create a new email I create a short unique code as my “email_label” I attach this to the header and then when the SNS notification comes back I can link that notification with the email that was sent which allows me to compile the statistics.

The build function in my mailable class in Laravel looks like this:

public function build()
    return $this->from(‘’)
        ->withSwiftMessage(function ($message) {
            $headers = $message->getHeaders();
            $headers->addTextHeader(‘X-SES-CONFIGURATION-SET’, ‘email_engagement’);
            $headers->addTextHeader(‘email_label’, $this->label);
        ->with([‘message_body’ =>‘Message Body’]);


You must make sure that the script won’t time out as it can take a while to send thousands of emails so you will need to adjust your php settings so manage this.

Secondly you don’t want that script to run again the next minute and start the script all over again otherwise your email will be sent out many times. My solution for this was to change the status on the email to “sending” and then when I am querying the table for scheduled emails I only search for emails with a status as “scheduled”.

Laravel also has an option to stop tasks overlapping:


However, as I like to be really safe when sending emails I actually use both to make sure.

You have two options with SES depending on your use case. If you are not using dynamic data (Personalising the Email) or you are managing this aspect yourself then use option 1 otherwise use option 2.

Option 1.

After retrieving your contacts, loop over each one and call the SES API on each loop to send the email. You will need to throttle the sending to make sure that you don’t exceed your Amazon limit. You will need to check your AWS account to find out what this is. Initially when you increase your limit they normally allow you to send 14 emails per second.

I used the following code to throttle my API calls.

foreach($clients as $client) {​    // Send email code.    usleep(100000)

As I am cautious and my mail lists are not that big I have kept it to 10 emails per second but obviously you can change this depending on your limit with SES and how close you want to get to that limit.

If you do go over the limit you can catch the error with a try catch block and resend the email to SES after a short pause. You are allowed to go over the limit with short bursts but again I wouldn’t bank on this. I think it’s a lot easier to control the speed you are sending to the API in the first place.

Option 2.

If you are personalizing the email such as adding in the name or other details in to the body of the email, then use the template option with the AWS SDK.

You will need to create the template first in your SES account which you can do through the API. Then reference that template when you send the list of email addresses to the SES API along with the data you wish to dynamically add to the template.

You are limited to 50 email addresses with each API call so if you are going to send to a larger list than this, chunk your list into blocks of 50 and then loop through each of the chunks.

Again you will be limited to how quickly you can send these requests. Normally you can send one request to the API per second using the template method although you will want to check you SES account to make sure.

Amazon Notifications (SNS)

Every time you send an email to SES, SNS will respond with a JSON response. You can set this up to receive successful, bounces and complaints otherwise they will email you every time there is a bounce or complaint and dealing with these manually is not much fun!

I have set it up so I have a different endpoint for bounces, complaints, delivery and engagement. If you prefer you could easily set up one endpoint and delegate depending on the type of response.

Then I will add to this to my email tracking table and to the suppression list table if it’s a bounce or complaint.

This then allows me to display all the normal statistics of emails sent, opened etc and the suppression list allows me to ensure I am only sending valid emails to SES. With the soft bounces I record the number of attempts and after three failed attempts the email address is marked as permanent and I won’t send to it again.

Once you have setup SES and SNS you can easily test the endpoints from you AWS account to make sure that it is setup correctly.

Our Sponsors

NodeJS Experts
React Experts
PHP Experts
AngularJS Experts
Aws Experts
Firebase Experts

Top Applications in TutorialStuff

Top Experts In TutorialStuff

Trending On TutorialStuff