Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Mail and notifications

A registration confirmation, a receipt after payment, an abandoned-cart reminder — almost every site needs email. In Laravel a message is described by a class and a Blade template, and settings decide how it is delivered.

Configuration

The mail server parameters live in .env:

MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=robot@example.com
MAIL_PASSWORD=secret
MAIL_FROM_ADDRESS=robot@example.com
MAIL_FROM_NAME="My blog"

During development the value MAIL_MAILER=log is handy: messages are not sent but written to the storage/logs/laravel.log log.

The message class

php artisan make:mail OrderShipped
namespace App\Mail;
 
use App\Models\Order;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
 
class OrderShipped extends Mailable
{
    public function __construct(public Order $order) {}
 
    public function envelope(): Envelope
    {
        return new Envelope(subject: 'Your order has shipped');
    }
 
    public function content(): Content
    {
        return new Content(view: 'mail.order-shipped');
    }
}

The public properties of the class are available in the template.

The template

{{-- resources/views/mail/order-shipped.blade.php --}}
<h1>Order #{{ $order->id }} has shipped</h1>
 
<p>Total: ${{ $order->total }}</p>
 
<a href="{{ route('orders.show', $order) }}">View the order</a>

Sending

use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;
 
Mail::to($order->user)->send(new OrderShipped($order));

to() accepts an address as a string or a user model — Laravel takes its email property.

Through a queue

Connecting to a mail server takes seconds. The queue() method sends the message in the background:

Mail::to($order->user)->queue(new OrderShipped($order));

Notifications

A notification is a message that can be delivered in several ways at once: by email, into the database for a bell on the site, to a messenger:

php artisan make:notification InvoicePaid
namespace App\Notifications;
 
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
 
class InvoicePaid extends Notification
{
    public function __construct(public int $amount) {}
 
    public function via(object $notifiable): array
    {
        return ['mail', 'database'];
    }
 
    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject('Invoice paid')
            ->line("We received your payment: \${$this->amount}.")
            ->action('Open the invoice', url('/invoices'));
    }
 
    public function toArray(object $notifiable): array
    {
        return ['amount' => $this->amount];
    }
}

It is sent with a method of the user model:

$user->notify(new InvoicePaid(1500));
 
$unread = $user->unreadNotifications;

Common mistake

A message sent during the request delays the response, and if the mail server fails the user sees an error instead of the "Order placed" page. Send mail through a queue — queue() instead of send() — and check how it looks without real delivery, with MAIL_MAILER=log.

Thanks for reading!

Donate to the site — we work hard for you.