Skip to main content
Sending Email

Sending Email

Laravel's mail layer separates the message definition from the transport. You define a mailable class and a Blade view, then send through SMTP, a local log driver, or a transactional provider.

Configuration

MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=mailer@example.com
MAIL_PASSWORD=secret
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@example.com
MAIL_FROM_NAME="Acme"

During development, set MAIL_MAILER=log to write messages to the log, or use a local mail catcher. Testing against real addresses risks sending accidental messages to customers.

Creating a mailable

php artisan make:mail OrderShipped --markdown=mail.orders.shipped
namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    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(
            markdown: 'mail.orders.shipped',
            with: ['trackingUrl' => $this->order->tracking_url],
        );
    }
}

Sending

use Illuminate\Support\Facades\Mail;

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

Mail::to($user)->cc($accountant)->send(new InvoiceReady($invoice));

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

queue() hands the message to the queue worker so the web request does not wait for SMTP. Configure a queue driver and run a worker before relying on it.

Markdown mail

Markdown mailables produce responsive HTML and a plain-text alternative. Components such as buttons, panels, and tables keep messages consistent across clients.

@component('mail::message')
# Hello {{ $user->name }}

Your order is on its way.

@component('mail::button', ['url' => $trackingUrl])
Track package
@endcomponent

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

Attachments

public function attachments(): array
{
    return [
        Attachment::fromStorage('invoices/'.$this->invoice->id.'.pdf')
            ->as('invoice.pdf')
            ->withMime('application/pdf'),
    ];
}

Localization and templates

Mailables are normal classes, so they can use the recipient's locale. Set the locale before sending and pass translated strings into the view.

Deliverability basics

  • Use a verified sending domain with SPF, DKIM, and DMARC records.
  • Send from a monitored address and set a reply-to when appropriate.
  • Keep transactional and marketing mail on separate streams.
  • Handle bounces and complaints through your provider's webhooks.