Aller au contenu

Lire votre premier e-mail de test

Un test qui inscrit un utilisateur finit dans une boîte aux lettres : l’e-mail de confirmation porte un code ou un lien, et le test doit le lire. Playwright et Cypress pilotent un navigateur, et un navigateur ne reçoit aucun e-mail. Facteur est la boîte à laquelle votre application écrit pendant le test. Votre test demande le message à l’API, et le code et les liens reviennent déjà extraits : rien dans votre suite ne lit un corps HTML.

Une inbox est une boîte aux lettres que vos tests lisent par l’API. Elle reçoit sur un domaine entier, et chaque message garde l’adresse exacte à laquelle il a été envoyé.

  • Vous êtes propriétaire ou administrateur de votre organisation Facteur. Seuls ces deux rôles créent des clés d’API.
  • Vous pouvez faire écrire votre application à une adresse de votre choix.
  • Vous avez curl, ou n’importe quel client HTTP.
  1. Ouvrez Paramètres, puis Clés d’API, dans l’application Facteur, et choisissez Créer une clé.
  2. Nommez la clé d’après l’endroit où elle tourne, par exemple GitHub CI. Dans six mois, le nom vous dira quelle clé révoquer.
  3. Laissez la permission de lecture sur une clé qui ne fait que lire des messages. Une suite de tests n’a pas besoin de plus.
  4. Choisissez une durée de 30, 90, 180 ou 365 jours.
  5. Copiez la clé quand elle apparaît. Facteur n’en garde qu’une empreinte : la clé s’affiche une seule fois.

Exportez-la dans le terminal où vous allez travailler :

Terminal window
export FACTEUR_API_KEY=fk_votre_cle

Chaque requête porte la clé dans l’en-tête Authorization. Celle-ci liste les inboxes que la clé atteint :

list-inboxes.sh
curl --silent --show-error --fail-with-body \
-H "Authorization: Bearer $FACTEUR_API_KEY" \
https://api.facteur.eu/inboxes

La réponse est un 200 avec un tableau JSON. Un tableau vide est une réponse valide : la clé fonctionne, et les espaces de travail qu’elle atteint ne contiennent pas encore d’inbox. Chaque inbox porte un id de huit caractères. Cet identifiant est le premier segment de son adresse.

Si la réponse est un 401, le guide des erreurs dit laquelle des trois raisons c’est.

Faites écrire votre application à une adresse de cette forme :

signup+run-4821@j3k9x2mq.inbox.facteur.eu

Tout ce qui précède l’arobase vous appartient, et j3k9x2mq est l’id de l’inbox. Toute adresse qui finit par @j3k9x2mq.inbox.facteur.eu arrive dans cette inbox, sans rien créer avant. Donnez à chaque test sa propre étiquette après le +, comme un numéro d’exécution ou un nom de branche. Deux tests partagent alors une inbox et chacun ne lit que son courrier.

search.sh
curl --silent --show-error --fail-with-body --get \
-H "Authorization: Bearer $FACTEUR_API_KEY" \
--data-urlencode "inbox=j3k9x2mq" \
--data-urlencode "sentTo=signup+run-4821" \
--data-urlencode "wait=20000" \
https://api.facteur.eu/messages

wait est un nombre de millisecondes. Tant que rien ne correspond, la requête reste ouverte pendant ce temps, cinq minutes au plus. Si rien n’a correspondu à l’échéance, la réponse est quand même un 200, avec une liste vide.

Une recherche est une requête GET : --get fait mettre par curl chaque --data-urlencode dans l’adresse de la requête, et écrit les caractères spéciaux à votre place. Les mots que vous cherchez font donc partie de cette adresse, et un proxy entre votre machine et Facteur peut les écrire dans ses journaux. Cherchez une adresse, un sujet ou un code, jamais un secret. Limites donne la longueur maximale de chaque critère.

Un message revient sous cette forme :

{
"messages": [
{
"id": "0198f0a0-7d3e-7000-8000-00000000e2a1",
"inbox": "j3k9x2mq",
"type": "email",
"status": "parsed",
"fromAddress": "no-reply@example.test",
"toAddress": "signup+run-4821@j3k9x2mq.inbox.facteur.eu",
"subject": "Votre code de confirmation",
"otp": "418302",
"codes": ["418302"],
"links": ["https://example.test/confirm?token=abc"],
"textBody": "Your confirmation code is 418302.",
"htmlBody": "<p>Your confirmation code is <b>418302</b>.</p>",
"receivedAt": "2026-10-13T09:41:07+00:00"
}
],
"nextCursor": null
}

otp est le code à usage unique que Facteur a trouvé dans le message, et null s’il n’y en a pas. links liste les liens du message dans l’ordre où ils apparaissent. textBody et htmlBody sont les deux corps du message : un lien ou un code qu’aucun champ ne porte se lit dans la réponse de la recherche, sans second appel. status vaut parsed quand chaque champ lu dans le corps est rempli. Une recherche ne renvoie que les messages parsed, sauf si vous envoyez status=any.

  • Cherchez sur sentTo, jamais sur le sujet ni sur « le dernier message ». Deux tests qui partagent une inbox liraient sinon le courrier l’un de l’autre.
  • Mettez le numéro de tentative dans l’étiquette. Un test relancé ne lit alors pas le message de sa première tentative pour réussir à tort.