
Cours Laravel 8 – les bases – envoyer un email
Laravel utilise le célèbre composant SwiftMailer pour l’envoi des emails. Mais il en simplifie grandement l’utilisation. Dans ce chapitre nous allons prolonger l’exemple précédent de la prise de contact en ajoutant l’envoi d’un email à l’administrateur du site lorsque quelqu’un utilisateur soumet une demande de contact.
On va donc prendre le code tel qu’on l’a laissé lors du précédent chapitre et le compléter en conséquence.
On verra plus tard que Laravel propose aussi un système complet de notification qui permet entre autres l’envoi d’emails.
Le scénario
Le scénario est donc le même que pour le précédent chapitre avec l’ajout d’une action :
On va avoir les mêmes routes et vues, c’est uniquement au niveau du contrôleur que le code va évoluer pour intégrer cette action complémentaire.
Configuration
Si vous regardez dans le fichier .env vous trouvez une section qui concerne les emails :
MAIL_MAILER=smtp MAIL_HOST=mailhog MAIL_PORT=1025 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}"
Les premières valeurs correspondent au prestataire utilisé.
Au niveau du driver, le plus classique est certainement le SMTP mais vous pouvez aussi utiliser mail, mailgun (gratuit jusqu’à 10 000 envois par mois), Postmark, ses …
Vous devez correctement renseigner les paramètres pour que ça fonctionne selon votre contexte (en local avec le SMTP de votre prestataire, en production avec la fonction mail de PHP ou d’un autre système…).
La classe Mailable
Avec Laravel, pour envoyer un email il faut passer par la création d’une classe « mailable ». Encore une fois c’est Artisan qui va nous permettre de créer notre classe :
php artisan make:mail Contact
Comme le dossier n’existe pas il est créé en même temps que le fichier de la classe :
Par défaut on a ce code :
<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class Contact extends Mailable { use Queueable, SerializesModels; /** * Create a new message instance. * * @return void */ public function __construct() { // } /** * Build the message. * * @return $this */ public function build() { return $this->view('view.name'); } }
Tout se passe dans la méthode build. On voit qu’on retourne une vue, celle-ci doit comporter le code pour le contenu de l’email.
On commence par changer le nom de la vue :
return $this->view('emails.contact');
On va créer le dossier emails et cette vue (resources/views/emails/contact.blade.php) :
Avec ce code :
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> </head> <body> <h2>Prise de contact sur mon beau site</h2> <p>Réception d'une prise de contact avec les éléments suivants :</p> <ul> <li><strong>Nom</strong> : {{ $contact['nom'] }}</li> <li><strong>Email</strong> : {{ $contact['email'] }}</li> <li><strong>Message</strong> : {{ $contact['message'] }}</li> </ul> </body> </html>
Pour que ça fonctionne on doit transmettre à cette vue les entrées de l’utilisateur. Il faut donc passer les informations à la classe Contact à partir du contrôleur.
On peut aussi créer des email en Markdown.
Transmission des informations à la vue
Il y a deux façons de procéder pour transmettre les informations, nous allons utiliser la plus simple. Il suffit de créer une propriété obligatoirement publique dans la classe Mailable et celle-ci sera automatiquement transmise à la vue. Voici le nouveau code de notre classe :
<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; class Contact extends Mailable { use Queueable, SerializesModels; /** * Elements de contact * @var array */ public $contact; /** * Create a new message instance. * * @return void */ public function __construct(Array $contact) { $this->contact = $contact; } /** * Build the message. * * @return $this */ public function build() { return $this->from('monsite@chezmoi.com') ->view('emails.contact'); } }
J’en ai aussi profité pour préciser l’adresse de l’expéditeur avec la méthode from (on peut aussi renseigner la variable MAIL_FROM_ADDRESS dans le fichier .env). On pourrait attacher un document avec attach, faire une copie avec cc…
J’ai créé la propriété publique $contact qui sera renseignée par l’intermédiaire du constructeur.
Il ne reste plus qu’à modifier le contrôleur pour envoyer cet email avec les données nécessaires :
<?php namespace App\Http\Controllers; use App\Http\Requests\ContactRequest; use Illuminate\Support\Facades\Mail; use App\Mail\Contact; class ContactController extends Controller { public function create() { return view('contact'); } public function store(ContactRequest $request) { Mail::to('administrateur@chezmoi.com') ->send(new Contact($request->except('_token'))); return view('confirm'); } }
Tout se passe sur cette ligne :
Mail::to('administrateur@chezmoi.com') ->send(new Contact($request->except('_token')));
On a :
- l’adresse de l’administrateur (to),
- l’envoi avec la méthode send,
- la création d’une instance de la classe Contact avec la transmission des données saisies (mis à part le token pour la protection CSRF qui ne sert pas).
Et si tout se passe bien le message doit arriver jusqu’à l’administrateur :
Comme l’envoi d’emails peut prendre beaucoup de temps on utilise en général une file d’attente (queue). Il faut changer ainsi le code dans le contrôleur :
Mail::to('administrateur@chezmoi.com') ->queue(new Contact($request->except('_token')));
Mais évidemment pour que ça fonctionne il faut avoir paramétré et lancé un système de file d’attente. J’en parlerai sans doute dans un chapitre ultérieur.
Test de l’email
Quand on crée la vue pour l’email il est intéressant de voir l’aspect final avant de faire un envoi réel. Pour le faire il suffit de créer une simple route :
Route::get('/test-contact', function () { return new App\Mail\Contact([ 'nom' => 'Durand', 'email' => 'durand@chezlui.com', 'message' => 'Je voulais vous dire que votre site est magnifique !' ]); });
Maintenant en utilisant l’url monsite/test-contact on obtient l’aperçu directement dans le navigateur !
Envoyer des emails en phase développement
Le mode Log
Lorsqu’on est en phase de développement il n’est pas forcément pratique ou judicieux d’envoyer réellement des emails. Un solution simple consiste à passer en mode Log en renseignant le driver dans le fichier .env :
MAIL_MAILER=log
Les emails ne seront pas envoyés mais le code en sera mémorisé dans le fichier des logs :
Vous allez y trouver par exemple ce contenu :
[2020-08-29 15:16:48] local.DEBUG: Message-ID: <f2d44aa0cbb6730bf16d9800235a21cb@laravel6.oo> Date: Thu, 29 Aug 2020 15:16:48 +0000 Subject: Contact From: monsite@chezmoi.com To: administrateur@chezmoi.com MIME-Version: 1.0 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable <!DOCTYPE html> <html lang="fr"> <head> <meta charset="utf-8"> </head> <body> <h2>Prise de contact sur mon beau site</h2> <p>Réception d'une prise de contact avec les éléments suivants :</p> <ul> <li><strong>Nom</strong> : Dupont</li> <li><strong>Email</strong> : dupont@lui.fr</li> <li><strong>Message</strong> : Un petit message de contact</li> </ul> </body> </html>
Ce qui vous permet de vérifier que tout se passe correctement (hormis l’envoi).
MailTrap
Une autre possibilité très utilisée est MailTrap qui a une option gratuite (une boîte, avec 50 messages au maximum et 2 messages par seconde). Vous avez un tableau de bord et une boîte de messages :
J’ai fait apparaître les configurations pour Laravel. Il est ainsi facile de renseigner le fichier .env :
MAIL_DRIVER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME=login MAIL_PASSWORD=passe MAIL_ENCRYPTION=null
Avec cette configuration lorsque j’envoie un email je le vois arriver :
Vous pouvez analyser l’email avec précision, je vous laisse découvrir toutes les options.
En résumé
- Laravel permet l’envoi simple d’email.
- Il faut configurer correctement les paramètres pour l’envoi des emails.
- Pour chaque email il faut créer une classe « mailable ».
- On peut passer des informations à l’email en créant une propriété publique dans la classe « mailable ».
- On peut passer en mode Log en phase de développement ou alors utiliser MailTrap.


12 commentaires
Switchup
Bonjour tout d’abord merci pour ce cours ! c’est TOP !
Petite question pour voir si je n’ai pas loupé qqchose…
J’ai une installation larevl toute fraiche d’ajourd’hui, avec PHP 8.1
en suivant le cours de cette page j’arrive après la soumission du formulaire à l’erreur suivante :
===
ErrorException
Undefined variable $contact (View: /Users/Switchup/Laravel-Projects/learn/resources/views/emails/contact.blade.php)
===
J’ai réussi à avoir le résultat escompté en modifiant la fonction build() du script \app\Mail\Contact de la façon suivante :
===
->view(’emails.contact’,[‘contact’ => $this->contact]);
//->view(’emails.contact’);
===
et j’ai donc du passer la variable à la vue (comme expliqué dans les pages précédente) est-ce un oubli dans le code de cette page de cours ou bien j’ai loupé un point ?
Switchup
Et voilà comme d’habitude… poser la question c’est y répondre…
Méaculpa ! j’avais simplement oublié de déclarer :
public $contact;
Dans ma class.
—-
Donc encore un tout grand merci pour ce cours, C’est super pédagogique, je me régale ! ?
Josuke
Salut ! Tout d’abord merci pour le tuto et je vourdrais savoir comment es que vous mettriez en place l’envoi automatique de mail toute les « x » minute. Avec Laravel bien sur !
Merci a vous bonne journée!
bestmomo
Bonjour,
Laravel est bien équipé pour ce genre de chose, la documentation est ici.
invincible
Bonjour BestMomo.
Merci beaucoup pour ce tuto.
Cependant, je n’arrive pas à bien comprendre le principe.
En effet, grâce à ce tuto, j’arrive à bien envoyer des emails sur mailtrap.
Cependant ce que je souhaite faire, c’est de pouvoir envoyer un email à n’importe quel utilisateur quelque soit sa boîte de messagerie (gmail, hotmail, yahoo…)
Merci d’avance pour l’aide.
bestmomo
Bonjour,
Pour envoyer des emails on a deux solutions : soit on utilise la commande classique de PHP (mail) soit on utilise un serveur SMTP et alors il faut bien paramétrer dans le fichiers .env.
invincible
Merci pour ta réponse.
Dans le cas où je souhaite utiliser un serveur SMTP, comment paramétrer mon fichier .env pour envoyer un email à un utilisateur quelque soit son adresse de messagerie ?
Lorsque je paramètre mon fichier .env comme çà :
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=XXXXXXXXXXXXXX
MAIL_PASSWORD=XXXXXXXXXXXXXX
MAIL_ENCRYPTION=tls
tous les mails que j’envoie vont directement sur mon compte mailtrap.
Ce que je souhaite, c’est que par exemple lorsque j’utilise une adresse comme fernand@gmail.com ou fernand@hotmail.com, le mail que j’envoie puisse aller dans à cette adresse là et non dans mon compte mailtrap.
Merci d’avance de m’éclairer sur ce point.
bestmomo
Si tu veux utiliser un serveur SMTP il te faut connaître tous les paramètres. Par exemple pour Gmail :
MAIL_DRIVER=smtp
MAIL_HOST=smtp.googlemail.com
MAIL_PORT=465
MAIL_USERNAME=ton_adresse@gmail.com
MAIL_PASSWORD=ton_mot_de_passe
MAIL_ENCRYPTION=ssl
JS Fourquet
Bonjour,
j’ai respecté à la lettre votre tutorial et pourtant je n’arrive pas à avoir le même résultat que vous. Je n’ai même pas de log d’erreur ou autre.
Déjà à un moment on a : use App\Http\Requests\ContactRequest; dont on a pas vu la configuration dans ce tutorial (donc logiquement je l’ai fait moi même, rien de bien grave) mais là j’ai beau revoir en boucle, je vois pas du tout où j’ai pu avoir oublié quelque chose.
Si vous pouvez m’éclairer ça sera super.
Merci.
JS Fourquet
J’ai tout refait de A à Z et non ça ne fonctionne pas.
Je pense qu’il doit avoir une erreur dans le cours car avec un autre tutorial j’ai pu réussir à avoir le mail qui apparait dans le log.
Pouvez vous tester de votre coté à nouveau ?
bestmomo
Bonsoir,
J’ai réécrit le code de cet article et du précédent (c’est là qu’on trouve la form request) avec une installation fraiche de Laravel 8 et chez moi ça fonctionne correctement. J’ai bien le mail dans les logs et sur Mailtrap.
JS Fourquet
D’accord donc le problème vient bien de mon coté.
Je vais refaire une installation fraiche et reprendre depuis le début.
Merci pour cette confirmation. 🙂