# Récupérer le code, les liens et les en-têtes d'un message

> Chaque message reçu arrive avec son code à usage unique, ses liens et ses en-têtes déjà extraits, sans rien configurer.
> https://facteur.eu/aide/extraction

Un test n'a presque jamais besoin du corps d'un email. Il a besoin **d'une chose
dans le corps** : un code à six chiffres, un lien de confirmation, un jeton. Nous
l'extrayons à la réception, et vous la lisez dans un champ. Il n'y a rien à
configurer.

## Les champs que vous obtenez

| Champ | Ce qu'il porte |
|---|---|
| `otp` | Le code à usage unique, quand le message en contient un seul évident |
| `codes` | Les autres suites de chiffres ou de caractères qui ressemblent à des codes |
| `links` | Chaque lien du message : son `href`, **déséchappé**, et son `text` |
| `headers` | Les en-têtes, en minuscules, pour retrouver les vôtres |
| `text.body` / `html.body` | Les deux versions du corps, telles qu'envoyées |

## Suivre un lien sans le déséchapper vous-même

Un lien écrit dans du HTML porte des entités : `&amp;` là où l'URL a un `&`. Un test
qui suit un lien encore échappé demande au serveur une URL dont le second paramètre
s'appelle `amp;next`. Il reçoit alors une page qui n'est pas celle qu'il attendait, et
aucune erreur ne le signale.

Les `href` que l'API renvoie sont déséchappés. Vous pouvez passer
`message.links[0].href` directement à `page.goto()` ou à `cy.visit()`.

## Quand `otp` est vide et `codes` est rempli

`otp` est renseigné quand le message contient **un seul** candidat clair.

Dès qu'il y en a plusieurs, par exemple un code de confirmation et un numéro de
commande à six chiffres, nous laissons `otp` vide et nous mettons les deux candidats
dans `codes`. Deviner lequel est le bon donnerait un test qui passe jusqu'au jour où
le numéro de commande change de longueur.

Dans ce cas, désignez la valeur dans un vrai message et laissez la plateforme écrire
le motif : c'est le sujet de [Pointeurs](pointeurs).

## Corréler un message avec l'exécution qui l'a déclenché

Posez un en-tête dans l'email que votre application envoie (`X-Test-Id`,
`X-Correlation-Id`), et retrouvez-le tel quel :

```js
const message = messages.find((m) => m.headers['x-test-id'] === executionId);
```

Lisez la clé **en minuscules**, toujours. Un en-tête est insensible à la casse sur le
fil : comparer la clé telle que vous l'avez envoyée donne un test qui marche jusqu'au
jour où votre bibliothèque d'envoi change de capitalisation.

## Limites connues

- **Nous ne devinons pas votre format.** Un identifiant maison ne ressemble à rien de
  connu. Utilisez un pointeur, voir [Pointeurs](pointeurs).
- **Nous ne lisons pas le contenu des pièces jointes.** Vous obtenez leur nom, leur
  taille et leur empreinte, voir [Lire depuis vos tests](lire-un-message).
- **Rien n'est extrait d'un message refusé.** Au-delà de votre quota, le message n'est
  ni stocké ni analysé, voir [Quotas et rétention](quotas-et-retention).
- **L'extraction a lieu après l'acquittement SMTP.** Un message existe donc pendant
  quelques millisecondes sans code ni liens. Lisez le champ `status` avant les champs
  extraits, voir [Lire depuis vos tests](lire-un-message).
