Laravel Mailable : Comment Créer et Envoyer des Emails ?

developpeur-ecran-code-bureau-moderne

Vous avez besoin d’envoyer des emails depuis votre application Laravel ? Vous cherchez comment utiliser les Mailables de manière propre et efficace ? Que ce soit pour une confirmation d’inscription, une notification de commande ou un formulaire de contact, c’est une fonction de base pour toute application web.

Ce guide vous explique tout de A à Z. Vous allez apprendre comment configurer, créer, et envoyer des emails avec Laravel Mailable, en suivant les bonnes pratiques. On couvrira aussi les options plus avancées comme les pièces jointes et la mise en file d’attente pour ne pas ralentir votre application.

Prérequis : Configurer Votre Transporteur d’Emails

Avant d’écrire la moindre ligne de code pour un email, il faut dire à Laravel comment il doit les envoyer. C’est l’étape de la configuration. Tout se passe principalement dans un seul fichier : .env. C’est là que vous mettez les informations de connexion à votre service d’envoi.

Depuis les versions récentes de Laravel, tout le système de mail repose sur le composant Symfony Mailer. C’est un moteur puissant et fiable qui gère l’envoi pour vous. Vous n’avez qu’à lui donner les bons réglages dans votre fichier de configuration .env à la racine de votre projet.

Les variables les plus importantes sont :

  • MAIL_MAILER: C’est le service que vous allez utiliser (smtp, log, mailgun…).
  • MAIL_HOST: L’adresse du serveur de votre service (ex: smtp.mailgun.org).
  • MAIL_PORT: Le port de connexion (ex: 587).
  • MAIL_USERNAME: Votre nom d’utilisateur.
  • MAIL_PASSWORD: Votre mot de passe ou clé API.
  • MAIL_ENCRYPTION: Le type de chiffrement (tls, ssl).
  • MAIL_FROM_ADDRESS: L’adresse email qui apparaîtra comme expéditeur.
  • MAIL_FROM_NAME: Le nom qui apparaîtra comme expéditeur.

Voici un tableau simple pour comprendre les principaux drivers et quand les utiliser.

Driver Usage Principal Avantage Clé
log Développement N’envoie aucun email, écrit le contenu dans vos fichiers de log. Rapide et sûr pour le dev.
smtp Production simple Standard, fonctionne avec presque tous les hébergeurs et services mail (Gmail, OVH…).
Mailtrap / Mailpit Test visuel Capture tous les emails dans une boîte de réception virtuelle. Idéal pour voir le rendu sans spammer.
Mailgun / SES Production à volume Services API très fiables pour envoyer des milliers d’emails, avec suivi des ouvertures, clics, etc.
Configuration SMTP simple pour débuter

Pour la plupart des projets qui démarrent, une configuration SMTP standard est suffisante. Voici un exemple pour votre fichier .env :

MAIL_MAILER=smtp
MAIL_HOST=smtp.votreserveur.com
MAIL_PORT=587
MAIL_USERNAME="votre_username"
MAIL_PASSWORD="votre_password"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

Pensez à remplacer les valeurs par vos propres informations.

Pour le développement en local, la meilleure pratique est de ne jamais envoyer de vrais emails. Utilisez le driver log si vous voulez juste vérifier que l’envoi est déclenché. Le contenu de l’email sera écrit dans storage/logs/laravel.log.

Mais le mieux, c’est d’utiliser un outil comme Mailtrap ou Mailpit. Ils simulent un serveur SMTP et capturent tous les emails dans une interface web. Ça vous permet de voir exactement à quoi ressemblera votre email final sans envoyer un seul vrai message.

Étape 1 : Créer Votre Première Classe Mailable

Laravel a une approche très propre pour gérer les emails. L’idée est simple : une classe représente un type d’email. Par exemple, si vous avez un email de bienvenue et un email de réinitialisation de mot de passe, vous créerez deux classes : WelcomeEmail.php et PasswordResetEmail.php.

Pour créer une nouvelle classe Mailable, on utilise une commande Artisan. C’est rapide et ça met en place toute la structure pour vous. Ouvrez votre terminal et tapez :

php artisan make:mail OrderShipped

Cette commande va créer un nouveau fichier dans votre application : app/Mail/OrderShipped.php. C’est dans ce fichier que vous allez définir tout ce qui concerne cet email : son sujet, son expéditeur et son contenu.

Voici à quoi ressemble le fichier généré. C’est une base de travail simple et claire.

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
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;

    /**
     * Create a new message instance.
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Order Shipped',
        );
    }

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

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [];
    }
}

Étape 2 : Anatomie d’un Mailable – Construire Votre Message

Maintenant que la classe est créée, il faut la remplir. La construction d’un email dans une classe Mailable se divise en deux parties principales : l’enveloppe (qui, à qui, sujet) et le contenu (le corps du message).

Ces deux aspects sont gérés par les méthodes envelope() et content().

Définir l’enveloppe : Expéditeur et Sujet (envelope)

La méthode envelope() sert à définir les métadonnées de l’email. Les deux plus importantes sont l’expéditeur (from) et le sujet (subject). Si vous ne définissez pas de from ici, Laravel utilisera celui configuré dans votre fichier .env.

Voici comment configurer le sujet et un expéditeur spécifique :

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

public function envelope(): Envelope
{
    return new Envelope(
        from: new Address('[email protected]', 'Support Technique'),
        subject: 'Votre commande a été expédiée',
    );
}

C’est tout. Le message aura maintenant un sujet clair et un expéditeur précis.

Définir le contenu : La Vue Blade (content)

La méthode content() définit le corps de votre email. La manière la plus simple et la plus puissante de le faire est d’utiliser une vue Blade. C’est exactement comme créer une page web, mais pour un email. Vous pouvez utiliser toute la puissance de Blade : variables, boucles, conditions, etc.

Vous devez indiquer à Laravel quel fichier de vue utiliser. Par exemple, si on veut utiliser une vue qui se trouve dans resources/views/emails/orders/shipped.blade.php, on l’indique comme ceci :

use Illuminate\Mail\Mailables\Content;

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

Maintenant, créons ce fichier. Allez dans resources/views, créez un dossier emails, puis un sous-dossier orders, et enfin le fichier shipped.blade.php. Le contenu peut être du HTML simple :

<!DOCTYPE html>
<html>
<head>
    <title>Commande expédiée</title>
</head>
<body>
    <h1>Bonjour !</h1>
    <p>Bonne nouvelle, votre commande a été expédiée et est en route.</p>
</body>
</html>

Passer des Données à la Vue

Un email statique, c’est bien, mais souvent on a besoin d’afficher des informations dynamiques, comme le nom du client ou le numéro de commande. C’est très simple avec les Mailables.

La méthode standard est de déclarer des propriétés publiques sur votre classe Mailable et de les initialiser dans le constructeur (__construct). Laravel rendra automatiquement ces propriétés publiques disponibles dans votre vue Blade.

Imaginons que vous voulez passer un objet Order à votre email. Modifiez votre classe OrderShipped :

<?php

namespace App\Mail;

// ... autres use ...
use App\Models\Order; // N'oubliez pas d'importer votre modèle

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * L'instance de la commande.
     *
     * @var \App\Models\Order
     */
    public function __construct(
        public Order $order,
    ) {}

    // ... méthodes envelope() et content() ...
}

Avec cette syntaxe (PHP 8+), la propriété $order est déclarée et initialisée en une seule fois. C’est propre et concis.

Maintenant, vous pouvez utiliser cette variable $order directement dans votre vue shipped.blade.php :

<!DOCTYPE html>
<html>
<head>
    <title>Commande expédiée</title>
</head>
<body>
    <h1>Bonjour {{ $order->user->name }} !</h1>
    <p>Bonne nouvelle, votre commande N°{{ $order->id }} a été expédiée.</p>
    <p>Elle sera livrée à l'adresse suivante : {{ $order->shipping_address }}</p>
</body>
</html>

Toute propriété publique que vous définissez dans votre Mailable sera automatiquement accessible dans le template Blade. C’est cette simplicité qui rend le système si agréable à utiliser.

Étape 3 : Envoyer Votre Email

Une fois votre classe Mailable configurée, l’envoyer est un jeu d’enfant. On utilise la façade Mail de Laravel. Le plus souvent, vous ferez ça depuis un contrôleur, après une action de l’utilisateur (comme valider une commande).

La syntaxe de base est très lisible. Vous spécifiez le destinataire avec la méthode to(), puis vous envoyez votre Mailable avec la méthode send().

<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;

class OrderController extends Controller
{
    public function ship(Order $order)
    {
        // ... logique pour expédier la commande ...

        // Envoyer l'email de notification
        Mail::to($order->user->email)->send(new OrderShipped($order));

        return redirect('/orders')->with('status', 'Commande expédiée !');
    }
}

Ici, on récupère l’email de l’utilisateur associé à la commande et on lui envoie une nouvelle instance de notre Mailable OrderShipped. Notez qu’on passe l’objet $order au constructeur, comme on l’a défini plus tôt.

Envoyer à plusieurs personnes (to, cc, bcc)

Vous pouvez aussi envoyer un email à plusieurs destinataires, ou mettre des gens en copie (cc) et en copie cachée (bcc).

Les méthodes cc() et bcc() peuvent recevoir une adresse email, un utilisateur, ou un tableau de plusieurs adresses/utilisateurs.

Aller plus loin avec les Mailables

Laravel Mailable ne s’arrête pas là. Il propose des fonctionnalités avancées pour gérer des cas d’usage plus complexes, comme l’ajout de pièces jointes ou l’optimisation des performances avec les files d’attente.

Ajouter des Pièces Jointes (attachments)

Pour joindre un fichier à votre email, il suffit d’utiliser la méthode attachments() de votre classe Mailable. Elle doit retourner un tableau d’objets Attachment.

Il y a deux manières principales de joindre un fichier :

  • Depuis un chemin sur le disque (fromPath) : C’est le cas le plus courant, par exemple pour joindre une facture PDF qui a été générée et sauvegardée.
  • Depuis des données brutes en mémoire (fromData) : Utile si vous générez le contenu du fichier à la volée sans le sauvegarder sur le disque.

Voici un exemple pour joindre une facture PDF depuis le disque de stockage :

use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Support\Facades\Storage;

public function attachments(): array
{
    return [
        Attachment::fromPath(Storage::path('invoices/invoice-123.pdf'))
            ->as('facture.pdf')
            ->withMime('application/pdf'),
    ];
}

Avec la méthode fromPath, vous fournissez le chemin absolu du fichier. La méthode as() permet de définir le nom du fichier qui sera vu par le destinataire.

Gagner en Performance : Mettre les Emails en File d’Attente (queue)

Envoyer un email via SMTP peut prendre du temps (parfois plusieurs secondes). Pendant ce temps, votre utilisateur attend une réponse de votre serveur. Ce n’est pas une bonne expérience. Pour éviter ça, on peut mettre l’envoi d’email dans une file d’attente (queue).

Le principe est simple : au lieu d’envoyer l’email tout de suite, Laravel va juste enregistrer une « tâche d’envoi d’email » dans une base de données ou un service comme Redis. Un processus séparé (un worker) viendra ensuite récupérer cette tâche et enverra l’email en arrière-plan. Pour l’utilisateur, la réponse est quasi instantanée.

Pour rendre un Mailable « queueable », il suffit de lui faire implémenter l’interface ShouldQueue.

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; // <-- L'importer
use Illuminate\Mail\Mailable;
// ...

class OrderShipped extends Mailable implements ShouldQueue // <-- L'implémenter
{
    use Queueable, SerializesModels;
    
    // ...
}

Ensuite, au lieu d’utiliser la méthode send(), vous utiliserez la méthode queue() :

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

Et c’est tout ! Laravel s’occupe du reste. Attention, cela nécessite que vous ayez configuré un driver de file d’attente (comme `database` ou `redis`) et que vous ayez un worker qui tourne en permanence (`php artisan queue:work`).

Utiliser Markdown pour des Emails Responsives

Écrire du HTML pour les emails peut être compliqué, surtout pour qu’ils s’affichent bien sur tous les clients mail (Outlook, Gmail, mobile…). Laravel propose une solution : les emails Markdown.

Vous écrivez le contenu de votre email en Markdown, une syntaxe très simple, et Laravel se charge de le convertir en un template HTML responsive et propre. Il génère même automatiquement une version texte brut pour les clients mail qui ne supportent pas le HTML.

Pour créer un Mailable en Markdown, utilisez l’option --markdown lors de la création :

php artisan make:mail OrderShipped --markdown=emails.orders.shipped

La méthode content() de votre Mailable pointera alors vers une vue Markdown au lieu d’une vue Blade classique. La syntaxe est simple et utilise des composants pré-faits.

@component('mail::message')
# Commande expédiée

Bonjour {{ $order->user->name }},

Bonne nouvelle ! Votre commande N°{{ $order->id }} a été expédiée.

@component('mail::button', ['url' => route('orders.show', $order)])
Voir ma commande
@endcomponent

@component('mail::panel')
Ceci est un panneau d'information.
@endcomponent

Merci d'utiliser notre application !
{{ config('app.name') }} @endcomponent

Le rendu sera un email professionnel et compatible avec la plupart des appareils, sans que vous ayez eu à écrire une seule ligne de CSS ou de tableau HTML complexe.

Comment Tester Efficacement Vos Emails en Local ?

Tester les emails en développement est une étape clé. Vous voulez vous assurer que tout fonctionne et que le rendu est correct avant de passer en production. Voici les meilleures stratégies.

Option 1 : Le driver log
C’est la solution la plus rapide. Dans votre fichier .env, mettez MAIL_MAILER=log. Chaque fois qu’un email est « envoyé », son contenu sera écrit dans le fichier storage/logs/laravel.log. C’est pratique pour vérifier que les données sont correctes, mais vous n’avez pas d’aperçu visuel.

Option 2 : Mailtrap ou Mailpit (Recommandé)
C’est la meilleure méthode. Des services comme Mailtrap ou des outils locaux comme Mailpit agissent comme de faux serveurs SMTP. Ils capturent tous vos emails sortants et les affichent dans une boîte de réception web. Vous pouvez cliquer dessus, voir le rendu HTML, vérifier les en-têtes, etc.

La configuration est simple. Pour Mailtrap, par exemple, il vous suffit de copier-coller les identifiants fournis dans votre .env :

MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=votre_user_mailtrap
MAIL_PASSWORD=votre_pass_mailtrap
MAIL_ENCRYPTION=tls

Option 3 : Prévisualiser dans le navigateur
Une astuce très pratique est de créer une route de test qui retourne directement le rendu HTML de votre Mailable. Ça vous permet de travailler sur le design de votre email en direct, avec des rafraîchissements instantanés dans votre navigateur.

Dans votre fichier de routes (routes/web.php), ajoutez une route temporaire :

use App\Mail\OrderShipped;
use App\Models\Order;

Route::get('/test-email', function () {
    $order = Order::find(1); // Récupérez une commande pour l'exemple
    return new OrderShipped($order);
});

Maintenant, en visitant http://votre-site.test/test-email, vous verrez votre email s’afficher directement. C’est parfait pour ajuster rapidement le HTML et le CSS.

Vous avez maintenant toutes les clés pour maîtriser l’envoi d’emails avec Laravel. En utilisant les classes Mailable, vous gardez votre code propre, organisé et facile à maintenir. Vous pouvez commencer par une configuration SMTP simple et évoluer vers des files d’attente et des services API quand votre application grandira.

L’important est de retenir la structure : une classe par type d’email, la configuration dans l’envelope() et le content(), et l’envoi via la façade Mail. C’est un outil puissant et flexible qui couvrira 99% de vos besoins en matière d’envoi d’emails.

FAQ – Questions Fréquentes sur Laravel Mailable

Comment gérer les erreurs d’envoi d’email dans Laravel ?

L’envoi d’email peut échouer (ex: serveur SMTP indisponible). Pour éviter que votre application ne plante, vous pouvez entourer votre appel à `Mail::send()` d’un bloc `try/catch`. Laravel lèvera une exception `\Exception` ou plus spécifiquement une `\Symfony\Component\Mailer\Exception\TransportExceptionInterface` en cas de problème.

Puis-je utiliser des styles CSS dans mes emails Laravel ?

Oui, mais c’est compliqué. La plupart des clients mail ne supportent pas les balises `