Tutoriel
Envoyer des e-mails avec Laravel
Envoyez les e-mails de Laravel via Emailit avec le transport mail et la façade emailit/emailit-laravel, ou en SMTP simple, et vérifiez les webhooks Emailit.
Ce guide présente deux façons d’envoyer les e-mails de Laravel via Emailit : le paquet emailit/emailit-laravel, qui ajoute un transport mail emailit et une façade Emailit, et le SMTP simple avec le mailer intégré de Laravel. Il se termine par une route de webhook qui vérifie les signatures.
Prérequis
- PHP 8.1 ou version ultérieure et Laravel 10, 11 ou 12.
- Un domaine d’envoi vérifié, par exemple
acme.com. - Une clé API. Une clé Sending Only limitée à votre domaine suffit.
- Tant que votre espace de travail n’a pas l’accès production, vous ne pouvez envoyer qu’aux adresses e-mail des comptes des membres de l’espace de travail.
Option 1 : le paquet Laravel d’Emailit
Le paquet envoie vos Mailables existants, vos Mailables Markdown, vos notifications et vos e-mails en file d’attente via l’API Emailit, sans modifier votre code d’envoi.
Installer le paquet
composer require emailit/emailit-laravelLe service provider est découvert automatiquement.
Configurer le transport
Ajoutez votre clé et faites d’Emailit le mailer par défaut dans .env :
EMAILIT_API_KEY=secret_••••••••••••••••••••••••••••••••
MAIL_MAILER=emailit
MAIL_FROM_ADDRESS=hello@acme.com
MAIL_FROM_NAME="Acme"Déclarez le mailer dans config/mail.php :
'mailers' => [
// ...
'emailit' => [
'transport' => 'emailit',
],
],MAIL_FROM_ADDRESS doit appartenir à un domaine d’envoi vérifié. Pour modifier l’URL de base de l’API, publiez le fichier de configuration avec php artisan vendor:publish --tag=emailit-config ; ce n’est pas nécessaire pour un usage normal.
Envoyer un Mailable
Créez un Mailable comme d’habitude :
php artisan make:mail WelcomeEmailnamespace App\Mail;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WelcomeEmail extends Mailable
{
use Queueable, SerializesModels;
public function __construct(public User $user) {}
public function envelope(): Envelope
{
return new Envelope(subject: 'Welcome to Acme');
}
public function content(): Content
{
return new Content(view: 'emails.welcome');
}
}Envoyez-le, ou mettez-le en file d’attente pour que la requête n’attende pas l’API :
use App\Mail\WelcomeEmail;
use Illuminate\Support\Facades\Mail;
Mail::to($user)->send(new WelcomeEmail($user));
Mail::to($user)->queue(new WelcomeEmail($user));Utiliser la façade pour les fonctionnalités de l’API
La façade Emailit expose l’intégralité du SDK PHP, pour les fonctionnalités que le mailer de Laravel ne prend pas en charge, comme les modèles enregistrés et les envois programmés :
use Emailit\Laravel\Facades\Emailit;
$email = Emailit::emails()->send([
'from' => 'Acme <hello@acme.com>',
'to' => $user->email,
'template' => 'welcome',
'variables' => ['first_name' => $user->first_name],
'scheduled_at' => 'tomorrow at 9am',
]);
$email->id; // em_…La façade couvre aussi les domaines, les contacts, les listes de contacts, les adresses bloquées, les webhooks et les autres ressources. Si vous préférez l’injection de dépendances, typez Emailit\EmailitClient dans un contrôleur ou un job : Laravel le résout avec la clé configurée.
Interceptez les exceptions typées pour gérer les échecs :
use Emailit\Exceptions\ApiErrorException;
use Emailit\Exceptions\RateLimitException;
try {
Emailit::emails()->send($payload);
} catch (RateLimitException $e) {
// 429: release the job back to the queue and try again later
} catch (ApiErrorException $e) {
report($e); // $e->getHttpStatus() has the status code
}Option 2 : SMTP simple
Si vous préférez ne pas ajouter de paquet, faites pointer le mailer SMTP de Laravel vers le relais Emailit :
MAIL_MAILER=smtp
MAIL_HOST=smtp.emailit.com
MAIL_PORT=587
MAIL_USERNAME=emailit
MAIL_PASSWORD=secret_••••••••••••••••••••••••••••••••
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@acme.com
MAIL_FROM_NAME="Acme"Sur le port 587, le mailer de Laravel passe la connexion en STARTTLS. Les anciens fichiers config/mail.php lisent MAIL_ENCRYPTION et les plus récents l’ignorent : vous pouvez donc le conserver sans risque. Pour le TLS implicite, utilisez le port 465 ; si votre hébergeur bloque le port 587, utilisez 2525 ou 2587. Les Mailables, les notifications et les files d’attente fonctionnent exactement comme avec le paquet. Consultez Paramètres SMTP.
Via SMTP, vous ne pouvez pas utiliser les modèles enregistrés ni scheduled_at ; utilisez pour cela la façade ou l’API.
Recevoir des webhooks
Créez un webhook qui pointe vers https://your-app.com/webhooks/emailit, puis enregistrez son secret de signature :
EMAILIT_WEBHOOK_SECRET=whsec_••••••••'emailit' => [
'webhook_secret' => env('EMAILIT_WEBHOOK_SECRET'),
],Ajoutez un contrôleur qui vérifie la signature à partir du corps brut :
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class EmailitWebhookController extends Controller
{
public function __invoke(Request $request)
{
$payload = $request->getContent();
$signature = (string) $request->header('X-Emailit-Signature');
$timestamp = (string) $request->header('X-Emailit-Timestamp');
$expected = hash_hmac('sha256', $timestamp.'.'.$payload, config('services.emailit.webhook_secret'));
if (abs(time() - (int) $timestamp) > 300 || ! hash_equals($expected, $signature)) {
abort(401, 'Invalid signature');
}
// The body is a JSON array of up to 100 events.
foreach (json_decode($payload, true) as $event) {
match ($event['type']) {
'email.bounced', 'email.complained' => $this->stopEmailing($event['data']['object']['to']),
default => null,
};
}
return response()->noContent();
}
private function stopEmailing(string $address): void
{
// Mark the address as undeliverable in your database.
}
}Déclarez la route et excluez-la de la protection CSRF, car Emailit ne peut pas envoyer de jeton CSRF :
use App\Http\Controllers\EmailitWebhookController;
Route::post('/webhooks/emailit', EmailitWebhookController::class);->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: ['webhooks/emailit']);
})Sous Laravel 10, ajoutez plutôt 'webhooks/emailit' au tableau $except de app/Http/Middleware/VerifyCsrfToken.php. Renvoyez un 2xx dans les 30 secondes et déléguez les traitements lents à une file d’attente. Consultez Signature des requêtes.
Conseils pour la production
- Mettez vos e-mails en file d’attente. Utilisez
queue()ouShouldQueuepour que les requêtes web n’attendent pas l’envoi, et limitez le débit des jobs d’envoi en masse (par exemple avecRedis::throttle) pour rester sous vos limites d’envoi. Par défaut, les nouveaux espaces de travail peuvent envoyer 2 e-mails par seconde. - Mettez la configuration en cache sans risque. Après
php artisan config:cache,env()ne fonctionne que dans les fichiers de configuration. Lisez la clé via la configuration, comme le fait le paquet. - Utilisez une clé dédiée. Donnez à chaque application et à chaque environnement sa propre clé Sending Only, pour pouvoir effectuer la rotation de l’une sans toucher aux autres. Consultez Clés API.
- Dédoublonnez les webhooks. Enregistrez chaque
event_idtraité et ignorez les doublons, car Emailit réessaie les livraisons en échec.