sajad torkamani

In a nutshell

Laravel provides a clean, simple email API powered by the popular Symfony Mailer component. Laravel and Symfony Mailer provide drivers for sending email via SMTP, Mailgun, Postmark, Resend, Amazon SES, and sendmail, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

Configuration

Laravel’s email services may be configured via your application’s config/mail.php configuration file. Each mailer configured within this file may have its own unique configuration and even its own unique “transport”, allowing your application to use different email services to send certain email messages. For example, your application might use Postmark to send transactional emails while using Amazon SES to send bulk emails.

Within your mail configuration file, you will find a mailers configuration array. This array contains a sample configuration entry for each of the major mail drivers / transports supported by Laravel, while the default configuration value determines which mailer will be used by default when your application needs to send an email message.

Generate Mailables

When building Laravel applications, each type of email sent by your application is represented as a “mailable” class. These classes are stored in the app/Mail directory. 

php artisan make:mail OrderShipped

Writing Mailables

Once you have generated a mailable class, open it up so we can explore its contents. Mailable class configuration is done in several methods, including the envelopecontent, and attachments methods.

  • envelope: The envelope method returns an Illuminate\Mail\Mailables\Envelope object that defines the subject and, sometimes, the recipients of the message.
  • content: The content method returns an Illuminate\Mail\Mailables\Content object that defines the Blade template that will be used to generate the message content.

Configuring the Sender

You can configure the sender in two ways:

  1. Using the Envelope
  2. Using a Global from Address

Configure HTML view

/**
 * Get the message content definition.
 */
public function content(): Content
{
    return new Content(
        view: 'mail.orders.shipped',
    );
}

Configure Text view

return new Content(
    html: 'mail.orders.shipped',
    text: 'mail.orders.shipped-text'
);

Pass data to views

Via 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;
 
    /**
     * Create a new message instance.
     */
    public function __construct(
        public Order $order,
    ) {}
 
    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'mail.orders.shipped',
        );
    }
}

Via the with parameter

<?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;
 
    /**
     * Create a new message instance.
     */
    public function __construct(
        protected Order $order,
    ) {}
 
    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        return new Content(
            view: 'mail.orders.shipped',
            with: [
                'orderName' => $this->order->name,
                'orderPrice' => $this->order->price,
            ],
        );
    }
}

Generate Markdown Mailables

php artisan make:mail OrderShipped --markdown=mail.orders.shipped
use Illuminate\Mail\Mailables\Content;
 
/**
 * Get the message content definition.
 */
public function content(): Content
{
    return new Content(
        markdown: 'mail.orders.shipped',
        with: [
            'url' => $this->orderUrl,
        ],
    );
}

Send mail

To send a message, use the to method on the Mail facade. The to method accepts an email address, a user instance, or a collection of users. If you pass an object or collection of objects, the mailer will automatically use their email and name properties when determining the email’s recipients, so make sure these attributes are available on your objects. Once you have specified your recipients, you may pass an instance of your mailable class to the send method:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
 
class OrderShipmentController extends Controller
{
    /**
     * Ship the given order.
     */
    public function store(Request $request): RedirectResponse
    {
        $order = Order::findOrFail($request->order_id);
 
        // Ship the order...
 
        Mail::to($request->user())->send(new OrderShipped($order));
 
        return redirect('/orders');
    }
}

Queue a mail

1. Call Mail#queue()

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue(new OrderShipped($order));

This method will automatically take care of pushing a job onto the queue so the message is sent in the background. You will need to configure your queues before using this feature.

2. Make your Mailable class implement the ShouldQueue contract

use Illuminate\Contracts\Queue\ShouldQueue;
 
class OrderShipped extends Mailable implements ShouldQueue
{
    // ...
}

Queue a mail to be sent after a delay

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->later(now()->addMinutes(10), new OrderShipped($order));

Render a Mailable without sending it

use App\Mail\InvoicePaid;
use App\Models\Invoice;
 
$invoice = Invoice::find(1);
 
return (new InvoicePaid($invoice))->render();

Preview Mailables in the browser

Route::get('/mailable', function () {
    $invoice = App\Models\Invoice::find(1);
 
    return new App\Mail\InvoicePaid($invoice);
});

Sources & further reading

Tagged: Laravel