Sending Email in Laravel Using Gmail SMTP

On February 05, 2024
10min read
Dzenana Kajtaz Technical Content Writer @Mailtrap

Laravel, known for having an expressive and elegant syntax, is one of the most commonly used PHP frameworks. 

Be it for its vast documentation and plenty of tutorials or its impressive features, scalability, and progressiveness, Laravel is often the go-to for building full-stack web applications.

These full-stack web applications can be enhanced with an email-sending functionality using a combination of Laravel and an SMTP server offered by an email service provider such as Gmail. 

If using Laravel to send email through Gmail is something you plan on doing within your current/future Laravel project, then keep on reading as, in this article, we show you step-by-step how it’s done!

Steps to take before initiating the email-sending process in Laravel

While sending emails in Laravel is not overly complicated, it is crucial to familiarize yourself with the following foundational concepts before initiating the process.

Building your application

If you do not currently have a Laravel application, you can use the following steps to create one.

First, using the terminal, create a new Laravel project by running either laravel new app_email_in_laravel or the composer create-project laravel/app_email_in_laravel command (of course, within the commands, you should replace “app_email_in_laravel” with the name of your application).

Next, utilize the cd app_email_in_laravel command to switch to a directory named app_email_in_laravel (make sure this matches your actual directory name). 

This step is essential in executing the Laravel command that creates mailable classes (more details in the next section).

Lastly, to view your Laravel application in a web browser, execute the php artisan serve command.

Configuration

In the Laravel framework, you can configure email services in the config/mail.php file. This file contains a mailers configuration array with sample configuration entries for various mail drivers/transports supported by Laravel.

The default configuration value in this file determines the default mailer when sending an email from your Laravel application.

Thanks to the multiple mailers that can be configured in the config/mail.php file, you can utilize different email-sending services for different types of emails.

Generating and writing mailables

Various types of emails in Laravel are represented by a class called “mailable”, which is stored in the app/Mail directory. 

This directory is not present by default in your application, but it gets generated automatically when you create your first mailable class using this Artisan CLI command:

php artisan make:mail MailableName

After creating a mailable class, you can view its contents and configure the class using the following methods:

  • Envelope – Returns an instance of the Illuminate\Mail\Mailables\Envelope object, which allows you to define the subject and recipients of the email.
  • Content – Returns an instance of the Illuminate\Mail\Mailables\Content object, which lets you define the Blade template used to generate the content of the email message.
  • Attachments – Returns an array of attachments that can be added to the email.

Sender configuration

To specify the sender – the “from” email address and name – you have two options: you can use the Envelope object of the message or set a global “from” address.

  • Specifying the sender in the Envelope object:
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;
 
/**
* Get the message envelope.
*
* @return \Illuminate\Mail\Mailables\Envelope
*/
public function envelope()
{
   return new Envelope(
       from: new Address('example@example.com', 'Test Sender'),
       subject: 'Test Email',
   );
}
  • Specifying the sender in config/mail.php using a global “from” address:
'from' => ['address' => 'example@example.com', 'name' => 'App Name']

Note: If you want to use the same “from” address for all the emails sent by your application, it is recommended to use the global “from” address method. This approach is convenient as it eliminates the need to call the from method in each of your mailable classes, and it serves as the default “from” address if no other address is specified.

How to send emails using Laravel and Gmail SMTP?

The initial step in sending emails using Gmail SMTP is adding your Gmail SMTP configuration to the .env file of your application.

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=mygoogle@gmail.com 
MAIL_PASSWORD=*************
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=mygoogle@gmail.com
MAIL_FROM_NAME="${APP_NAME}"

After the SMTP setup is completed, it’s time to generate one of those mailable classes we mentioned earlier using the following command.

php artisan make:mail MyTestEmail

Upon executing the command in the Artisan CLI, a new class named “MyTestEmail” will be generated in the app/Mail directory.

If you wish, you can inspect the class code below:

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class MyTestEmail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the message envelope.
     *
     * @return \Illuminate\Mail\Mailables\Envelope
     */

    public function envelope()
    {
        return new Envelope(
            subject: 'My Test Email',
        );
    }
 /**
     * Get the message content definition.
     *
     * @return \Illuminate\Mail\Mailables\Content
     */

    public function content()
    {
        return new Content(
            view: 'view.name',
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array
     */
    public function attachments()
    {
        return [];
    }
}

As evident from the code above, the content() method will return a view. Therefore, you need to navigate to the resources/views directory, create a new folder, and within it, a blade.php file.

When the file has been generated, you can add content to it.

// resources/views/mail/test-email.blade.php
Hey, 
Can your Laravel app send emails yet? 😉 
Funny Coder

Then, return to the content() method and update the name of the view being returned by it with the name of the newly-created file.

If you wish to add dynamic content, you can use the with attribute to include the recipient’s name in your email template/blade.php file.

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class MyTestEmail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(private $name)
    {
        //
    }

    /**
     * Get the message envelope.
     *
     * @return \Illuminate\Mail\Mailables\Envelope
     */
    public function envelope()
    {
        return new Envelope(
            subject: 'My Test Email',
        );
    }

    /**
     * Get the message content definition.
     *
     * @return \Illuminate\Mail\Mailables\Content
     */
    public function content()
    {
        return new Content(
            view: 'mail.test-email',
            with: ['name' => $this->name],
        );
    }
}

You will also need to make a minor modification in the test-email.blade.php view file as well and make it accept the $name variable as a parameter.

// resources/views/mail/test-email.blade.php

Hey {{$name}}, 
Can your Laravel app send emails yet? 😉 
Mailtrap

As the final step, add a route in the routes/web.php file using the following code:

<?php

use Illuminate\Support\Facades\Route;
use App\Mail\MyTestEmail;
use Illuminate\Support\Facades\Mail;

Route::get('/testroute', function() {
    $name = "Funny Coder";

    // The email sending is done using the to method on the Mail facade
    Mail::to('testreceiver@gmail.com')->send(new MyTestEmail($name));
});

To test the functionality, you can run the php artisan serve command and then access your web browser. In the browser, paste the URL of the route you created.

Once you have done this, if everything is working properly, an email should be sent to the “to” address that you specified.

For learning how to send an email in HTML format, an email with an attachment, or an email with multiple recipients, check out our Sending Emails in Laravel – All You Want to Know article.

Limitations and possible issues when using Gmail SMTP

Gmail, although widely used, does come with limitations and issues that are not talked about so often.

So, to help you keep your Laravel project on the right track and avoid any potential pitfalls, we’ll now go over these limitations and issues one by one.

Sending limit – With Gmail SMTP, users have a daily email sending limit, which depends on the Gmail account they use. Exceeding this limit will cause errors or a temporary suspension.

Rate limit – Another limit Gmail SMTP users have to deal with is the limit on how many emails they can send per minute or per hour. Exceeding this limit will block or delay your email sending.

Security – Sending emails through Gmail SMTP will require a secure connection such as SSL or TLS, which you need to configure correctly in the Gmail SMTP settings. Failing to do so will leave your emails and their data vulnerable to interception and tampering.

Google’s security settings also require proper configuration of things such as two-factor authentication to avoid the blocking of email sending.

Custom domain – For sending emails from a custom domain such as johndoe@yourcompany.com with Gmail SMTP, you need to configure the correct DNS settings. Not doing so will cause your emails to fail SPF, DKIM, and DMARC authentication checks and thus be marked as spam or simply rejected.

Gmail SMTP: is there an alternative to consider?

After introducing you to the limitations and possible issues that come with using Gmail SMTP, it’s only natural that the question “Is there an alternative?” pops up in your head. And the answer is, yes, there is!

Along with the common but somewhat basic alternatives, such as Outlook SMTP, Yahoo Mail SMTP, and so on, at your disposal, you also have the SMTP server of Mailtrap Email Sending – a sending solution that gives developers an infrastructure with high deliverability rates by design.

Mailtrap Email Sending also facilitates effortless maintenance and troubleshooting through alerts (deliverability and critical) and unique monitoring tools, which include helicopter-view dashboards, drill-down reports with detailed stats on mailbox providers (Gmail, Google Workspace, O365, and Outlook), email categories, and extended email history with historical data from up to 60 days of email logs.

Other benefits of the sending solution are a smooth and secure setup, the option to use an email API or SMTP service, and an email delivery time of around 1 sec, which allows you to reach recipients’ inboxes just in time.

To find the Mailtrap Email Sending SMTP credentials, you first need to create a Mailtrap account and log in. 

Then, in your account, under Email Sending, navigate to Sending Domains, where you need to add and verify your domain.

The process is described in detail in the video below:

Upon domain verification, you will be taken to the API and SMTP Integration page, where you can copy the SMTP credentials you need to paste into your Laravel app/project to start using Mailtrap’s SMTP server.

As mentioned earlier, an email API is also available within Mailtrap Email Sending for those that want to automate the sending process and have better flexibility.

To integrate this email API into your Laravel application, you can use the Mailtrap PHP SDK, which makes the integration easier and more efficient than manually writing the integration code for your project.

These are the steps for using the SDK:

  • Install the Mailtrap PHP client and dependencies using Composer:
composer require railsware/mailtrap-php symfony/http-client nyholm/psr7
  • Add the Mailtrap transport into your config/mail.php file:
<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Mailer Configurations
    |--------------------------------------------------------------------------
    */
    'mailers' => [
        // start mailtrap transport
        'mailtrap' => [
            'transport' => 'mailtrap'
        ],
        // end mailtrap transport
    ]
];
  • Add the Mailtrap credentials into your Laravel .env file:
MAIL_MAILER="mailtrap"
MAILTRAP_HOST="send.api.mailtrap.io"
MAILTRAP_API_KEY="YOUR_API_KEY_HERE"
MAILTRAP_INBOX_ID=1000001
  • Create a mailable class to send email:
php artisan make:mail WelcomeMail
  • Configure the app/Mail/WelcomeMail.php class:
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Queue\SerializesModels;
use Mailtrap\EmailHeader\CategoryHeader;
use Mailtrap\EmailHeader\CustomVariableHeader;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Header\UnstructuredHeader;

class WelcomeMail extends Mailable
{
    use Queueable, SerializesModels;

    private string $name;

    /**
     * Create a new message instance.
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            from: new Address('jeffrey@example.com', 'Jeffrey Way'),
            replyTo: [
                new Address('taylor@example.com', 'Taylor Otwell'),
            ],
            subject: 'Welcome Mail',
            using: [
                function (Email $email) {
                    // Headers
                    $email->getHeaders()
                        ->addTextHeader('X-Message-Source', 'example.com')
                        ->add(new UnstructuredHeader('X-Mailer', 'Mailtrap PHP Client'));

                    // Custom Variables
                    $email->getHeaders()
                        ->add(new CustomVariableHeader('user_id', '45982'))
                        ->add(new CustomVariableHeader('batch_id', 'PSJ-12'));

                    // Category (should be only one)
                    $email->getHeaders()
                        ->add(new CategoryHeader('Integration Test'));
                },
            ]
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'mail.welcome-email',
            with: ['name' => $this->name],
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [
            Attachment::fromPath('https://mailtrap.io/wp-content/uploads/2021/04/mailtrap-new-logo.svg')
                ->as('logo.svg')
                ->withMime('image/svg+xml'),
        ];
    }

    /**
     * Get the message headers.
     */
    public function headers(): Headers
    {
        return new Headers(
            'custom-message-id@example.com',
            ['previous-message@example.com'],
            [
                'X-Custom-Header' => 'Custom Value',
            ],
        );
    }
}
  • Create an email template under resources/views/mail/welcome-email.blade.php:
Hey, {{$name}} and welcome 😉

<br>
Funny Coder
  • Add the CLI router to the app/routes/console.php file:
<?php

use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Mail;

/*
|--------------------------------------------------------------------------
| Console Routes
|--------------------------------------------------------------------------
|
*/

Artisan::command('send-welcome-mail', function () {
    Mail::to('testreceiver@gmail.com')->send(new WelcomeMail("Jon"));
    // Also, you can use a specific mailer if your default mailer is not "mailtrap", but you want to use it for welcome emails
    // Mail::mailer('mailtrap')->to('testreceiver@gmail.com')->send(new WelcomeMail("Jon"));
})->purpose('Send welcome mail');
  • Run the CLI command, which will send your email:
php artisan send-welcome-mail

And that’s it! Mailtrap Email Sending API is now integrated with your Laravel app.

Testing emails before sending: why and how?

For some, the process of setting up the email-sending functionality in their Laravel app stops when the email-sending code has been written. For others, who take the more cautious route, this process also involves adding email testing as a crucial pre-sending step.

Through email testing, you get to check how your emails get rendered by web browsers as well as how responsive they are. You can also check the spam score, search for your domain/IP on blacklists, and do even more if you have the proper email testing tool.

An email testing tool that comes with all the mentioned features and others as well, such as the creation of virtual inboxes for different projects and project stages, insight into detailed tech info (email headers and SMTP transaction data), and so on, is Mailtrap Email Testing

Mailtrap Email Testing is a solution that enables you to inspect and debug emails in staging, dev, and QA environments before sending them to recipients. This way, it creates a safe environment for email testing that bears no risk of spamming recipients in the process.

The solution comes with ready-to-use integrations in 20+ languages, user management, and SSO. 

And what about getting started with Mailtrap Email Testing? That takes just five minutes and consists of the following steps:

  • Create a Mailtrap account and log in. 
  • In your account, navigate to Email Testing – > Inboxes – > SMTP Settings.
  • Select Laravel from the list of integrations.
  • Copy the integration code generated and paste it into your email-sending script.
  • Run the script and receive the first test email in your virtual inbox shortly, where you can test and debug it.

Note: When testing, you don’t have to use real sender or receiver email addresses as the test emails are being sent to virtual inboxes, and email verification is not being done.

Mailtrap Email Testing also offers SMTP credentials for each of your virtual inboxes, which can be accessed by clicking “Show Credentials” on the SMTP Settings page. So, if you prefer using credentials over code snippets for integrating this testing solution, simply copy and paste these into your email-sending script, MTA settings, email client settings, or any other system that supports them.

Wrapping things up

Laravel and Gmail have two major things in common – widespread usage and lots of educational resources. Hopefully, this article will now serve as your go-to resource for learning how to use Laravel to send email through Gmail or a great alternative like Mailtrap Email Sending. 

To further expand your knowledge on using this framework for email sending, testing, verification, and more, make sure to check out a couple of our other articles:

Article by Dzenana Kajtaz Technical Content Writer @Mailtrap

I’m a Technical Content Writer with an educational background in software engineering and 4 years of experience as a writer, editor, and content marketer. Currently, I mainly focus on writing about email infrastructure, sending, testing, and so on, but I do love creating fun and engaging content on email marketing topics as well.