We're hiring! Check out open positions
Development

Sending Emails in Laravel: Mailable Classes, Templates & Laravel Versions

Tim Davidson
8 min read

For creating apps with PHP, software engineers may choose Laravel, a PHP framework that optimizes emailing processes. Laravel allows you to manage email previews, has various options for localization, and ensures that real users never see test emails in their inboxes.

The available documentation and tutorials cover most of the questions on managing emails in Laravel. Still, new releases and constant updates may cause questions. So let's go through the most frequent ones: how to send emails in Laravel, and manage mailable classes and Blade templates.

Сreating Mailable Class

Each type of email sent in Laravel is presented as a mailable class. It is stored in app/Mail directory that is automatically generated as soon as the class is created using the make:mail Artisan command:

php artisan make:mail OrderShipped

Configuration for mailables is done in several methods — envelope, content, and attachments.

Configuring The Sender

Using The Envelope

In Laravel, we have two ways to configure the sender.

Firstly, it may be specified on the message's envelope:

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('jeffrey@example.com', 'Jeffrey Way'),

        subject: 'Order Shipped',

    );

}

Using a Global from Address

When your application has the same sender address for all the emails, you may specify an address in the config/mail.php configuration file. If there is no fixed "from" address within the mailable class, the system will use this one:

\*\*'from' => \['address' => 'example@example.com', 'name' => 'App Name'],\*\

Use global "reply_to" address within config/mail.php file:

\*\*'reply_to' => \['address' => 'example@example.com', 'name' => 'App Name'],\*\*

Configuring The View

You may define the view or the template needed to be used when rendering the email's contents within the content method:

/\*\*

\* Get the message content definition.

\*

\* @return \Illuminate\Mail\Mailables\Content

\*/

public function content()

{

    return new Content(

        view: 'emails.orders.shipped',

    );

}

Plain Text Emails

Specify the plain-text template when creating the Content definition to define a plain-text version of an email:

/\*\*

\* Get the message content definition.

\*

\* @return \Illuminate\Mail\Mailables\Content

\*/

public function content()

{

    return new Content(

        view: 'emails.orders.shipped',

        text: 'emails.orders.shipped-text'

    );

}

You may use the html parameter as an alias of the view parameter:

return new Content(

    html: 'emails.orders.shipped',

    text: 'emails.orders.shipped-text'

);

View Data

You may use one of two to view data:

Via Public Properties

Any public property defined on the mailable class will be available to view automatically.

For instance, pass data into the constructor and set that data to public properties:

<?php

namespace App\\\\Mail;

use App\\\\Models\\\\Order;

use Illuminate\\\\Bus\\\\Queueable;

use Illuminate\\\\Mail\\\\Mailable;

use Illuminate\\\\Mail\\\\Mailables\\\\Content;

use Illuminate\\\\Queue\\\\SerializesModels;

class OrderShipped extends Mailable

{

    use Queueable, SerializesModels;

    /\\\\*\\\\*

     \\\\* The order instance.

     \\\\*

     \\\\* @var \\\\App\\\\Models\\\\Order

     \\\\*/

    public $order;

    /\\\\*\\\\*

     \\\\* Create a new message instance.

     \\\\*

     \\\\* @param  \\\\App\\\\Models\\\\Order  $order

     \\\\* @return void

     \\\\*/

    public function \_\_construct(Order $order)

    {

        $this->order = $order;

    }

    /\\\\*\\\\*

     \\\\* Get the message content definition.

     \\\\*

     \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Content

     \*/

    public function content()

    {

        return new Content(

            view: 'emails.orders.shipped',

        );

    }

}

When the data is set to public property, you may access it:

<div>

    Price: {{ $order->price }}

</div>

Via The with Parameter

When you need to customize the email's data format before it is delivered to the template, pass the data manually to view via the Content definitions with parameter.

Set the data to protected or private properties, and the data will no longer be automatically available to the template:

<?php

namespace App\\\\Mail;

use App\\\\Models\\\\Order;

use Illuminate\\\\Bus\\\\Queueable;

use Illuminate\\\\Mail\\\\Mailable;

use Illuminate\\\\Mail\\\\Mailables\\\\Content;

use Illuminate\\\\Queue\\\\SerializesModels;

class OrderShipped extends Mailable

{

    use Queueable, SerializesModels;

    /\\\\*\\\\*

     \\\\* The order instance.

     \\\\*

     \\\\* @var \\\\App\\\\Models\\\\Order

     \\\\*/

    protected $order;

    /\\\\*\\\\*

     \\\\* Create a new message instance.

     \\\\*

     \\\\* @param  \\\\App\\\\Models\\\\Order  $order

     \\\\* @return void

     \\\\*/

    public function \_\_construct(Order $order)

    {

        $this->order = $order;

    }

    /\\\\*\\\\*

     \\\\* Get the message content definition.

     \\\\*

     \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Content

     \*/

    public function content()

    {

        return new Content(

            view: 'emails.orders.shipped',

            with: \\\\[

                'orderName' => $this->order->name,

                'orderPrice' => $this->order->price,

            \],

        );

    }

}

You may access it as soon as it is passed to the withmethod:

<div>

    Price: {{ $orderPrice }}

</div>

Attachments

To add attachments to an email, add them to the array returned by the attachments method.

Firstly, add an attachment — provide a path to the fromPath method:

use Illuminate\\\\Mail\\\\Mailables\\\\Attachment;

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromPath('/path/to/file'),

    \];

}

While attaching files, specify the display name or MIME type — use the as and withMime methods:

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromPath('/path/to/file')

                ->as('name.pdf')

                ->withMime('application/pdf'),

    \];

}

Attaching Files From Disk

Attach files from [filesystem disks](https://www.google.com/url?q=https://laravel.com/docs/9.x/filesystem&sa=D&source=editors&ust=1666940498658446&usg=AOvVaw0KAShE-20ew6jIprRNyup5) using the fromStorage attachment method:

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromStorage('/path/to/file'),

    \];

}

Additionally, specify the name and MIME type for the attachment:

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromStorage('/path/to/file')

                ->as('name.pdf')

                ->withMime('application/pdf'),

    \];

}

To specify a storage disk use fromStorageDisk method:

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromStorageDisk('s3', '/path/to/file')

                ->as('name.pdf')

                ->withMime('application/pdf'),

    \];

}

Raw Data Attachments

To attach raw data, use fromData method:

/\\\\*\\\\*

 \\\\* Get the attachments for the message.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Attachment\\\\[\]

 \\\\*/

public function attachments()

{

    return \\\\[

        Attachment::fromData(fn () => $this->pdf, 'Report.pdf')

                ->withMime('application/pdf'),

    \];

}

Inline Attachments

To embed an image, use the embed method.

The system automatically makes the $message variable for all templates:

<body>

    Here is an image:

    <img src="{{ $message->embed($pathToImage) }}">

</body>

Headers

To attach additional headlines, define a headers method. It will return Illuminate\\\\Mail\\\\Mailables\\\\Headers instance:

use Illuminate\\\\Mail\\\\Mailables\\\\Headers;

/\\\\*\\\\*

 \\\\* Get the message headers.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Headers

 \\\\*/

public function headers()

{

    return new Headers(

        messageId: 'custom-message-id@example.com',

        references: \\\\['previous-message@example.com'\],

        text: \\\\[

            'X-Custom-Header' => 'Custom Value',

        \],

    );

}

Tags & Metadata

Add tags and metadata via Envelope definition:

use Illuminate\\\\Mail\\\\Mailables\\\\Envelope;

/\\\\*\\\\*

 \\\\* Get the message envelope.

 \\\\*

 \\\\* @return \\\\Illuminate\\\\Mail\\\\Mailables\\\\Envelope

 \\\\*/

public function envelope()

{

    return new Envelope(

        subject: 'Order Shipped',

        tags: \\\\['shipment'\],

        metadata: \\\\[

            'order\_id' => $this->order->id,

        \],

    );

}

Working with Laravel Mail

Creating the Laravel Email Template

With Laravel, you can create templates, including buttons, tables, and panels — a rare feature for other frameworks' markdown support. The template is a fully customizable Blade file.

Template files use the .blade.php extension. They are stored in the resources/views directory.

To return Blade views from routes or controllers, use view helper

Displaying Data

To display data, use the route:

Route::get('/', function () {

    return view('welcome', \\\['name' => 'Samantha']);

});

Display the contents of the name variable:

Hello, {{ $name }}.

HTML Entity Encoding

To disable double encoding, use the Blade::withoutDoubleEncoding method from the boot method of AppServiceProvider:

<?php

namespace App\\\\Providers;

use Illuminate\\\\Support\\\\Facades\\\\Blade;

use Illuminate\\\\Support\\\\ServiceProvider;

class AppServiceProvider extends ServiceProvider

{

    /\\\\\*\\\\\*

     \\\\\* Bootstrap any application services.

     \\\\\*

     \\\\\* @return void

     \\\\\*/

    public function boot()

    {

        Blade::withoutDoubleEncoding();

    }

}

Sending an email with Laravel

To send an email in Laravel, use one of the API-based drivers: Mailgun, SparkPost,  Amazon SES or [Mailtrap email API](https://www.google.com/url?q=https://mailtrap.io/email-api/&sa=D&source=editors&ust=1666940498671915&usg=AOvVaw12QVyaEmDc60C71AiPBiAR). You may set a default driver in a mail configuration file and manage particular types of messages with SparkPost:

Mail::mailer('sparkpost')

\->to($emailAddress())

\->send(new NewUserNotification));

Sending Emails Through Laravel using SMTP

You may use any SMTP server, Gmail, for instance. All the configurations are in config/mail.php file.

Laravel recommends using the Mailtrap SMTP server. It ensures that the actual users will never get a test email — to send a message to real users, change the configuration:

MAIL_MAILER=smtp

MAIL_HOST=smtp.googlemail.com

MAIL_PORT=465

MAIL_USERNAME=youremail@gmail.com

MAIL_PASSWORD=your password

MAIL_ENCRYPTION=ssl

Integrate Mailtrap with Laravel

Laravel did work with Mailtrap simple. There is a default Mailtrap server, so you only need to enter credentials. Use Cloudways Managed Hosting Platform to install Laravel and paste the configurations in the .env file.

1ubiugu

MAIL_DRIVER=smtp

MAIL_HOST=smtp.mailtrap.io

MAIL_PORT=2525

MAIL_USERNAME= //your username generated by Mailtrap

MAIL_PASSWORD= // your password generated by Mailtrap

MAIL_FROM_ADDRESS=from@example.com

MAIL_FROM_NAME=Example

Laravel Versions

Laravel releases a new version every year. All the versions designated LTS are supported with security fixes for three years and bug fixes for two years.

The 9th version of Laravel was released on February 8, 2022. The 8th version is still maintained; older ones are not updated or maintained. The 10th version may be released on February 7, 2023.

Tim Davidson
Tim Davidson
Tim is the face of the company. When you want to kick off a new project, or an update on your existing project, Tim is your man. With a background in project management, Tim specialises in managing the chaos around the company.

Have an idea you want to discuss?

We’re based in Canberra, Australia and we LOVE working with locals… but we work with clients all around the world.

From the U.S. to the U.K. From Norway to New Zealand. Where there’s a problem to solve, we’ll be there!

More insights from us

MACH architecture - The ultimate growth play
Development

MACH architecture - The ultimate growth play

MACH architecture has become a red-hot trend in the enterprise world for the past few years. It's an abbreviation of…
Tim Davidson
Tim Davidson
10 min read
Next.js vs Gatsby.js - Which Is The Best React Framework?
Development

Next.js vs Gatsby.js - Which Is The Best React Framework?

Next.js and Gatsby are two of the most popular static site generators used to build fast and SEO-friendly websites. They…
Tim Davidson
Tim Davidson
9 min read
The Pros and Cons of Headless Commerce - The Double Edged Sword
Development

The Pros and Cons of Headless Commerce - The Double Edged Sword

Our team recently jumped in to help a headless eCommerce project that was heading in the wrong direction. The team had…
Tim Davidson
Tim Davidson
11 min read