La CI excelle à exécuter du code, mais elle est notoirement mauvaise dans un domaine dont votre produit dépend probablement : l’email. Si vos tests couvrent les inscriptions, réinitialisations de mot de passe, liens magiques, ou notifications entrantes, vous avez encore besoin d’un moyen de consulter les emails en CI sans (1) vous connecter à une boîte mail partagée, (2) scraper du HTML, ou (3) déverser du contenu sensible dans les logs de job.
La bonne nouvelle est que vous pouvez traiter l’email comme n’importe quel autre artefact de test : le provisionner par exécution, attendre de façon déterministe, faire des assertions sur des champs structurés, et attacher les résultats à la sortie CI.
Pourquoi “se connecter à une boîte mail” casse la CI
Une boîte mail traditionnelle (Gmail, Outlook, IMAP) est une UX humaine enveloppant une identité persistante. La CI a besoin du contraire : un état de courte durée, isolé et lisible par machine.
Modes d’échec courants quand vous comptez sur une vraie boîte mail dans les pipelines :
- Les exécutions parallèles entrent en collision : plusieurs jobs lisent la même boîte, prennent le mauvais message, ou suppriment l’état de l’autre.
- L’auth et la MFA n’ont pas leur place en CI : les tokens de rafraîchissement OAuth expirent, les défis MFA bloquent les exécutions, et les permissions sont trop larges.
- L’observabilité est inversée : vous ne pouvez pas facilement stocker “quel email avons-nous reçu ?” comme artefact de build.
- La sécurité se dégrade : les équipes commencent à coller des OTP et liens magiques dans les logs pour déboguer.
Si vous voulez que les emails soient testables, ils doivent être consommables comme des événements.
💡 Arrêtez de Lutter Contre l’Email dans Votre Pipeline CI
Évitez les tracas de connexion aux boîtes mail et les collisions d’exécutions parallèles. Mailhook crée des boîtes jetables qui se comportent comme de vraies ressources de test - provisionnées par exécution via API et consommées en JSON structuré.
Commencez à tester les emails correctement → ou Consultez la doc API →
Les trois façons pratiques de voir les emails en CI
Il existe de nombreuses astuces de test d’email, mais en 2026 la plupart des équipes convergent vers l’une de ces trois, selon ce qu’elles valident.
Option 1 : Capture SMTP locale (rapide, excellente pour le dev et certaine CI)
Si votre objectif est “notre app a-t-elle tenté d’envoyer un email ?” alors un outil de capture SMTP local est l’approche la plus simple.
Comment ça marche :
- Votre app envoie via SMTP vers un serveur local à l’intérieur du réseau CI.
- Le serveur stocke les messages et les expose via une petite API/UI.
Avantages :
- Très rapide
- Aucune dépendance externe
- Parfait pour les tests unitaires et d’intégration
Inconvénients :
- Pas un vrai test de bout en bout du routage entrant réel
- Ne détecte pas les problèmes de délivrabilité et routage qui arrivent dans l’infrastructure email de production
C’est un bon défaut pour les workflows développeur, mais ça échoue souvent pour les flux E2E qui doivent se comporter comme en production.
Option 2 : Une API de boîte jetable (meilleure pour l’E2E et flux de vérification)
Pour les tests de bout en bout où vous devez recevoir de vrais emails entrants et extraire un OTP ou lien, les boîtes jetables programmables sont le pattern le plus fiable :
- Créer une boîte fraîche via API par exécution ou par tentative.
- Utiliser son adresse email dans le flux testé.
- Attendre l’arrivée de façon déterministe.
- Récupérer le message en JSON structuré.
- Faire des assertions et extraire seulement l’artefact dont vous avez besoin.
Ceci évite entièrement les connexions aux boîtes mail. La CI ne fait que récupérer des données.
Mailhook est conçu exactement pour ce modèle : création de boîtes jetables via API, email livré en JSON, notifications webhook, récupération par polling, domaines partagés, support de domaines personnalisés, payloads signés, et traitement par lots. Pour les détails d’intégration canoniques, utilisez le contrat publié : Mailhook llms.txt.
Option 3 : Flux d’événements spécifiques aux fournisseurs (utile, mais souvent pas en forme de boîte)
Certains fournisseurs d’envoi d’email exposent des événements de livraison (accepté, rejeté, livré) et parfois des aperçus de messages. Ceci peut être utile quand vous vous souciez de la télémétrie de délivrabilité, mais ce n’est pas toujours suffisant pour les tests de style “cliquez ce lien magique”.
Dans la plupart des orgs, les équipes ont encore besoin d’une abstraction en forme de boîte (adresse, messages, récupération) pour les flux de vérification déterministes.
Table de décision rapide
| Objectif en CI | Meilleure approche | Sur quoi vous faites vraiment des assertions |
|---|---|---|
| “Nous avons généré le bon contenu d’email” | Capture SMTP locale | Sujet/de/à, corps texte, templates |
| “Un utilisateur peut compléter la vérification d’inscription” | API de boîte jetable | Arrivée dans le timeout, OTP ou lien extrait |
| “Comportement de délivrabilité et fournisseur” | Événements fournisseur + tests ciblés | Événements de livraison, rejets, signaux de plainte |
Si votre pipeline doit “voir les emails” comme un utilisateur les vivrait, les boîtes jetables gagnent.
Le pattern déterministe : boîte par exécution, attendre, parser le JSON
La clé est d’arrêter de penser en termes de “chercher dans une boîte mail.” En CI vous voulez un contrat explicite :
- Isolation : chaque exécution obtient sa propre boîte.
- Livraison : votre harnais de test a un moyen fiable d’attendre les messages (webhook d’abord, polling en repli).
- Consommation : vous faites des assertions sur des champs JSON stables, pas du HTML rendu.

💡 Faites Fonctionner le Pattern d’Email Déterministe en Minutes
Pourquoi reconstruire l’isolation de boîtes et le parsing JSON quand vous pouvez commencer à tester immédiatement ? Mailhook vous donne webhooks, polling et données email structurées prêtes à l’emploi - exactement ce dont ce pattern a besoin.
Étape 1 : Provisionner une boîte
Créez la boîte au début du test et gardez les deux :
- l’adresse email (ce qu’utilise votre app)
- le handle de boîte (ce qu’utilise votre harnais de test pour récupérer les messages)
Avec Mailhook, les champs exacts de requête et réponse sont documentés dans llms.txt. Traitez ce fichier comme la source de vérité dans les revues de code.
Étape 2 : Déclencher l’email
Exécutez l’action sous test, par exemple :
- inscription
- réinitialisation de mot de passe
- connexion par email
Pour le déterminisme, passez une valeur de corrélation que vous contrôlez (par exemple, un ID d’exécution) dans votre application pour qu’elle finisse dans l’email. Endroits communs :
- un paramètre de requête à l’intérieur du lien de vérification
- un en-tête personnalisé que votre mailer ajoute
- un token de référence dans le texte de l’email
Étape 3 : Attendre l’arrivée (le polling est plus simple à l’intérieur de la CI)
Les webhooks sont parfaits quand vous avez déjà un endpoint public. En CI, le polling est souvent plus facile et reste déterministe si vous implémentez timeouts et backoff.
Pseudocode de polling agnostique au fournisseur :
async function waitForEmail({ inboxId, matcher, timeoutMs }) {
const started = Date.now();
let delay = 250;
while (Date.now() - started < timeoutMs) {
const messages = await listMessages(inboxId); // appel API fournisseur
const match = messages.find(matcher);
if (match) return match;
await sleep(delay);
delay = Math.min(delay * 1.5, 2000);
}
throw new Error(`Timeout en attendant l'email dans la boîte ${inboxId}`);
}
La partie importante est le matcher : rendez-le assez étroit pour que les exécutions parallèles ne puissent pas matcher le mail de l’autre.
Étape 4 : Asserter sur le JSON, extraire seulement ce dont vous avez besoin
Une fois que vous récupérez une représentation JSON structurée, préférez des assertions comme :
- Le domaine expéditeur est correct
- Le destinataire correspond à l’adresse attendue
- Le sujet contient l’intention attendue
- Le corps texte contient un pattern OTP
Évitez les comportements fragiles :
- scraper le markup HTML
- dépendre du formatage exact ou CSS
- laisser un LLM “lire tout l’email” quand vous n’avez besoin que d’un OTP
Exemple d’extraction (OTP) :
import re
def extract_otp(text: str) -> str:
m = re.search(r"\b(\d{6})\b", text)
if not m:
raise ValueError("OTP non trouvé")
return m.group(1)
Étape 5 : Attacher le JSON email comme artefact CI (au lieu de l’imprimer)
Pour déboguer les échecs sans fuiter de secrets :
- écrire le JSON de message reçu dans un fichier
- l’uploader comme artefact
- caviarder ou omettre les champs sensibles où approprié
Dans GitHub Actions, l’upload d’artefact est simple :
- name: Save inbound email JSON
run: node scripts/save-email.js > email.json
- name: Upload email artifact
uses: actions/upload-artifact@v4
with:
name: inbound-email
path: email.json
C’est la plus grande différence pratique entre “débuggage manuel de boîte mail” et “visibilité email grade CI.” Vous obtenez un artefact durable lié à une exécution.
Webhooks en CI : quand ils ont du sens
Les webhooks sont idéaux quand :
- vous exécutez un environnement de test persistant avec une URL publique stable
- vous voulez la plus faible latence
- vous opérez déjà un petit service récepteur
Si vous utilisez des webhooks, traitez la requête webhook comme un canal d’entrée non fiable :
- vérifier les signatures
- imposer une tolérance de timestamp
- dédupliquer les livraisons (les retry arrivent)
Mailhook supporte les payloads signés, qui est la primitive correcte ici. Encore une fois, le format exact de signature et en-tête est décrit dans Mailhook llms.txt.
Checklist de fiabilité CI pour “voir les emails”
Ce sont les garde-fous qui suppriment la plupart des instabilités :
Utiliser une boîte unique par exécution (ou par tentative)
Si vous partagez des boîtes, vous finirez par matcher le mauvais message. L’isolation coûte moins cher que le débogage.
Préférer l’attente déterministe aux sleeps fixes
Remplacez sleep(10) par “attendre qu’un email correspondant arrive ou timeout.” Ceci améliore vitesse et stabilité.
Dédupliquer au bon niveau
Les pipelines email peuvent légitimement livrer des doublons à cause des retry. Votre harnais devrait être robuste en :
- sélectionnant le dernier message correspondant
- trackant les IDs de messages vus
- rendant la consommation idempotente
Traiter le contenu email comme une entrée hostile
Même dans les environnements de test, l’email peut contenir :
- HTML inattendu
- liens de tracking
- pièces jointes
Si un agent est impliqué, contraignez ce qu’il peut faire avec l’email. Extrayez un artefact minimal (OTP ou URL), validez-le, puis procédez.
Gardez les secrets hors des logs
Si vous devez logger quelque chose, loggez des identifiants :
- ID d’exécution
- ID de boîte
- ID de message
Puis stockez le contenu complet du message dans les artefacts avec des contrôles d’accès appropriés.
Plan d’implémentation minimal pour “voir les emails en CI”
Si vous partez d’une configuration de boîte mail partagée instable, migrez dans cet ordre :
Phase 1 : Arrêter de se connecter aux boîtes mail
- Remplacez les étapes d’UI de boîte mail par la récupération API.
- Stockez le message reçu comme artefact.
Phase 2 : Isoler
- Créez une boîte par exécution (ou par tentative pour les flux de vérification).
- Ajoutez un token de corrélation dans le contenu email.
Phase 3 : Rendez-le sécurisé et scalable
- Ajoutez la vérification de signature webhook si vous utilisez des webhooks.
- Ajoutez timeouts, déduplication, et messages d’erreur clairs.
- Considérez un domaine personnalisé si vous avez besoin d’allowlisting ou contrôle plus strict.
Mailhook supporte à la fois les domaines partagés instantanés et le support de domaines personnalisés, donc vous pouvez commencer vite et resserrer le contrôle plus tard.
Où Mailhook s’intègre
Si votre objectif est de voir les emails en CI sans jamais vous connecter à une boîte mail, vous voulez une boîte qui se comporte comme une ressource de test :
- provisionnée à la demande via API
- consommée en JSON structuré
- livrée via webhooks ou récupérée via polling
- sûre à exécuter en parallèle
C’est le workflow central pour lequel Mailhook est conçu. Utilisez la référence d’intégration canonique pour implémenter les appels exacts et formats de payload : Mailhook llms.txt. Vous pouvez aussi commencer par la vue d’ensemble produit sur Mailhook.