# Delivery Status Notifications : le format des DSN (RFC 3464)

> Comment sont structurés les messages de rebond : le format DSN multipart/report, les champs par message et par destinataire (Action, Status, Diagnostic-Code), et comment les expéditeurs devraient les analyser.

Source: emailmarketing.net — https://emailmarketing.net/fr/apprendre/gestion-des-rebonds/notifications-d-etat-de-livraison

Pour traiter les rebonds automatiquement, vous devez lire le message de rebond lisible par une machine que renvoient les serveurs de messagerie. Lorsqu'un message ne peut pas être livré (ou que sa livraison est retardée, ou qu'une notification positive que vous avez demandée se déclenche), le MTA qui fait le rapport renvoie une **Delivery Status Notification (DSN)**, ou notification d'état de livraison, à l'expéditeur d'enveloppe.

La RFC 3464 définit le format normalisé de ce message. Tout processeur automatique de rebonds est, au fond, un analyseur de ce format, complété d'heuristiques pour les rebonds qui ne le respectent pas.

## Règles d'enveloppe

- Une DSN envoyée par SMTP **DOIT utiliser une adresse de retour nulle** : `MAIL FROM:<>`. Cela empêche les boucles de messagerie, car aucune DSN n'est jamais générée pour une DSN.
- Il s'ensuit que les rebonds arrivent à l'adresse que vous avez indiquée dans le `MAIL FROM` du message d'origine. Une adresse de retour qui encode chaque destinataire (**VERP**, par exemple `bounces+user=example.com@sender.com`) vous permet d'identifier le destinataire en échec même lorsque le corps de la DSN est mal formé. Elle permet aussi à un [processeur de feedback loop](https://emailmarketing.net/fr/apprendre/gestion-des-listes/feedback-loops-de-plaintes) de réutiliser la même chaîne de suppression.
- Chaque destinataire indiqué par l'expéditeur DEVRAIT donner lieu à **au plus une** DSN « delivered » ou « failed ». Lorsqu'un message atteint un alias de liste de diffusion, le MTA de transfert DEVRAIT émettre une DSN « expanded » pour le destinataire d'origine, et ne devrait pas transmettre la demande de DSN aux adresses issues de l'expansion.

## Structure générale : multipart/report

Une DSN est un message MIME avec `Content-Type: multipart/report; report-type=delivery-status`. Elle contient :

| Partie | Content-Type | Rôle |
|---|---|---|
| 1 | `text/plain` (en général) | Une explication de ce qui s'est passé, à lire par un humain |
| 2 | `message/delivery-status` | L'état sous une forme qu'une machine peut analyser. C'est la partie que lisent les processeurs de rebonds |
| 3 | `message/rfc822` ou `text/rfc822-headers` | Le message d'origine renvoyé (ou ses en-têtes). Facultatif |

La partie `message/delivery-status` est un ensemble de groupes de champs écrits comme des en-têtes : un groupe **par message**, puis un groupe **par destinataire** pour chaque destinataire rapporté. Une ligne vide sépare les groupes.

## Champs par message

| Champ | Obligatoire ? | Syntaxe et signification |
|---|---|---|
| `Reporting-MTA` | **Obligatoire** | `mta-name-type; mta-name` : le MTA qui rapporte le résultat, par exemple `dns; mail.example.net` |
| `Original-Envelope-Id` | Facultatif | Identifiant de transaction fourni à la soumission, pour rapprocher la DSN de l'envoi d'origine |
| `DSN-Gateway` | Conditionnel | Présent uniquement quand la DSN a été traduite depuis un système de rapport étranger (non Internet) |
| `Received-From-MTA` | Facultatif | Nom du MTA dont le message a été reçu |
| `Arrival-Date` | Facultatif | Date et heure RFC 822 d'arrivée du message au MTA qui fait le rapport |

Les noms de MTA sont sensibles à la casse, et leur orthographe doit être conservée exactement.

## Champs par destinataire

| Champ | Obligatoire ? | Syntaxe et signification |
|---|---|---|
| `Final-Recipient` | **Obligatoire** | `address-type; generic-address` : l'adresse du destinataire telle que l'a vue le MTA qui fait le rapport |
| `Action` | **Obligatoire** | L'une des cinq valeurs ci-dessous |
| `Status` | **Obligatoire** | Code d'état étendu, `DIGIT.1*3DIGIT.1*3DIGIT` (par exemple `5.1.1`) |
| `Original-Recipient` | Facultatif | L'adresse telle que l'expéditeur l'a indiquée à l'origine (avant transfert ou réécriture) |
| `Remote-MTA` | Facultatif | Le MTA du saut suivant impliqué dans la tentative de livraison rapportée |
| `Diagnostic-Code` | Facultatif | `diagnostic-type; text` : l'erreur réelle au niveau du transport, par exemple la réponse SMTP complète du serveur distant |
| `Last-Attempt-Date` | Facultatif | Date et heure RFC 822 de la dernière tentative de livraison |
| `Final-Log-ID` | Facultatif | Référence dans le journal de livraison du MTA qui fait le rapport |
| `Will-Retry-Until` | Facultatif | Pour `delayed` uniquement : le moment où le MTA abandonnera |

### Valeurs d'Action (exactement cinq, insensibles à la casse)

| Action | Signification | Traitement par un processeur de rebonds |
|---|---|---|
| `failed` | N'a pas pu être livré, et la livraison est abandonnée définitivement | C'est le rebond. Classez-le à l'aide de `Status` et de `Diagnostic-Code` |
| `delayed` | Pas encore livré ; les tentatives continuent (voir `Will-Retry-Until`) | Informatif. Ne supprimez pas l'adresse, car une DSN `failed` peut suivre ou non |
| `delivered` | Livré avec succès à l'adresse du destinataire | Une DSN positive (envoyée uniquement si elle est demandée) ; ce n'est pas un rebond |
| `relayed` | Transmis vers un environnement qui ne prend pas la responsabilité des DSN | Terminal du point de vue des DSN, mais ce n'est pas une preuve de livraison |
| `expanded` | Livré à l'adresse indiquée par l'expéditeur, qui était un alias ou une liste à plusieurs destinataires qui a renvoyé le message | Non terminal ; utilisé uniquement pour les alias à plusieurs destinataires |

### Status et Diagnostic-Code

- `Status` porte le [code d'état étendu](https://emailmarketing.net/fr/apprendre/gestion-des-rebonds/codes-d-etat-etendus-smtp), qui ne dépend pas du transport. C'est la clé de classement principale (`4.x.x` temporaire, `5.x.x` définitif).
- `Diagnostic-Code` conserve l'erreur de transport brute. Lorsque son type est `smtp`, le texte est la réponse SMTP du serveur distant. La RFC note qu'il est « quelque peu redondant » avec `Status`, mais qu'il est fourni pour conserver l'information d'origine. Lorsque `Remote-MTA` est présent, le diagnostic vient de ce MTA ; sinon, il vient du MTA qui fait le rapport. En pratique, le texte du diagnostic contient souvent des détails propres au fournisseur (noms de listes de blocage, URL de politique, « user unknown ») que le `Status` numérique ne donne pas, donc analysez les deux.

### Conventions de type

- Les valeurs `address-type`, `mta-name-type` et `diagnostic-type` sont des atomes insensibles à la casse. Les valeurs standard sont `rfc822` (adresses), `dns` (noms de MTA) et `smtp` (diagnostics). `unknown` sert quand le type ne peut pas être déterminé, le préfixe `X-` marque les types expérimentaux, et les nouveaux types sont enregistrés auprès de l'IANA.
- Le contenu qui suit le type peut être sensible à la casse (les parties locales des boîtes aux lettres, par exemple) et doit être conservé exactement.

## Exemple (tiré de la RFC)

```
Reporting-MTA: dns; cs.utk.edu

Original-Recipient: rfc822;louisl@larry.slip.umd.edu
Final-Recipient: rfc822;louisl@larry.slip.umd.edu
Action: failed
Status: 4.0.0
Diagnostic-Code: smtp; 426 connection timed out
Last-Attempt-Date: Thu, 7 Jul 1994 17:15:49 -0400
```

## Conseils d'analyse pour les expéditeurs

1. **Identifiez le destinataire.** Privilégiez `Original-Recipient`, et à défaut `Final-Recipient`. Retirez le préfixe de type `rfc822;`. Si le corps ne peut pas être analysé, rabattez-vous sur l'adresse de retour encodée par VERP.
2. **Filtrez sur `Action`.** Seul `failed` doit entraîner une suppression. Ignorez `delayed` pour l'hygiène de base de données, mais journalisez-le pour la surveillance de la livraison. Traitez `delivered`, `relayed` et `expanded` comme des messages qui ne sont pas des rebonds.
3. **Classez sur `Status`.** Envoyez `5.x.x` vers votre logique de rebond définitif et `4.x.x` vers vos compteurs de rebonds temporaires. Utilisez la [table des codes de détail](https://emailmarketing.net/fr/apprendre/gestion-des-rebonds/codes-d-etat-etendus-smtp) pour séparer les codes d'adresse invalide (à supprimer) des codes de politique ou de réputation (à investiguer). Une vague de `5.7.1` est un problème d'expéditeur, pas un problème de liste.
4. **Affinez sur `Diagnostic-Code`.** Des règles par expression régulière ou par mot-clé, appliquées au texte SMTP brut, détectent les situations propres à un fournisseur que le code numérique masque (listes de blocage nommées, « spam content », avis de limitation de débit).
5. **Attendez-vous à plusieurs groupes de destinataires dans une même DSN.** Un seul message de rebond peut rapporter plusieurs destinataires, donc traitez chaque groupe séparément.
6. **Attendez-vous à des rebonds qui ne respectent pas le format.** Beaucoup de rebonds réels sont du texte libre sans aucune partie `message/delivery-status`. L'analyse selon la RFC 3464 est la voie rapide ; gardez une solution de repli heuristique, avec VERP comme filet de sécurité.
7. **Ne répondez jamais automatiquement à une DSN**, et n'envoyez jamais vos propres rebonds avec une adresse de retour non nulle. C'est la règle `MAIL FROM:<>` qui préserve l'écosystème de l'email des boucles.
