Tutoriel
Envoyer des e-mails avec Ruby on Rails
Livrez les e-mails d’Action Mailer via Emailit avec la gem emailit ou les paramètres SMTP, appelez l’API directement et vérifiez les webhooks Emailit dans Rails.
Ce guide montre comment envoyer les e-mails de Rails via Emailit. Vous pouvez utiliser la méthode de livraison Action Mailer de la gem emailit, qui envoie via l’API, ou faire pointer les paramètres SMTP d’Action Mailer vers le relais Emailit. Il explique aussi comment appeler l’API directement et vérifier les webhooks.
Prérequis
- Ruby 3.0 ou version ultérieure et une application Rails.
- 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.
Installer la gem
bundle add emailitLa gem n’a aucune dépendance d’exécution en dehors de la bibliothèque standard de Ruby.
Configurer votre clé API
Stockez la clé dans votre environnement ou dans les credentials Rails :
bin/rails credentials:editemailit:
api_key: secret_••••••••••••••••••••••••••••••••
webhook_secret: whsec_••••••••Les exemples ci-dessous lisent Rails.application.credentials.dig(:emailit, :api_key). Si vous utilisez des variables d’environnement, lisez plutôt ENV.fetch("EMAILIT_API_KEY").
Envoyer avec Action Mailer
Quand la gem détecte Rails, elle enregistre une méthode de livraison :emailit. Activez-la par environnement :
config.action_mailer.delivery_method = :emailit
config.action_mailer.emailit_settings = {
api_key: Rails.application.credentials.dig(:emailit, :api_key)
}Vos mailers ne changent pas. L’adresse from doit appartenir à un domaine d’envoi vérifié :
class UserMailer < ApplicationMailer
default from: "Acme <hello@acme.com>"
def welcome(user)
@user = user
mail(to: @user.email, subject: "Welcome to Acme")
end
endUserMailer.welcome(user).deliver_laterLa méthode de livraison convertit chaque message en requête API, avec from, to, cc, bcc, reply_to, l’objet, les parties HTML et texte, et les pièces jointes.
Appeler l’API directement
Pour les fonctionnalités qu’Action Mailer ne prend pas en charge, comme les modèles enregistrés ou les envois programmés, utilisez le client :
client = Emailit::EmailitClient.new(Rails.application.credentials.dig(:emailit, :api_key))
email = client.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_…"Les erreurs sont levées sous forme d’exceptions typées : Emailit::AuthenticationError (401), Emailit::RateLimitError (429), Emailit::UnprocessableEntityError (422) et Emailit::ApiError pour tout le reste.
Envoyer plutôt via SMTP
Pour utiliser le SMTP simple, configurez la livraison SMTP d’Action Mailer :
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.emailit.com",
port: 587,
user_name: "emailit",
password: Rails.application.credentials.dig(:emailit, :api_key),
authentication: :plain,
enable_starttls_auto: true
}Les mailers et deliver_later fonctionnent de la même façon. Si votre hébergeur bloque le port 587, utilisez 2525 ou 2587. Consultez Paramètres SMTP.
Recevoir des webhooks
Créez un webhook qui pointe vers https://your-app.com/webhooks/emailit. Ajoutez une route et un contrôleur qui vérifie la signature à partir du corps brut :
post "/webhooks/emailit", to: "emailit_webhooks#create"class EmailitWebhooksController < ActionController::API
def create
payload = request.raw_post
signature = request.headers["X-Emailit-Signature"].to_s
timestamp = request.headers["X-Emailit-Timestamp"].to_s
return head :unauthorized unless valid_signature?(payload, signature, timestamp)
# The body is a JSON array of up to 100 events.
JSON.parse(payload).each do |event|
case event["type"]
when "email.bounced", "email.complained"
address = event.dig("data", "object", "to")
# Stop emailing this address.
end
end
head :ok
end
private
def valid_signature?(payload, signature, timestamp)
return false if signature.empty? || timestamp.empty?
return false if (Time.now.to_i - timestamp.to_i).abs > 300
secret = Rails.application.credentials.dig(:emailit, :webhook_secret)
expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{payload}")
ActiveSupport::SecurityUtils.secure_compare(expected, signature)
end
endHériter de ActionController::API désactive la protection CSRF, qu’Emailit ne peut pas satisfaire. Renvoyez un 2xx dans les 30 secondes et déplacez les traitements lents dans Active Job. Consultez Signature des requêtes.
Conseils pour la production
- Livrez en différé. Utilisez
deliver_laterpour que les requêtes web n’attendent pas l’envoi, et limitez le débit des jobs d’envoi en masse pour rester sous vos limites d’envoi (2 e-mails par seconde par défaut). - Sécurisez le développement. Utilisez
:letter_opener,:testou une clé de préproduction distincte en développement pour ne pas envoyer d’e-mails à de vrais utilisateurs par accident. - Dédoublonnez les webhooks. Enregistrez chaque
event_idtraité : Emailit réessaie les livraisons en échec, qui peuvent donc arriver plusieurs fois. - Effectuez la rotation des clés sans interruption de service en déployant une nouvelle clé avant de supprimer l’ancienne. Consultez Clés API.