Tutorial

Transactionele e-mail met Laravel

Laravel heeft een volwassen mail-stack: Mailable-klassen, Blade-templates, queues en ingebouwde foutafhandeling. In deze tutorial configureer je SMTP via Wesender en verstuur je je eerste transactionele mail.

Wat je nodig hebt

  • Laravel 10 of nieuwer
  • Een Wesender-account en een API-key
  • Een geverifieerd verzenddomein
Laravel Symfony Node.js
1
Stap 1

.env configureren

Voeg de SMTP-instellingen toe aan je .env-bestand:

.env
MAIL_MAILER=smtp
MAIL_HOST=smtp.wesender.nl
MAIL_PORT=587
MAIL_USERNAME=jouw-api-key
MAIL_PASSWORD=jouw-api-key
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="noreply@joudomein.nl"
MAIL_FROM_NAME="${APP_NAME}"
Gebruik poort 587 met TLS (STARTTLS). Poort 465 met SSL werkt ook. Combineer ze niet: 587 met SSL of 465 met TLS geeft verbindingsfouten. Sla de API-key op als omgevingsvariabele, nooit hard-coded.
2
Stap 2

Een Mailable aanmaken

terminal
php artisan make:mail WelkomstMail

Laravel genereert app/Mail/WelkomstMail.php. De moderne opzet gebruikt envelope(), content() en attachments():

app/Mail/WelkomstMail.php
<?php

namespace App\Mail;

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

class WelkomstMail extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(public User $user) {}

    public function envelope(): Envelope
    {
        return new Envelope(subject: 'Welkom bij ' . config('app.name'));
    }

    public function content(): Content
    {
        return new Content(view: 'emails.welkomst');
    }

    public function attachments(): array
    {
        return [];
    }
}
3
Stap 3

De Blade-template

Maak resources/views/emails/welkomst.blade.php aan:

resources/views/emails/welkomst.blade.php
<!DOCTYPE html>
<html lang="nl">
<head><meta charset="UTF-8"><title>Welkom</title></head>
<body style="font-family: sans-serif; color: #1a1a1a; padding: 2rem;">
  <h1>Hoi {{ $user->name }},</h1>
  <p>Welkom. Je account is klaar om te gebruiken.</p>
  <a href="{{ url('/dashboard') }}" style="color: #10b981;">Naar het dashboard</a>
</body>
</html>
Publieke properties van de Mailable zijn automatisch beschikbaar als $user in de template.
4
Stap 4

Versturen vanuit je applicatie

controller of listener
use App\Mail\WelkomstMail;
use Illuminate\Support\Facades\Mail;

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

Gebruik render() of geef de Mailable terug vanuit een route om de mail in de browser te bekijken:

routes/web.php (alleen lokaal)
Route::get('/preview/welkomst', function () {
    return new WelkomstMail(auth()->user());
});
5
Stap 5

In de wachtrij zetten

Laat de Mailable ShouldQueue implementeren voor asynchrone verzending:

app/Mail/WelkomstMail.php
use Illuminate\Contracts\Queue\ShouldQueue;

class WelkomstMail extends Mailable implements ShouldQueue
{
    use Queueable, SerializesModels;
    // ...
}

Zet QUEUE_CONNECTION niet op sync in productie. Start daarna de worker:

terminal
php artisan queue:work
Verstuur je mail binnen een database-transactie, gebruik dan afterCommit() zodat de job pas na de commit vertrekt:
gebruik
Mail::to($user->email)->afterCommit()->send(new WelkomstMail($user));
6
Stap 6

Foutafhandeling

Definieer een failed()-methode op de Mailable voor queued mail:

app/Mail/WelkomstMail.php
public function failed(Throwable $e): void
{
    Log::error('Mail versturen mislukt', [
        'to'    => $this->user->email,
        'error' => $e->getMessage(),
    ]);
}
7
Stap 7

Testen

Start Tinker en verstuur een testmail:

terminal
php artisan tinker
Mail::to('test@voorbeeld.nl')->send(new \App\Mail\WelkomstMail(App\Models\User::first()));
Check daarna je Wesender-dashboard voor de verzendlog.