You’ve learned a lot.
You should earn a lot.

Find a Job

The Ultimate Guide to Sending Email in Laravel

Sending emails in web applications has become so essential. Marketing, notifications, newsletters, adverts, etc are some of the reasons why we send emails to our clients. I'd say the majority of websites send automated emails at least via a "Contact us" form.

Let's explore the many possible ways to send emails in a Laravel application.

Choosing An Email Service Provider

Although your first thought when you see "Email Service Provider" may be service providers in Laravel, that is not what I am referring to here. I am referring to online services that provide email sending functionalities via APIs.

You might be wondering why you need to make use of a service when you can just go hardcore with SMTP. The old way works fine, no doubt, but if you really want something awesome, robust, scalable and economic, then a service provider is better as it does all the hard jobs and just gives you an endpoint for your program to talk to,

We are going to review several possible providers and how to set them up in a Laravel application. Speaking of which, install a new Laravel application and leave config/services.php open in your favorite editor.


  1. Sign up for an account if you have not.
  2. Verify your email and phone number.
  3. You will be redirected to your Dashboard.
  4. Locate your API Key and domain


Mailtrap is awesome for development and testing. It was not built with sending emails in production in mind.

  1. Registier via https://mailtrap.io/register/signup
  2. Verify if necessary
  3. Access your inboxes via https://mailtrap.io/inboxes
  4. Store the SMTP credentials somewhere safe


  1. Sign up
  2. Setup a domain name
  3. Go to settings from the left menu
  4. Click Add API key

  5. Add Mandrill option in the config/services.php file
'mandrill' => [
        'secret' => env('MANDRILL_KEY'),

There are several more options, including Amazon SES, but we will just focus on a few. They are all very similar to setup so let us just stick with learning with what we have.

Configuring Our Services

Our config/services.php has all the configuration for major external services that are required for our application. It is also recommended that if Laravel does not provide any service, you should stick to the design pattern of using the services config file to configure your application.

 'mailgun' => [
        'domain' => env('MAILGUN_DOMAIN'),
        'secret' => env('MAILGUN_SECRET'),

    'mandrill' => [
        'secret' => env('MANDRILL_KEY'),

    'ses' => [
        'key' => env('SES_KEY'),
        'secret' => env('SES_SECRET'),
        'region' => 'us-east-1',

    'sparkpost' => [
        'secret' => env('SPARKPOST_SECRET'),

    'stripe' => [
        'model' => App\User::class,
        'key' => env('STRIPE_KEY'),
        'secret' => env('STRIPE_SECRET'),

Notice that Mailtrap is missing here. It uses SMTP and is provided as default in every Laravel installation because it is made for testing purposes.

A practice really frowned upon is storing credentials in codes as they may leak to the wrong hands, especially while moving a code base around in a VCS. For this reason, Laravel uses a .env file for storing it's credentials and environmental variables:









You can go ahead to replace the usernames, passwords, keys, domains and secrets you got while registering for the email services.

Setting a Default Option

As I already mentioned, we cannot use all the services at the same time. In that case, even after setting up multiple providers, we still need to tell Laravel which one to use:





Sending Emails

Setting up the services and configuring them does not actually send the emails, but it is an amazing step we have taken together. We can do better. Let us send an email.

A Basic Approach

We will use RESTful approach to send the emails because it is the standard. So get your Postman ready to do some jobs.

We do not need a Model or a View with where we are headed. Instead we just need a controller and a route. Create a controller named EmailController:

php artisan make:controller EmailController

Now add a simple route to app/Http/routes.php:

Route::post('/send', 'EmailController@send');

Our controller is pointing to the controller we created and is asking the send action method to process the request. Let us go ahead and create the send action method:

Note: Action methods are methods in a controller that handle a request.

public function send(Request $request){
    //Logic will go here        

That is a basic method waiting and ready to be fleshed out. We have also type-hinted Request if we need anything to do with the request object.

To send HTML emails, we need to create a template for that. Create a send.blade.php file in resources/views/emails with the following:

<body style="background: black; color: white">

Back to the action method. It is time to actually add the mail sending logic which can be done using the Mail facade:

 public function send(Request $request)
        $title = $request->input('title');
        $content = $request->input('content');

        Mail::send('emails.send', ['title' => $title, 'content' => $content], function ($message)

            $message->from('me@gmail.com', 'Christian Nwamba');



        return response()->json(['message' => 'Request completed']);

The Mail Facade which is used to handle emails in Laravel provides several methods including send(). The send() method takes 3 parameters: a blade view, data to be bound to the view, and a closure. You can configure the mail how ever you want in the closure.

Head to Postman and make a Post request to /send with title and content as seen below:

Below is an image of this mail as it arrives in Mailtrap

We can configure all the properties of an email right inside the closure. Below are the available options as provided by Taylor:

$message->from($address, $name = null);
$message->sender($address, $name = null);
$message->to($address, $name = null);
$message->cc($address, $name = null);
$message->bcc($address, $name = null);
$message->replyTo($address, $name = null);
$message->attach($pathToFile, array $options = []);

Let us experiment with one more of the features which is $message->attach()

Attaching Files

Attaching files is very simple. We just use the attach() method and supply a file path.

 public function send(Request $request)
        $title = $request->input('title');
        $content = $request->input('content');
        //Grab uploaded file
        $attach = $request->file('file');

        Mail::send('emails.send', ['title' => $title, 'content' => $content], function ($message) use ($attach)

            $message->from('me@gmail.com', 'Christian Nwamba');


            //Attach file

            //Add a subject
            $message->subject("Hello from Scotch");


We requested a file uploaded via a form and attached it to the mail. Notice that we also added a subject to the email.

Optimizing with Queues

You can now use queues to optimize sending emails. It is dead simple. Instead of sending with the send() method, we send with the queue() method:

 public function send(Request $request)
        //Using queues is better
        Mail::queue('emails.send', ['title' => $title, 'content' => $content], function ($message) use ($attach)


Remember that we have to run the listen command on the queues before they can be dispatched:

php artisan queue:listen

In production, it is not advisable to use listen because of it's high CPU usage. It is better we use work and pass the --daemon option:

sude nohup php artisan queue:work --daemon --tries=3

Bonus: Bulk Email Notifications with MailChimp

As this article is one about sending emails, it would be nice to consider sending bulk emails. The popular tool that handles this is Mailchimp so lets try that out.

Setup MailChimp

Setting up Mailchimp invovles two steps - account creation and Laravel project setup. To create a MailChimp account, head straight to the Sign up page, sign up, and verify your account if required.

Next create a list of your subscribers. In a real project, you would be adding users to the list programatically using the API, but we can just go ahead and create some via the dashboard as seen below.

Now grab the List Id by going to Settings > List name and defaults. Also create and get your API key from User > Accounts > Extras > API Keys. "User" stands for your username, which is on the navigation bar.

Head back to the Laravel project and store the key and Id in .env:


Then pull Mandrill's PHP SDK from composer:

composer require mailchimp/mailchimp

Sending Campaigns

Mailchimp's bulk emails are identified as campaigns. Let us create another simple action method to handle sending bulk message to our list of subscribers:

public function notify(Request $request){

        //List ID from .env
        $listId = env('MAILCHIMP_LIST_ID');

        //Mailchimp instantiation with Key
        $mailchimp = new \Mailchimp(env('MAILCHIMP_KEY'));

        //Create a Campaign $mailchimp->campaigns->create($type, $options, $content)
        $campaign = $mailchimp->campaigns->create('regular', [
            'list_id' => $listId,
            'subject' => 'New Article from Scotch',
            'from_email' => 'pub@gmail.com',
            'from_name' => 'Scotch Pub',
            'to_name' => 'Scotch Subscriber'

        ], [
            'html' => $request->input('content'),
            'text' => strip_tags($request->input('content'))

        //Send campaign

        return response()->json(['status' => 'Success']);

We are using two campaign methods: create() and send(). The create() method provisions a campaign and returns an array which contains the id of our campaign. We then pass this id to the send() method to dispatch the emails. That's all!

Go ahead and add the extra route:

Route::post('/notify', 'EmailController@notify');


If your web application sends emails, it is recommended you take the extra mile and use useful services to optimize the whole process. Test your emails with Mailtrap, send with Mandrill/Mailgun/SES or anything that suites you, and optimize with Queues.

Chris Nwamba

I have passion for instructing computers and understanding it's language and would die to remain a computer programmer in my next life.