Skip to content
Tutorials

Vérification par Email Temporaire : Un Flux Déterministe pour les OTP

| | 13 min de lecture
Vérification par Email Temporaire : Un Flux Déterministe pour les OTP
Temp Email Verification: A Deterministic Flow for OTPs

La vérification OTP par email fait partie de ces flux qui “fonctionnent bien” jusqu’à ce que vous les mettiez en CI, lanciez des tests en parallèle, ou laissiez un agent LLM les piloter. Alors les modes d’échec habituels apparaissent rapidement : collisions de boîte partagée, sleeps fixes, emails en double, nouvelles tentatives qui renvoient des codes, et scraping HTML fragile.

La vérification par email temporaire ne devient fiable que lorsque vous traitez l’email de vérification comme un flux d’événements déterministe lié à une boîte de réception spécifique et éphémère, et non comme “une adresse quelconque” que vous espérez pouvoir lire plus tard.

Ce guide présente un flux OTP déterministe que vous pouvez réutiliser dans les tests E2E, l’automatisation QA, et les chaînes d’outils d’agents, avec des règles de conception concrètes pour l’attente, la déduplication, l’extraction et la sécurité.

Ce que devrait signifier “vérification par email temporaire” (pour les OTP)

Pour la vérification OTP, l’objectif n’est pas “recevoir un email” en général. L’objectif est :

  • Provisionner une boîte de réception isolée pour une tentative.
  • Déclencher exactement un email de vérification pour cette tentative.
  • Attendre l’arrivée en utilisant des budgets de temps explicites, pas sleep(10_000).
  • Parser le message comme données structurées, extraire seulement l’OTP (ou l’URL de vérification), puis procéder.
  • Rendre le tout sûr pour les nouvelles tentatives.

En pratique, vous voulez une API de boîte de réception qui modélise la boîte comme une ressource de première classe, afin de pouvoir lire de manière déterministe “les messages pour cette tentative” sans scanner une boîte partagée.

Mailhook est construit autour de ce modèle : créer des boîtes de réception jetables via API, recevoir les emails comme JSON structuré, et consommer la livraison via des webhooks temps réel ou une API de polling. Pour les détails d’intégration exacts, utilisez la spécification canonique : mailhook.co/llms.txt.

Les cinq invariants d’un flux OTP déterministe

Si vous n’adoptez qu’une chose de cet article, adoptez ces invariants. Ils font la différence entre instable et déterministe.

Isolation : une boîte par tentative

Les emails OTP sont intrinsèquement liés à une tentative. Si vous réutilisez une boîte entre les tentatives (ou entre des jobs CI parallèles), vous créez de l’ambiguïté.

Règle : créez une nouvelle boîte de réception jetable pour chaque tentative de vérification, pas par suite de tests, pas par environnement, pas par utilisateur.

L’isolation élimine les deux bugs les plus courants :

  • Un test lit l’OTP d’une exécution précédente.
  • Deux exécutions parallèles entrent en compétition et consomment les codes l’une de l’autre.

Attente déterministe : webhook-first, polling en fallback

L’arrivée des OTP est asynchrone et peut être retardée.

Règle : traitez l’arrivée d’email comme un événement. Préférez les webhooks pour une faible latence, mais implémentez le polling comme fallback afin que votre flux résiste aux problèmes transitoires de livraison webhook.

Si vous ne faites que du polling, vous faites souvent du sur-polling (coûteux) ou du sous-polling (lent). Si vous n’utilisez que des webhooks, vous pouvez échouer brutalement sur une mauvaise configuration réseau.

Corrélation : matchers étroits, pas “le dernier email gagne”

Même avec l’isolation de boîte, les nouvelles tentatives et le comportement du fournisseur peuvent créer des doublons. Rendez votre sélection déterministe en matchant sur l’intention.

Exemples de bonnes clés de correspondance :

  • Domaine d’expéditeur attendu
  • Préfixe de sujet ou identifiant de modèle
  • Présence d’un marqueur OTP dans text/plain
  • Un token de corrélation que vous contrôlez (par exemple, un en-tête personnalisé que votre app ajoute)

Idempotence : nouvelles tentatives sûres sans double-consommation

Dans les systèmes réels, les doublons arrivent : nouvelles tentatives du fournisseur, nouvelles tentatives webhook, et vos propres re-exécutions de tests.

Règle : le traitement doit être idempotent au niveau qui vous importe.

Pour les flux OTP, l’idempotence signifie généralement :

  • Déduplication au niveau message (même message traité une fois)
  • Déduplication au niveau artefact (même lien OTP ou code consommé une fois)

Extraction minimale : donnez à votre code (ou agent) seulement l’OTP

Traitez l’email entrant comme une entrée non fiable.

Règle : extrayez le plus petit artefact qui fait avancer le workflow, typiquement les chiffres OTP ou une seule URL de vérification, et évitez de passer du HTML brut aux agents.

Cela améliore la fiabilité (moins de surface de parsing) et réduit le risque (injection de prompt, liens malveillants, pixels de tracking).

Architecture de référence : le harnais OTP déterministe

Voici l’idée principale : construisez un petit “harnais OTP” avec une interface stable, puis réutilisez-le partout (Playwright, Cypress, tests d’intégration backend, outils d’agents).

Un diagramme de flux simple montrant la vérification OTP déterministe avec cinq étapes étiquetées : Créer une boîte de réception jetable (email + inbox_id), Déclencher inscription/connexion, Attendre la livraison (webhook-first avec fallback polling), Parser JSON et extraire OTP, Soumettre OTP et faire expirer la boîte.

Étape A : Provisionner une boîte (et garder à la fois email et inbox_id)

Votre système sous test a besoin d’une adresse email, mais votre harnais a besoin d’un handle de boîte.

Donc votre étape de création devrait retourner un objet comme :

  • email (l’adresse à taper dans l’UI ou envoyer à votre API)
  • inbox_id (le handle sur lequel vous attendez)
  • expires_at (pour que vous puissiez nettoyer correctement)

Avec Mailhook, la création de boîte de réception jetable se fait via API, et vous pouvez utiliser des domaines partagés instantanés ou le support de domaine personnalisé selon votre environnement. Utilisez le contrat canonique pour les champs et endpoints : mailhook.co/llms.txt.

Étape B : Déclencher l’email OTP (exactement une fois par tentative)

Votre harnais devrait appeler votre app pour démarrer la vérification. Déclencheurs typiques :

  • Inscription
  • Connexion par email
  • Réinitialisation de mot de passe
  • Flux “Vérifiez votre email”

La clé est que ce déclencheur est lié à la tentative. Si une nouvelle tentative arrive, vous devriez la traiter comme une nouvelle tentative avec une nouvelle boîte (ou appliquer des budgets de renvoi stricts).

Étape C : Attendre de manière déterministe le message correspondant

Concevez votre attente comme une boucle basée sur une deadline, pas comme un sleep fixe.

Une politique d’attente pratique :

  • Deadline totale : 60 à 120 secondes (dépend de l’environnement)
  • Intervalle de poll : backoff exponentiel avec jitter
  • Conditions d’arrêt : le premier message qui matche l’intention, ou deadline dépassée

Si vous avez des webhooks, vous pouvez raccourcir significativement le chemin heureux, mais vous voulez toujours un fallback polling.

Mailhook supporte à la fois les notifications webhook temps réel et une API de polling, plus des payloads signés pour la sécurité webhook.

Étape D : Extraire l’OTP du JSON structuré (préférez text/plain)

Ne scrapez pas le HTML si vous pouvez l’éviter.

Une approche d’extraction OTP robuste :

  • Préférez le contenu text/plain
  • Utilisez une regex conservative pour les OTP (et validez la longueur)
  • Si plusieurs codes existent, choisissez de manière déterministe (par exemple, le dernier code dans le corps, ou le message avec le received_at le plus récent)

Gardez la sortie minimale, retournez { otp, message_id, received_at } à l’appelant.

Étape E : Soumettre l’OTP et asserter le succès

Soumettez le code, puis assertez la post-condition :

  • La session utilisateur existe
  • Email marqué vérifié
  • Token invalidé

Enfin, laissez la boîte expirer (ou nettoyez explicitement si votre fournisseur supporte le contrôle de cycle de vie). Dans tous les cas, traitez le TTL de boîte comme partie de votre design d’intégration, pas comme une réflexion après coup.

Modes d’échec et corrections déterministes

La plupart de l’instabilité OTP est prévisible. Voici un mapping rapide que vous pouvez utiliser dans les revues de code.

Mode d’échec À quoi ça ressemble Correction déterministe
Collision de boîte partagée L’OTP appartient à une autre exécution de test Isolation boîte-par-tentative
Sleep fixe Parfois trop court, parfois lent Attente basée deadline avec webhook-first, fallback polling
Livraisons en double Même email traité deux fois Déduplication niveau message et niveau artefact
Dérive de modèle Le parsing casse quand la copie d’email change Asserter l’intention via des champs stables, extraire de text/plain
Boucle de renvoi L’agent continue à cliquer “renvoyer le code” Budgets et contraintes d’outils, une boîte par tentative
Spoofing webhook De fausses charges utiles entrent dans votre pipeline Vérifier les payloads signés, rejeter en cas d’échec de signature

Une fonction d’attente OTP agnostique au fournisseur (pseudocode)

Le point de ce snippet est la structure : isoler, attendre avec deadlines, matcher étroit, déduplication, extraire l’artefact minimal.

Ajustez les appels API à votre fournisseur. Pour les champs requête/réponse spécifiques à Mailhook et les en-têtes de signature, utilisez : mailhook.co/llms.txt.

type EmailWithInbox = {
  email: string;
  inbox_id: string;
  expires_at?: string;
};

type VerificationArtifact = {
  otp: string;
  message_id: string;
  received_at: string;
};

function extractOtpFromText(text: string): string {
  const matches = text.match(/\b(\d{6})\b/g) || [];
  if (matches.length === 0) throw new Error("OTP not found");
  return matches[matches.length - 1];
}

async function waitForOtp(params: {
  inbox: EmailWithInbox;
  deadlineMs: number;
  poll: (inbox_id: string, cursor?: string) => Promise<{ messages: any[]; next_cursor?: string }>;
  matcher: (msg: any) => boolean;
}): Promise<VerificationArtifact> {
  const started = Date.now();
  let cursor: string | undefined = undefined;
  const seenMessageIds = new Set<string>();

  while (Date.now() - started < params.deadlineMs) {
    const batch = await params.poll(params.inbox.inbox_id, cursor);
    cursor = batch.next_cursor;

    for (const msg of batch.messages) {
      const messageId = String(msg.message_id || msg.id);
      if (seenMessageIds.has(messageId)) continue;
      seenMessageIds.add(messageId);

      if (!params.matcher(msg)) continue;

      const text = String(msg.text || msg.text_plain || "");
      const otp = extractOtpFromText(text);

      return {
        otp,
        message_id: messageId,
        received_at: String(msg.received_at || msg.created_at || "")
      };
    }

    const elapsed = Date.now() - started;
    const backoff = Math.min(2000, 250 + Math.floor(elapsed / 10));
    await new Promise(r => setTimeout(r, backoff));
  }

  throw new Error("Timed out waiting for OTP email");
}

Choisir un bon matcher

Les matchers doivent être assez stricts pour éviter les faux positifs, mais pas si stricts qu’un petit changement de copie les casse.

Bons exemples de matchers :

  • Liste d’autorisation d’expéditeur et préfixe de sujet
  • Présence d’une phrase stable autour du code dans text/plain
  • Valeur d’en-tête que vous contrôlez (meilleure option quand faisable)

Évitez les matchers comme “le dernier email” ou “tout email contenant un nombre”. Ceux-ci finiront par casser.

Durcissement webhook (particulièrement important pour les agents)

Si vous ingérez des emails via webhooks, traitez la frontière webhook comme tout autre ingress public.

Pratiques clés :

  • Vérifiez les signatures sur le corps de requête brut (fail closed)
  • Appliquez une tolérance de timestamp pour réduire le risque de replay
  • Dédupliquez les livraisons (stockez un ID de livraison ou calculez un hash stable)
  • Gardez les handlers webhook rapides, acquittez rapidement, mettez le traitement en queue

Mailhook supporte les payloads signés pour la sécurité webhook. Pour l’algorithme de vérification exact et les noms d’en-têtes, suivez mailhook.co/llms.txt.

Si vous voulez des informations sur pourquoi DKIM “email signé par” n’est pas la même chose que l’authenticité du payload webhook, voir l’article d’ingénierie de Mailhook : Email Signed By: Verify Webhook Payload Authenticity.

Prévenir les boucles de renvoi et les “boucles de bot” dans la vérification OTP

L’UX OTP inclut souvent “renvoyer le code”. En automatisation, ce bouton est un piège.

Politiques déterministes qui arrêtent les boucles :

  • Donnez à chaque tentative un budget de renvoi strict (par exemple, un renvoi)
  • Si vous renvoyez, faites tourner les boîtes (nouvelle boîte par tentative de renvoi)
  • Ajoutez un budget de temps global, puis échouez avec des logs actionnables

Cela importe encore plus avec les agents LLM, car ils peuvent sur-apprendre sur “réessayer” et spammer les renvois.

Observabilité : que logger pour que les échecs soient actionnables

Quand la vérification OTP échoue en CI, vous voulez savoir si c’était :

  • Aucun email envoyé
  • Email envoyé mais retardé
  • Email reçu mais pas matché
  • Email matché mais extraction OTP échouée
  • OTP soumis mais rejeté

Loggez les identifiants, pas les emails entiers :

  • inbox_id
  • email
  • message_id
  • ID de livraison webhook (si applicable)
  • received_at
  • hash d’artefact extrait (pas l’OTP lui-même, si vous voulez minimiser les logs sensibles)

Si votre fournisseur retourne du JSON structuré, stockez ce JSON comme artefact CI pour le debugging, mais considérez la rétention et les contrôles d’accès.

Quand utiliser des domaines partagés vs domaines personnalisés

Pour la vérification par email temporaire, le choix de domaine est souvent une décision opérationnelle :

  • Les domaines partagés sont géniaux pour une configuration rapide et CI interne.
  • Les domaines personnalisés sont utiles quand vous avez besoin de listes d’autorisation, d’une séparation d’environnement plus forte, ou de contraintes enterprise.

Mailhook supporte les domaines partagés instantanés et le support de domaine personnalisé, donc vous pouvez commencer vite et migrer sans réécrire votre harnais.

Questions Fréquentes

Qu’est-ce que la vérification par email temporaire ? La vérification par email temporaire consiste à vérifier une adresse email en utilisant une boîte de réception éphémère à durée de vie courte. Pour les flux OTP, cela signifie provisionner une boîte par tentative, attendre de manière déterministe, extraire l’OTP, et terminer la vérification sans accès à une boîte partagée.

Pourquoi les tests OTP deviennent-ils instables en CI ? Les causes communes incluent les collisions de boîte partagée, les sleeps fixes, les retards de livraison, les emails en double des nouvelles tentatives, et le parsing fragile des modèles HTML. L’isolation plus les attentes basées deadline éliminent la plupart de l’instabilité.

Dois-je utiliser des webhooks ou du polling pour recevoir les emails de vérification ? Utilisez les webhooks par défaut pour une faible latence et l’efficacité, et gardez le polling comme fallback afin que votre flux survive aux échecs transitoires de webhook. Une approche hybride est la plus fiable.

Est-ce sûr de laisser un agent LLM lire les emails de vérification ? Ça peut l’être, si vous traitez l’email entrant comme une entrée non fiable, vérifiez l’authenticité webhook, évitez de rendre le HTML, validez les liens, et n’exposez que des artefacts extraits minimaux (comme l’OTP) à l’agent.

Où puis-je trouver le contrat API exact de Mailhook ? Mailhook publie une référence d’intégration canonique et lisible par machine à mailhook.co/llms.txt.

Construire un flux OTP déterministe avec Mailhook

Si vous voulez une vérification par email temporaire qui soit parallèle-safe et agent-friendly, Mailhook vous donne les primitives dont vous avez besoin : création de boîte de réception jetable via API, emails livrés comme JSON structuré, notifications webhook avec payloads signés, et une API de polling comme fallback.

Commencez par la référence d’intégration canonique, puis branchez-la dans votre harnais OTP : Mailhook llms.txt. Vous pouvez aussi explorer le produit sur mailhook.co.

email verification OTP automation testing webhooks API integration

Articles connexes