Gestion des Emails et Notifications avec Action Mailer
Introduction à la Communication Asynchrone dans Rails
Dans le développement web moderne, la communication avec les utilisateurs est essentielle. Qu'il s'agisse de confirmer une inscription, de réinitialiser un mot de passe, d'envoyer une notification de commande, ou de communiquer des mises à jour importantes, les emails restent un canal privilégié. Pour les applications Rails, Action Mailer est le framework intégré qui facilite l'envoi d'emails et la gestion des notifications.
Cette leçon vous guidera à travers les concepts fondamentaux d'Action Mailer, de sa configuration à l'envoi effectif d'emails, en passant par la création de vues dédiées et les bonnes pratiques. À la fin de cette leçon, vous serez capable d'intégrer des fonctionnalités d'email robustes et efficaces dans vos applications Ruby on Rails.
Qu'est-ce qu'Action Mailer ?
Action Mailer est une surcouche de l'API Mail de Ruby, conçue spécifiquement pour s'intégrer de manière transparente avec le reste du framework Rails. Il suit le principe MVC (Modèle-Vue-Contrôleur) pour la gestion des emails, de manière similaire à la gestion des requêtes web par Action Pack.
- Mailers (Contrôleur) : Des classes Ruby qui définissent les méthodes d'envoi d'emails (ex:
welcome_email,password_reset). Elles préparent les données et décident quel email envoyer. - Vues (Vue) : Des templates ERB (ou autres) qui définissent le contenu HTML et/ou texte brut de l'email.
- Données (Modèle) : Les informations que vous souhaitez inclure dans l'email, souvent issues de vos modèles ActiveRecord.
Action Mailer permet de :
- Générer des emails au format HTML et/ou texte brut.
- Envoyer des emails de manière synchrone ou asynchrone (via Active Job).
- Gérer facilement les pièces jointes.
- Tester efficacement les fonctionnalités d'envoi d'emails.
Génération d'un Mailer
La première étape pour envoyer un email est de générer un mailer. Utilisez la commande rails generate mailer pour cela. Par convention, les mailers sont nommés de manière descriptive, souvent en rapport avec l'entité qu'ils concernent (ex: UserMailer, OrderMailer).
rails generate mailer UserMailer welcome password_reset
Cette commande va créer plusieurs fichiers :
app/mailers/user_mailer.rb: La classe du mailer.app/views/user_mailer/welcome.html.erb: La vue HTML de l'email de bienvenue.app/views/user_mailer/welcome.text.erb: La vue texte brut de l'email de bienvenue.app/views/user_mailer/password_reset.html.erb: La vue HTML de l'email de réinitialisation de mot de passe.app/views/user_mailer/password_reset.text.erb: La vue texte brut de l'email de réinitialisation de mot de passe.test/mailers/user_mailer_test.rb: Un fichier de test pour le mailer.test/mailers/previews/user_mailer_preview.rb: Un fichier pour prévisualiser les emails en développement.
Vous remarquerez que pour chaque action spécifiée (welcome, password_reset), deux fichiers de vue sont créés : un pour la version HTML et un pour la version texte brut. C'est une bonne pratique de toujours fournir les deux pour une meilleure compatibilité et accessibilité.
Définition des Actions de Mailer
Ouvrons le fichier app/mailers/user_mailer.rb. Il devrait ressembler à ceci après la génération :
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.welcome.subject
#
def welcome
@greeting = "Hi"
mail to: "to@example.org"
end
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.password_reset.subject
#
def password_reset
@greeting = "Hi"
mail to: "to@example.org"
end
end
Chaque méthode publique dans une classe de mailer (comme welcome ou password_reset) correspond à une action qui enverra un email.
La méthode mail
La méthode clé dans une action de mailer est mail. C'est elle qui construit et envoie l'email. Elle prend un hash d'options comme argument :
to: L'adresse email du destinataire. Peut être une chaîne de caractères ou un tableau d'adresses.from: L'adresse email de l'expéditeur. Par défaut, celle configurée dansapplication.rbou l'environnement.subject: Le sujet de l'email.cc: Adresses en copie carbone.bcc: Adresses en copie carbone invisible.reply_to: Adresse de réponse.attachments: Pour joindre des fichiers.
Exemple d'une action welcome_email améliorée :
Supposons que nous voulions envoyer un email de bienvenue à un nouvel utilisateur. Nous devrons lui passer l'objet User.
# app/mailers/user_mailer.rb
class UserMailer < ApplicationMailer
# Définit l'expéditeur par défaut pour tous les emails de ce mailer
default from: 'notifications@example.com'
def welcome_email(user)
@user = user # Rend l'objet user disponible dans les vues de l'email
@url = 'http://example.com/login' # Une URL pour l'utilisateur
# Envoie l'email
mail(to: @user.email, subject: 'Bienvenue sur notre application !')
end
def password_reset_email(user, token)
@user = user
@token = token
@url = "http://example.com/password_resets/#{token}/edit"
mail(to: @user.email, subject: 'Réinitialisation de votre mot de passe')
end
end
default from:: Il est courant de définir une adresse d'expéditeur par défaut pour tous les emails envoyés par ce mailer. Si vous ne la définissez pas ici, Action Mailer tentera de récupérerconfig.action_mailer.default_options[:from]ouconfig.action_mailer.default_from.- Les variables d'instance (comme
@useret@url) sont automatiquement disponibles dans les vues correspondantes, tout comme dans les contrôleurs.
Vues des Emails
Les vues d'Action Mailer fonctionnent de manière très similaire aux vues d'Action View. Elles sont stockées dans app/views/[mailer_name]/.
Pour l'action welcome_email, les vues seront app/views/user_mailer/welcome_email.html.erb et app/views/user_mailer/welcome_email.text.erb.
welcome_email.html.erb
<!-- app/views/user_mailer/welcome_email.html.erb -->
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Bienvenue, <%= @user.name %> !</h1>
<p>
Vous vous êtes inscrit avec succès sur notre super application,
votre nom d'utilisateur est : <%= @user.login %>.
</p>
<p>
Pour vous connecter, cliquez sur ce lien : <%= link_to 'Se connecter', @url %>.
</p>
<p>Merci de nous avoir rejoint et bonne journée !</p>
</body>
</html>
- Les helpers comme
link_topeuvent être utilisés dans les vues d'email, mais soyez conscient qu'ils généreront du HTML pur. Les clients de messagerie ne supportent pas tous le JavaScript ou les styles CSS complexes. - Il est crucial d'utiliser des styles en ligne pour le CSS dans les emails, car de nombreux clients de messagerie suppriment les balises
<style>ou les feuilles de style externes. Des outils commePremailer-Railspeuvent automatiser l'inlining.
welcome_email.text.erb
# app/views/user_mailer/welcome_email.text.erb
Bienvenue, <%= @user.name %> !
Vous vous êtes inscrit avec succès sur notre super application,
votre nom d'utilisateur est : <%= @user.login %>.
Pour vous connecter, utilisez ce lien : <%= @url %>.
Merci de nous avoir rejoint et bonne journée !
Cette version est cruciale pour les clients de messagerie qui ne supportent pas le HTML ou pour les utilisateurs qui préfèrent le texte brut. Elle doit être concise et fournir toutes les informations essentielles.
Layouts pour les Emails
De la même manière que pour les vues web, vous pouvez définir des layouts pour vos emails pour y inclure des éléments communs comme un en-tête, un pied de page ou un logo. Par défaut, Action Mailer utilise app/views/layouts/mailer.html.erb et app/views/layouts/mailer.text.erb.
<!-- app/views/layouts/mailer.html.erb -->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Styles CSS inlinés ou utilisés avec Premailer-Rails */
body { font-family: Arial, sans-serif; }
.container { width: 100%; max-width: 600px; margin: 0 auto; padding: 20px; }
.header { background-color: #f8f8f8; padding: 10px; text-align: center; }
.footer { background-color: #eee; padding: 10px; text-align: center; font-size: 0.8em; color: #555; }
</style>
</head>
<body>
<div class="header">
<h1>Mon Application Rails</h1>
</div>
<div class="container">
<%= yield %>
</div>
<div class="footer">
<p>© <%= Time.current.year %> Mon Application Rails. Tous droits réservés.</p>
</div>
</body>
</html>
<%= yield %> insérera le contenu de la vue spécifique de l'email.
Configuration d'Action Mailer
Pour qu'Action Mailer puisse envoyer des emails, il doit être configuré avec un serveur SMTP (Simple Mail Transfer Protocol) ou un service tiers.
La configuration est généralement faite dans les fichiers d'environnement :
config/environments/development.rbconfig/environments/production.rb
En Environnement de Développement
En développement, vous ne voulez généralement pas envoyer de vrais emails. Rails propose plusieurs solutions :
-
letter_openergem : Ouvre les emails dans votre navigateur web au lieu de les envoyer. Idéal pour le débogage rapide. Ajoutez à votreGemfile:gem 'letter_opener', group: :developmentPuis dansconfig/environments/development.rb:# config/environments/development.rb config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :letter_opener config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }perform_deliveries = true: Indique à Rails de tenter d'envoyer les emails (nécessaire même pourletter_opener).raise_delivery_errors = true: Permet de voir les erreurs de configuration d'email directement.default_url_options: Important pour les helpers commelink_toqui génèrent des URLs complètes dans les emails.
-
delivery_method: :smtp(avec un compte de test) : Vous pouvez configurer un serveur SMTP de test si vous avez besoin de tester la livraison réelle (ex: Mailtrap.io, SendGrid development account).# config/environments/development.rb config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: 'smtp.mailtrap.io', port: 2525, user_name: ENV['MAILTRAP_USERNAME'], # Récupérez ceci de vos variables d'environnement password: ENV['MAILTRAP_PASSWORD'], authentication: 'plain', enable_starttls_auto: true } config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }Il est fortement recommandé d'utiliser des variables d'environnement (ex: via le gem
dotenv-railsou un outil de gestion de secrets) pour les identifiants sensibles.
En Environnement de Production
En production, vous utiliserez un service de livraison d'emails fiable comme SendGrid, Mailgun, Postmark, ou le SMTP de votre hébergeur.
Exemple avec SendGrid (configuration SMTP) :
# config/environments/production.rb
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false # En production, vous loggerez les erreurs au lieu de les lever
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: 'smtp.sendgrid.net',
port: 587,
domain: 'yourdomain.com', # Remplacez par votre domaine
user_name: ENV['SENDGRID_USERNAME'], # Généralement 'apikey' pour SendGrid
password: ENV['SENDGRID_API_KEY'], # Votre clé API SendGrid
authentication: 'plain',
enable_starttls_auto: true
}
# Très important : Définissez votre vrai domaine de production ici
config.action_mailer.default_url_options = { host: 'www.yourproductiondomain.com' }
N'oubliez pas de configurer correctement les enregistrements DNS (SPF, DKIM, DMARC) de votre domaine pour améliorer la délivrabilité de vos emails.
Envoi d'Emails (Triggering Mailers)
Une fois votre mailer défini et configuré, vous pouvez déclencher l'envoi d'emails depuis vos contrôleurs, vos modèles (via des callbacks ou des méthodes), ou même des tâches Rake.
Il existe deux méthodes principales pour déclencher l'envoi :
deliver_now: Envoie l'email immédiatement. Cela peut bloquer l'exécution de votre requête web si l'envoi prend du temps.deliver_later: Envoie l'email en tâche de fond via Active Job. C'est la méthode préférée pour la plupart des cas d'utilisation afin d'éviter de bloquer l'interface utilisateur.
Exemple depuis un Contrôleur
Supposons que nous ayons un UsersController et que nous voulions envoyer un email de bienvenue après l'inscription d'un utilisateur.
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
# Envoi de l'email de bienvenue en tâche de fond
UserMailer.welcome_email(@user).deliver_later
redirect_to @user, notice: 'Utilisateur créé avec succès ! Un email de bienvenue a été envoyé.'
else
render :new
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
UserMailer.welcome_email(@user): Ceci retourne un objetMail::Message, mais l'email n'est pas encore envoyé..deliver_later: Ajoute la tâche d'envoi d'email à la file d'attente d'Active Job. Vous devrez configurer un adaptateur de file d'attente (ex: Sidekiq, Resque) en production. En développement, Active Job utilise par défaut la file d'attente:asyncqui est suffisante pour les tests.
Utilisation de deliver_now (pour les cas exceptionnels ou tests)
# Dans une console Rails, ou pour des emails critiques non bloquants
UserMailer.welcome_email(User.find(1)).deliver_now
Prévisualisation des Emails en Développement
Rails fournit un excellent moyen de prévisualiser vos emails sans avoir à les envoyer réellement. Ceci est géré par les classes MailerPreview. Lorsque vous générez un mailer, Rails crée automatiquement un fichier de prévisualisation (ex: test/mailers/previews/user_mailer_preview.rb).
Pour UserMailer, le fichier ressemblerait à ceci :
# test/mailers/previews/user_mailer_preview.rb
# Preview all emails at http://localhost:3000/rails/mailers/user_mailer
class UserMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/welcome_email
def welcome_email
user = User.new(name: "John Doe", email: "john@example.com", login: "johndoe")
UserMailer.welcome_email(user)
end
# Preview this email at http://localhost:3000/rails/mailers/user_mailer/password_reset_email
def password_reset_email
user = User.new(name: "Jane Doe", email: "jane@example.com", login: "janedoe")
token = "some_random_token_here"
UserMailer.password_reset_email(user, token)
end
end
Pour y accéder, démarrez votre serveur Rails en mode développement (rails s) et naviguez vers http://localhost:3000/rails/mailers. Vous verrez une liste de tous vos mailers et de leurs actions prévisualisables. Cela est extrêmement utile pour le design et le débogage des emails.
Tests des Mailers
Les tests sont une partie cruciale de toute application Rails, et les mailers ne font pas exception. Rails fournit des outils pour tester l'envoi et le contenu des emails.
Test unitaire d'un Mailer
Les tests des mailers se trouvent dans test/mailers/.
# test/mailers/user_mailer_test.rb
require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
test "welcome_email" do
user = users(:one) # Supposons que vous ayez des fixtures pour les utilisateurs
# Envoi de l'email de bienvenue
email = UserMailer.welcome_email(user).deliver_now
# Vérifiez que l'email a été mis dans la file d'attente (si deliver_later est utilisé) ou envoyé
assert_not ActionMailer::Base.deliveries.empty?
# Vérifiez l'expéditeur et le destinataire
assert_equal ['notifications@example.com'], email.from
assert_equal [user.email], email.to
assert_equal 'Bienvenue sur notre application !', email.subject
# Vérifiez le contenu du corps
assert_match "Bienvenue, #{user.name} !", email.body.encoded
assert_match user.login, email.body.encoded
assert_match 'http://example.com/login', email.body.encoded
end
test "password_reset_email" do
user = users(:one)
token = 'some_secure_token' # Un token de test
email = UserMailer.password_reset_email(user, token).deliver_now
assert_not ActionMailer::Base.deliveries.empty?
assert_equal [user.email], email.to
assert_equal 'Réinitialisation de votre mot de passe', email.subject
assert_match "http://example.com/password_resets/#{token}/edit", email.body.encoded
end
end
ActionMailer::Base.deliveries: C'est un tableau où Rails stocke tous les emails envoyés en mode test (par défaut). Vous pouvez vérifier si des emails ont été ajoutés et inspecter leur contenu.email.from,email.to,email.subject,email.body.encoded: Permettent d'accéder aux attributs de l'email pour les assertions.body.encodedcontient le contenu brut de l'email (HTML et texte).
Bonnes Pratiques et Conseils
- Toujours fournir des versions HTML et Texte Brut : Assure une compatibilité maximale avec tous les clients de messagerie.
- Utiliser les styles en ligne pour le CSS : Les clients de messagerie ont un support CSS très limité et suppriment souvent les balises
<style>. Des outils commePremailer-Railspeuvent automatiser ce processus. - Conception Responsive : Les emails sont souvent lus sur des appareils mobiles. Assurez-vous que vos templates s'adaptent bien aux différentes tailles d'écran. Des frameworks comme MJML ou Foundation for Emails peuvent grandement aider.
- Envoi Asynchrone avec Active Job (
deliver_later) : C'est impératif pour l'expérience utilisateur en production. Ne bloquez jamais le thread de la requête web pour l'envoi d'emails. - Utiliser un service de livraison d'emails fiable en Production : Ne tentez pas d'envoyer des emails directement depuis votre serveur web en production. Des services comme SendGrid, Mailgun, Postmark, AWS SES sont conçus pour cela et gèrent la délivrabilité, la réputation IP, etc.
- Sécurité et Confidentialité : Ne mettez jamais d'informations sensibles dans l'URL (comme des mots de passe). Utilisez des tokens à usage unique pour les réinitialisations de mot de passe.
- Internationalisation (I18n) : Utilisez le système I18n de Rails pour les sujets et le contenu des emails afin de supporter plusieurs langues.
# config/locales/en.yml en: user_mailer: welcome_email: subject: "Welcome to our App!"# app/mailers/user_mailer.rb mail(to: @user.email, subject: t('.subject')) # t('.subject') récupère la clé du locale - Gestion des Erreurs : Implémentez une gestion des erreurs pour les échecs de livraison d'emails, même si les services tiers sont fiables, des problèmes peuvent survenir.
Conclusion
Action Mailer est un composant puissant et bien intégré de Ruby on Rails qui simplifie grandement la gestion des emails et des notifications. En suivant le paradigme MVC, il permet de créer des communications claires, structurées et testables avec vos utilisateurs.
Nous avons couvert les étapes clés : de la génération d'un mailer à la définition de ses actions, la création de vues HTML et texte, la configuration des paramètres d'envoi en développement et production, le déclenchement des emails de manière synchrone ou asynchrone, et l'importance de la prévisualisation et des tests.
En maîtrisant Action Mailer et en appliquant les bonnes pratiques, vous pouvez enrichir l'expérience utilisateur de votre application Rails avec des communications par email efficaces et fiables. N'oubliez pas l'importance des services tiers pour la livraison en production et l'utilisation d'Active Job pour une performance optimale.