Comment envoyer des e-mails transactionnels depuis Heroku (avec Mailer To Go)
Un dyno Heroku est un excellent endroit pour exécuter votre application et un terrible endroit pour exécuter un serveur de messagerie. Le système de fichiers est éphémère, les IPs des dynos sont partagées et tournent, et le port 25 sortant est pratiquement inutilisable — donc tout courrier que vous essayez d’envoyer directement depuis un dyno atterrit dans les spams, s’il part du tout. La solution est de confier l’envoi à un service de messagerie. Mailer To Go est un add-on Heroku qui s’approvisionne en secondes et s’intègre à votre application, vous permettant d’envoyer via une connexion authentifiée et gérée en matière de réputation sur le port 587.
Ce guide vous fait passer de zéro à un e-mail envoyé et atterrissant dans la boîte de réception sur Heroku, et couvre les pièges spécifiques à Heroku (variables de config, applications de révision, tâches de fond) qui posent problème.
Étape 1 — Approvisionner l’add-on
Depuis la CLI :
heroku addons:create mailertogo --app your-app
Ou ajoutez-le depuis la Place de marché Heroku Elements. De toute façon, l’approvisionnement définit automatiquement ces variables de config sur votre application — pas de copier-coller d’identifiants :
heroku config --app your-app | grep MAILERTOGO
# MAILERTOGO_SMTP_HOST: smtp.mailertogo.com
# MAILERTOGO_SMTP_USER: ...
# MAILERTOGO_SMTP_PASSWORD: ...
# MAILERTOGO_API_KEY: ...
Pour le déclarer comme dépendance afin que chaque déploiement et application de révision l’obtienne, ajoutez-le à app.json :
{
"addons": ["mailertogo"]
}
Étape 2 — Vérifier votre domaine d’envoi
Ajoutez un sous-domaine d’envoi — mtg.yourdomain.com — dans le tableau de bord Mailer To Go et publiez les enregistrements SPF et DKIM qu’il vous montre (plus une politique DMARC à votre racine). Un sous-domaine garde la réputation d’envoi de votre application séparée de votre domaine racine, et c’est exactement ce qui fait que le courrier d’une plateforme éphémère comme Heroku atterrit de manière fiable. Voir Pourquoi Mailer To Go envoie depuis mtg.yourdomain.com et le guide de configuration SPF/DKIM/DMARC.
Étape 3 — Pointer votre application vers les variables de config
Votre application a déjà les identifiants en tant que variables d’environnement — référencez-les simplement.
Rails :
# config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: ENV["MAILERTOGO_SMTP_HOST"], # smtp.mailertogo.com
port: 587,
user_name: ENV["MAILERTOGO_SMTP_USER"],
password: ENV["MAILERTOGO_SMTP_PASSWORD"],
authentication: :plain,
enable_starttls: true
}
Node.js (Nodemailer) :
const transport = require("nodemailer").createTransport({
host: process.env.MAILERTOGO_SMTP_HOST,
port: 587,
auth: { user: process.env.MAILERTOGO_SMTP_USER, pass: process.env.MAILERTOGO_SMTP_PASSWORD },
});
Préférez HTTP à SMTP, ou sur un autre langage ? Utilisez l’API REST à la place — des exemples complets dans Envoyer un e-mail avec l’API Mailer To Go et SMTP.
Étape 4 — Déployer et envoyer un test
git push heroku main
heroku run rails runner 'ActionMailer::Base.mail(from: "hello@mtg.yourdomain.com", to: "you@example.com", subject: "Hello from Heroku", body: "It works.").deliver_now' --app your-app
heroku logs --tail --app your-app # watch the send
Ouvrez le message dans Gmail → Afficher l’original et confirmez que SPF, DKIM et DMARC disent tous PASS.
Pièges spécifiques à Heroku
- Ne codifiez jamais les identifiants en dur. Définir une variable de config redémarre vos dynos et fait une rotation propre ; un mot de passe codifiés en dur survit à une rotation d’identifiants et casse silencieusement. Lisez toujours depuis
ENV. - Envoyez depuis une tâche de fond. Le système de fichiers du dyno est éphémère et les requêtes web ont un délai d’expiration de 30 secondes, donc ne l’envoyez pas inline dans une action de contrôleur. Mettez en file d’attente vers Sidekiq / Delayed Job / GoodJob et envoyez depuis le worker — réponses plus rapides et tentatives automatiques sur les erreurs SMTP transitoires.
- Applications de révision et pipelines. Avec
mailertogodansapp.json, chaque application de révision peut approvisionner sa propre instance ; si vous préférez ne pas envoyer de vrai courrier depuis des applications éphémères, remplacez le mailer par:test(Rails) ou une adresse de rattrapage dans ces environnements. - Le port 25 est une impasse — vous n’en avez pas besoin. Heroku (comme chaque cloud majeur) rend le port 25 sortant inutilisable ; Mailer To Go utilise le port de soumission 587, qui est ouvert. Si vous voyez jamais des connexions traîner sur le port 25, c’est pourquoi.
- La mise à l’échelle des dynos va bien. SMTP est sans état par message, donc exécuter plusieurs dynos web/worker ne nécessite aucune manipulation spéciale — chaque dyno lit les mêmes variables de config.
Pourquoi cela fonctionne alors que l’envoi depuis le dyno ne fonctionne pas
La délivrabilité est un jeu de réputation joué par l’IP d’envoi et le domaine. Un dyno Heroku n’a ni une IP stable ni une réputation réchauffée, et ne peut pas publier les enregistrements d’authentification que les fournisseurs de boîtes de réception exigent. Mailer To Go fournit les IPs gérées, la signature DKIM et la rotation des clés, l’alignement SPF/DMARC et la gestion des rebonds/plaintes — donc votre dyno fait ce pour quoi il est bon (exécuter votre application) tandis que votre e-mail roule sur une infrastructure construite pour être délivré.
Vous déployez via Addons.io ou Build.io à la place ? La configuration est identique — voir Utiliser Mailer To Go sur Heroku, Addons.io et Build.io. Vous travaillez avec les sous-domaines Heroku en général ? Voir Sous-domaines Heroku : un guide d’introduction.