Pourquoi remplacer MailHog par Mailpit
MailHog n'est plus maintenu depuis fin 2022. Il accumule des dépendances obsolètes, son interface date des premières années de Bootstrap, et son API n'a jamais évolué. Mailpit comble chacun de ces points : il est activement développé (dernière release en 2024), propose une UI réactive en temps réel, et expose une API REST qui reste rétro-compatible avec celle de MailHog pour ne pas casser les scripts existants.
Le changement n'implique aucune migration de données : Mailpit ne persiste rien par défaut. Chaque redémarrage repart d'une boîte vide, ce qui est exactement le comportement voulu dans un pipeline de test.
Ce que Mailpit apporte en pratique
- Interface moderne avec recherche full-text, affichage HTML/texte, prévisualisation mobile et inspection des en-têtes
- Binaire unique Go compilé statiquement — aucune dépendance système, tourne dans un conteneur de 20 Mo
- Consommation mémoire au repos inférieure à 50 Mo, stable même avec des milliers d'e-mails en session
- API REST rétro-compatible MailHog (
/api/v1/messages,/api/v1/search) pour les scripts existants - Support SMTP authentifié, TLS optionnel, et contrôle d'accès par réseau
- Webhook configurable pour notifier un endpoint externe à chaque réception d'e-mail
Prérequis
Un VPS sous Debian 12 ou Ubuntu 22.04/24.04 avec Docker et Docker Compose v2 installés suffit. Mailpit est parmi les outils les plus légers du catalogue : comptez 1 vCPU partagé et 256 Mo de RAM pour un usage développeur ou CI. Un sous-domaine dédié (mail.votre-domaine.com) est recommandé pour accéder à l'interface depuis le navigateur en HTTPS — sans quoi l'accès ne se fait qu'en local via un tunnel SSH.
Ports utilisés : 1025 (SMTP) et 8025 (interface web). Si un service de messagerie tourne déjà sur le port 1025, vous devrez décaler Mailpit (voir la section dépannage).
Déployer Mailpit en 5 étapes
Créer le répertoire et le fichier Compose
mkdir -p /opt/mailpit && cd /opt/mailpitCréez le fichier
docker-compose.ymlsuivant :services: mailpit: image: axllent/mailpit:latest container_name: mailpit restart: unless-stopped ports: - "127.0.0.1:1025:1025" - "127.0.0.1:8025:8025" environment: MP_MAX_MESSAGES: 500 MP_SMTP_AUTH_ACCEPT_ANY: "true" MP_SMTP_AUTH_ALLOW_INSECURE: "true" MP_UI_AUTH: "admin:changeme" volumes: - mailpit_data:/data volumes: mailpit_data:Les ports sont liés à
127.0.0.1uniquement : Mailpit n'est jamais exposé directement sur l'IP publique. La variableMP_UI_AUTHactive l'authentification HTTP basique sur l'interface web — changez le mot de passe.MP_MAX_MESSAGESlimite le nombre d'e-mails conservés en mémoire par session.Démarrer le conteneur
docker compose up -d docker compose logs -f mailpitLa ligne
starting on [::]:1025confirme que le serveur SMTP écoute. Vérifiez que les ports sont bien liés à localhost :ss -tlnp | grep -E '1025|8025'Attendu :
127.0.0.1:1025et127.0.0.1:8025uniquement — jamais0.0.0.0.Configurer le reverse proxy Nginx
Créez
/etc/nginx/sites-available/mailpit:server { listen 443 ssl; server_name mail.votre-domaine.com; ssl_certificate /etc/letsencrypt/live/mail.votre-domaine.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mail.votre-domaine.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8025; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_read_timeout 86400; } }Le
proxy_read_timeout 86400est nécessaire pour les connexions WebSocket utilisées par l'interface en temps réel. Activez le vhost et rechargez Nginx :ln -s /etc/nginx/sites-available/mailpit /etc/nginx/sites-enabled/ nginx -t && systemctl reload nginxObtenez un certificat Let's Encrypt si ce n'est pas déjà fait :
certbot --nginx -d mail.votre-domaine.comTester l'envoi avec curl
Vérifiez que le serveur SMTP reçoit bien un message :
curl --url 'smtp://127.0.0.1:1025' \ --mail-from '[email protected]' \ --mail-rcpt '[email protected]' \ --upload-file - <<EOF From: [email protected] To: [email protected] Subject: Test Mailpit Corps du message de test. EOFOuvrez ensuite
https://mail.votre-domaine.comdans votre navigateur. Le message doit apparaître dans l'interface. Si vous avez configuréMP_UI_AUTH, saisissez les identifiants au prompt HTTP basique.Configurer votre application pour pointer vers Mailpit
Dans votre fichier
.env(Laravel, Symfony, n8n, Django…), remplacez la configuration SMTP par :MAIL_HOST=127.0.0.1 MAIL_PORT=1025 MAIL_ENCRYPTION=null MAIL_USERNAME=null MAIL_PASSWORD=nullPour les applications tournant dans Docker sur le même hôte, utilisez le nom du réseau Docker ou l'IP gateway (
172.17.0.1par défaut) à la place de127.0.0.1.
Mailpit en CI/CD : tester les e-mails dans le pipeline
En environnement CI, Mailpit s'intègre comme service sidecar. Il démarre en quelques secondes et n'a besoin d'aucune configuration externe.
Intégration CI/CD par framework
GitHub Actions — service Mailpit
services: mailpit: image: axllent/mailpit:latest ports: - 1025:1025 - 8025:8025Dans vos variables d'environnement du job, définissez
MAIL_HOST=127.0.0.1etMAIL_PORT=1025. Mailpit accepte tout e-mail sans authentification par défaut — aucune configuration SMTP supplémentaire n'est nécessaire.Laravel — PHPUnit
Dans
phpunit.xml, remplacez le transport par SMTP :<env name="MAIL_MAILER" value="smtp"/> <env name="MAIL_HOST" value="127.0.0.1"/> <env name="MAIL_PORT" value="1025"/>Dans votre test, envoyez le mail puis interrogez l'API Mailpit pour vérifier la réception :
$response = Http::get('http://127.0.0.1:8025/api/v1/messages'); $this->assertSame($response->json('total'), 1); $this->assertStringContainsString( 'Bienvenue', $response->json('messages.0.Subject') );Django — pytest
Dans
settings.py(ousettings_test.py) :EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = '127.0.0.1' EMAIL_PORT = 1025Dans votre test pytest, vérifiez via l'API Mailpit :
import requests def test_welcome_email_sent(): # déclencher l'envoi dans votre vue/service r = requests.get('http://127.0.0.1:8025/api/v1/messages') assert r.json()['total'] == 1 assert 'Bienvenue' in r.json()['messages'][0]['Subject']n8n — tests de workflow
Dans le nœud Send Email de n8n, configurez le serveur SMTP sur
127.0.0.1:1025sans authentification. Pour vérifier automatiquement qu'un workflow a bien déclenché un envoi, appelezGET http://127.0.0.1:8025/api/v1/messagesdepuis un nœud HTTP Request et validez le total dans un nœud IF.
Sécuriser l'accès à Mailpit
Mailpit stocke les e-mails uniquement en mémoire — aucun fichier sur disque, aucune base de données. C'est un avantage pour la confidentialité (pas de traces persistantes), mais aussi une limite : un redémarrage vide la boîte sans préavis.
Restriction réseau. Les ports 1025 et 8025 sont liés à 127.0.0.1 dans la configuration Docker Compose ci-dessus. Ne les exposez jamais sur 0.0.0.0 en production ou sur un serveur partagé : n'importe qui pourrait relayer des e-mails ou lire les messages interceptés.
Authentification HTTP basique sur l'interface. La variable MP_UI_AUTH=user:password active une authentification basique sur l'interface web. Préférez un mot de passe fort — l'interface expose le contenu intégral de vos e-mails de test, souvent peuplés de liens de confirmation, jetons et mots de passe temporaires.
SMTP authentifié. Pour les environnements multi-équipes, activez MP_SMTP_AUTH avec un fichier de comptes plutôt que MP_SMTP_AUTH_ACCEPT_ANY. Cela évite qu'un service mal configuré envoie des e-mails à la boîte de test d'un autre projet.
Astuce : vider la boîte entre les tests
L'API Mailpit expose un endpoint de purge : DELETE http://127.0.0.1:8025/api/v1/messages. Appelez-le dans votre setUp() PHPUnit ou votre fixture pytest pour repartir d'une boîte vide à chaque test, sans avoir à redémarrer le conteneur.
Dépannage — 4 cas fréquents
Port 1025 déjà occupé. Un serveur Postfix ou Sendmail local peut écouter sur ce port. Vérifiez avec ss -tlnp | grep 1025. Si c'est le cas, changez le port hôte dans le docker-compose.yml (ex. 1026:1025) et mettez à jour MAIL_PORT dans vos applications.
Accès refusé depuis un conteneur CI. Les conteneurs Docker dans GitHub Actions ont accès à 127.0.0.1 du runner, mais pas aux autres services via localhost si le réseau n'est pas correctement partagé. Utilisez le réseau host du runner ou référencez le service par son nom (mailpit:1025) dans le fichier de workflow.
Interface inaccessible derrière le reverse proxy. Les connexions WebSocket de l'interface temps réel peuvent être coupées par un timeout agressif de Nginx. Vérifiez que proxy_read_timeout est bien à 86400 et que les en-têtes Upgrade et Connection sont transmis.
Performance avec des milliers d'e-mails. Mailpit conserve tout en mémoire. Si votre pipeline génère des centaines d'e-mails par run, fixez MP_MAX_MESSAGES à une valeur raisonnable (100–500) pour éviter que la mémoire du conteneur ne croisse sans limite sur des sessions longues.
Mailpit vs MailHog vs Mailtrap vs Inbucket vs smtp4dev
Faites défiler le tableau
| Outil | Maintenance | RAM au repos | API REST | Persistance | Auth SMTP |
|---|---|---|---|---|---|
| **Mailpit** | Actif (2024) | < 50 Mo | Oui (v1 + v2) | Mémoire uniquement | Optionnelle |
| MailHog | Abandonné (2022) | ~30 Mo | Oui (v1 seul) | Mémoire uniquement | Non |
| Mailtrap (SaaS) | Actif | N/A (cloud) | Oui | Cloud (30 jours) | Oui (cloud) |
| Inbucket | Actif | ~20 Mo | Oui | Mémoire ou disque | Non |
| smtp4dev | Actif | ~80 Mo (.NET) | Oui | SQLite optionnel | Non |
Cas d'usage avancés
Interception multi-projets. Un seul Mailpit peut recevoir les e-mails de plusieurs projets en parallèle. Utilisez la recherche full-text ou filtrez par destinataire dans l'interface pour isoler les messages de chaque application.
Webhook vers Slack ou n8n. La variable MP_WEBHOOK_URL déclenche un POST JSON sur chaque réception. Branchez-la sur un workflow n8n pour router certains e-mails de test vers un canal Slack de l'équipe — utile pour les tests d'intégration partagés.
Export et rejeu. L'API expose les e-mails en format EML (GET /api/v1/message/<id>.eml). Téléchargez un message intercepté pour le rejouer dans un vrai client mail ou pour le garder comme fixture de test.
Mailpit dans un stack de développement complet. Ajoutez Mailpit comme service dans le docker-compose.yml de votre projet principal. Il s'intègre naturellement aux stacks Laravel Sail, Symfony Docker ou n8n self-hosted — un seul docker compose up démarre tout l'environnement de développement avec l'interception SMTP incluse.