Send Emails In Laravel 8 Using Gmail's SMTP Server

October 13, 2021
Written by
Funke Olasupo
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by

Sending email has become an essential part of modern web applications. For example, they are a great way to communicate with users, when they register, when verifying registrations, and when resetting passwords.

So in this tutorial, you will learn how to send emails in Laravel using a Gmail SMTP server.

Prerequisites

To follow this tutorial you need the following:

Overview

In certain circumstances, your local server may not send emails when using the default PHP mail() method, or it may make it quite problematic to do so. In such scenarios, using a dedicated email library, such as Symfony's Mailer component, can be a practical alternative.

You could also use one of the many email drivers which Laravel supports, including Mailgun, Amazon SES, and Postmark, and of course, Twilio's own SendGrid. However, in this tutorial, you'll learn how to configure Laravel to send emails using Gmail's SMTP server instead.

You're going to create an API for newsletter subscriptions. The user will subscribe to the newsletter by submitting their email address. After doing so, their email address will be stored in the database, and they are sent a “Thank you for subscribing” mail.

Benefits of using Gmail's SMTP server

  • Using Gmail's SMTP server helps ensure that emails are not stored in the recipient’s spam fold.
  • It is the prominent choice of many users for email communication because of their servers' stability and consistent performance.

That said, it's important to know that Google imposes some limitations on free accounts, e.g.,,  a maximum of 100 emails can be sent per day.

Create the Laravel application

You can create a new Laravel application via Composer or install the Laravel Installer as a global Composer dependency. We'll be using the Laravel Installer in this tutorial by running the following command in the terminal:

laravel new mail_article

This will create a fresh Laravel application in a new directory named mail_article. Next, change into the new project directory and start the application by running the following commands:

cd mail_article
php artisan serve

By default, the project is served on port 8000 on localhost. We can access it by entering http://localhost:8000 in the browser.  You should see a page similar to the image below confirming that your project is running. After seeing that, stop the application by pressing Ctrl + C.

 

The default Laravel home page

Add the Gmail SMTP server configuration

Laravel stores email configuration in config/mail.php. By default, it's set to use SMTP. We do not need to edit config/mail.php, however, because we can supply the necessary information in .env, which stores our environment variables. config/mail.php will, in turn, fetch the required details from there.

Open .env, and update the following variables:

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=<Enter your Gmail address>
MAIL_PASSWORD=<Enter your Gmail password>
MAIL_ENCRYPTION=ssl
MAIL_FROM_NAME=Newsletter

Be careful not to use quotes(“,',) or spaces.

Configure Google account settings

Now that the email configuration has been updated, we need to configure some security settings in our Gmail account. To do that, log in to Gmail and select "Manage your Google Account" from the profile (cog) option. Then, under "Less secure apps", select "Security", click "Turn on access (not recommended)", and toggle the option to the right of "Allow less secure apps: OFF".

 

Less secure app access enabled in a Google Account

 

This is because, by default, Gmail won't let "less secure" apps have access to use your Gmail account.

It’s important to understand the meaning of this term. Less secure describes a class of third party applications which are fundamentally less secure than using an authorization system like OAuth to gain access to your credentials. OAuth doesn’t give third party applications access to your credentials, it only provides authorization for certain services.

Set up the model and migrations

Now that we have made the necessary configuration changes, let's add the code that subscribes a user to the newsletter.

First, create the model and database migration simultaneously, by running the command below:

php artisan make:model Subscriber -m

This creates a Model file called Subscriber.php in the app/Models directory, and a Migration file called create_subscriber_table.php in the database/migrations directory.

Update Subscriber.php by adding the code below to the top of the file, which enables Model mass assignment.

protected $guarded = [];

Then, update the up() method of the migration file with an email field as in the example below

Schema::create('subscribers', function (Blueprint $table) {
    $table->id();
    $table->string('email');
    $table->timestamps();
});

Establish the database connection

To set the application's database, in .env, update the database configuration to match the following example, replacing the placeholders with details for your database.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<Enter your database name>
DB_USERNAME=<Enter your database username>
DB_PASSWORD=<Enter your database password>

You may need to clear the cache, although it's not compulsory. To do that, run the following command in the terminal:

php artisan config:cache

Next run the database migrations by running the following command:

php artisan migrate

Generate a Mailable

Laravel provides diverse ways to support sending emails using Mailable classes, supporting both Markdown and plain text emails. We will be using a Markdown Mailable for this tutorial.

Markdown Mailables contain a mix of Markdown and Blade templates that allow you to construct your email messages with prebuilt UI elements from Laravel.

To create the Mailable (app/Mail/Subscribe.php) and its corresponding view template (resources/views/emails/subscribers.blade.php), run the following Artisan command:

php artisan make:mail Subscribe --markdown=emails.subscribers

Set up the controller

Next up, you need to create a controller to store the logic that manages storing the email address and sending the confirmation email to the submitted email address. To create the controller, run this Artisan command:

php artisan make:controller SubscriberController

It will create a new file called SubscriberController.php in the app/Http/Controllers directory. With the file created, add the import statements below to import the classes which the controller will use:

use App\Mail\Subscribe;
use App\Models\Subscriber;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;

Next, define the subscribe() method which will hold the business logic, by copying the method below into the class. It will receive the users' input via $request.

public function subscribe(Request $request) 
{
    $validator = Validator::make($request->all(), [
         'email' => 'required|email|unique:subscribers'
    ]);

    if ($validator->fails()) {
        return new JsonResponse(['success' => false, 'message' => $validator->errors()], 422);
    }  

    $email = $request->all()['email'];
        $subscriber = Subscriber::create([
            'email' => $email
        ]
    ); 

    if ($subscriber) {
        Mail::to($email)->send(new Subscribe($email));
        return new JsonResponse(
            [
                'success' => true, 
                'message' => "Thank you for subscribing to our email, please check your inbox"
            ], 
            200
        );
    }
}

The first thing the subscribe() method does is validation. It confirms that a valid email address is being sent and not an empty field or some random text. It also checks that the user isn't already subscribed, meaning that the user isn't already in the subscribers table in the database.

If any of the validation rules fails, a JSON response with the error message of the rule that failed is returned. If the validation rules passed it sends the email to the email address submitted, once it's stored in the database.

Next, it creates a new record of a subscriber by instantiating the Subscriber model and passing the email submitted to the create() method.

We are passing the email address to the Mailable in the $email variable so we can see it returned in the email message to be sent. The to() method takes only the receiver's email address while the Mailable Subscribe() receives any data property that needs to be built in the email.

Create a Mailable

The Mailable class builds the email for us. It comes with a build method within which you can call other methods, such as from, view, markdown, and subject, which configure the various Mailable properties.

Open app/Mail/Subscriber.php and update the __construct() method as follows:

public $email;

public function __construct($email)
{
    $this->email = $email;
}

If you have no data to pass to the email, leave the __construct() method as it is.

Next is the build() method, which calls subject() to give our email message a subject.

public function build()
{
    return $this
        ->subject('Thank you for subscribing to our newsletter')
        ->markdown('emails.subscribers');
}

It already has the markdown() method by default which specifies the Blade file where the components of the email can be written.

Write Markdown messages

Open the Blade file resources/views/emails/subscribers.blade.php which contains all the components of the message, and update it to match the code below.

Note: This is the Blade file being targeted in the markdown() method in the build() method of the Mailable class.

@component('mail::message')
# Welcome to the first Newsletter

Dear {{$email}},

We look forward to communicating more with you. For more information visit our blog.

@component('mail::button', ['url' => 'enter your desired url'])
Blog
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

Both Markdown and Blade are supported here. Although, avoid excess indentation because it can result in code blocks in Markdown. You can compose your desired message here and make use of different properties like buttons, tables etc. To know more about Markdown Mailable, read this Laravel documentation.

Set up the routes

Seeing as this is an API we are building, we'll add a new route in routes/api.php. We only need to define one since we have only one endpoint, /api/subscribe, for users to submit their email.

To define it, add the following code to routes/api.php.

Route::post('/subscribe', [SubscriberController::class, 'subscribe']);

Then, add the import statement to the top of the file.

use App\Http\Controllers\SubscriberController;

Test the application

It's time to test our API and confirm that everything is functioning properly. There are various ways to do so, such as Postman, or cURL which we'll be using.

First run the command below to start the application.

php artisan serve

Run the command below in the root directory of the project, replacing <subscriber email address> with the email address that needs to subscribe.

curl -X POST -F "email=<subscribers email address>" http://localhost:8000/api/subscribe

If everything works as expected, you will see output similar to the example below:

{
    "success":true,
    "message":"Thank you for subscribing to our mail, please check your inbox"
}

Now check your inbox where you should see an email with the message, sender information, and email subject, etc, nicely formatted with some prebuilt Laravel UI

 

The received thank you email

If the request is unsuccessful because the email is already subscribed, you will see an output similar to the example below:

{
    "success":false,
    "message":{
        "email":[
            "The email has already been taken."
        ]
    }
}

Conclusion

In this tutorial, you learned how to send emails in Laravel using a Gmail SMTP Server. Mail in Laravel is a broad concept on its own but this tutorial can serve as a great starter guide. More information can be found in the official Laravel documentation. The code for this project is open-source and available on GitHub.

If you enjoyed integrating Gmail's SMTP server, why not try using SendGrid as a SMTP relay in Laravel?

Happy coding!

Funke is a tech lover with a keen interest in building and promoting sustainable tech communities especially among teenagers and young adults. She is a backend developer, who is passionate about communal growth and has published articles on many blogs including her personal blog.

When she is not writing codes or creating technical content she is rendering humanity service to her local community solving societal issues. You can reach out to her on Twitter and Github.