La fonctionnalité de mail de Laravel
La fonctionnalité mail est basée sur Symfony Mailer et prend en charge SMTP, Mailgun, Postmark, Resend, Amazon SES, sendmail, etc.
SwiftMailer, utilisé dans les anciennes versions, est abandonné. Depuis Laravel 9, c’est Symfony Mailer.
La configuration se trouve dans config/mail.php. Changez le driver via .env.
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=your-username
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"
Créer une classe Mailable
Chaque e-mail est représenté par une classe « Mailable ». Utilisez make:mail.
php artisan make:mail OrderShipped
Le fichier est créé dans app/Mail/.
La classe générée expose envelope(), content() et attachments().
<?php
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: 'Votre commande a été expédiée',
);
}
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
public function attachments(): array
{
return [];
}
}
Définir l’expéditeur
Utilisez envelope().
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;
public function envelope(): Envelope
{
return new Envelope(
from: new Address('[email protected]', 'Shop Support'),
subject: 'Votre commande a été expédiée',
);
}
Vous pouvez également définir un expéditeur global dans config/mail.php, ce qui évite de le préciser dans chaque Mailable.
'from' => [
'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
Définir le contenu
Dans content(), précisez le template Blade. Les propriétés public définies dans le constructeur sont automatiquement disponibles dans le template.
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
Créez le template resources/views/mail/orders/shipped.blade.php.
<!DOCTYPE html>
<html>
<body>
<h1>Votre commande a été expédiée</h1>
<p>N° de commande : {{ $order->id }}</p>
<p>Montant total : {{ number_format($order->total) }} €</p>
<p>Merci pour votre achat.</p>
</body>
</html>
Vous pouvez aussi passer explicitement les données via with. Les propriétés peuvent alors être protected ou private.
public function __construct(
protected Order $order,
) {}
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
with: [
'orderId' => $this->order->id,
'total' => $this->order->total,
],
);
}
Envoyer un e-mail
Utilisez la façade Mail, indiquez le destinataire avec to() puis send().
<?php
namespace App\Http\Controllers;
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
{
public function store(Request $request): RedirectResponse
{
$order = Order::findOrFail($request->order_id);
Mail::to($request->user())->send(new OrderShipped($order));
return redirect('/orders');
}
}
Vous pouvez ajouter des destinataires en CC / BCC.
Mail::to($request->user())
->cc($ccUsers)
->bcc($bccUsers)
->send(new OrderShipped($order));
Pour utiliser un mailer précis :
Mail::mailer('postmark')
->to($request->user())
->send(new OrderShipped($order));
Envoi via queue
L’envoi d’e-mails influe sur le temps de réponse. Passez par la queue pour l’envoi en arrière-plan.
Mail::to($request->user())->queue(new OrderShipped($order));
Pour utiliser la queue, configurez-la et démarrez les workers au préalable.
Envoi différé :
Mail::to($request->user())
->later(now()->plus(minutes: 10), new OrderShipped($order));
Si la classe implémente ShouldQueue, send() la place systématiquement en queue.
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
// ...
}
Définir connexion et nom de file via attributs PHP
Les attributs PHP permettent de spécifier la connexion et le nom de file directement sur la classe, sans chaîner on()->queue().
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Queue;
#[Connection('sqs')]
#[Queue('emails')]
class OrderShipped extends Mailable implements ShouldQueue
{
// ...
}
Cela indique explicitement que ce Mailable ira toujours dans la file emails sur la connexion SQS.
Créer un e-mail Markdown
Les e-mails Markdown exploitent le beau template HTML responsive fourni par Laravel.
Générer un Mailable Markdown
Utilisez l’option --markdown.
php artisan make:mail OrderShipped --markdown=mail.orders.shipped
Utilisez markdown dans content().
use Illuminate\Mail\Mailables\Content;
public function content(): Content
{
return new Content(
markdown: 'mail.orders.shipped',
with: [
'url' => route('orders.show', $this->order),
],
);
}
Écrire le template Markdown
Utilisez les composants Blade fournis par Laravel.
<x-mail::message>
# Votre commande a été expédiée
Nous vous informons que votre commande a été expédiée.
<x-mail::button :url="$url">
Voir la commande
</x-mail::button>
Merci de votre confiance,<br>
{{ config('app.name') }}
</x-mail::message>
Composants disponibles :
| Composant | Description |
|---|
<x-mail::button> | Bouton (color accepte primary, success, error) |
<x-mail::panel> | Panneau mis en évidence |
<x-mail::table> | Table Markdown |
Une version texte brut est aussi générée automatiquement pour les clients qui ne prennent pas en charge le HTML.
Prévisualiser les e-mails
Retournez une instance de Mailable depuis une route pour prévisualiser dans le navigateur, très utile en développement.
// routes/web.php
Route::get('/mailable', function () {
$order = App\Models\Order::first();
return new App\Mail\OrderShipped($order);
});
E-mails en développement local
Pour éviter d’envoyer des e-mails réels par erreur, utilisez un outil comme Mailpit.
# .env (Mailpit)
MAIL_MAILER=smtp
MAIL_HOST=127.0.0.1
MAIL_PORT=1025
Laragon et Laravel Herd incluent Mailpit par défaut.
Le driver log écrit le contenu du mail dans les logs. C’est le moyen le plus simple pour vérifier un envoi.
Récapitulatif
| Objectif | Méthode |
|---|
| Créer un Mailable | php artisan make:mail ClassName |
| Définir l’expéditeur | from dans envelope() |
| Utiliser un template Blade | view dans content() |
| Utiliser un template Markdown | markdown dans content() |
| Envoyer | Mail::to()->send() |
| Envoyer via queue | Mail::to()->queue() |
| Envoi différé | Mail::to()->later() |