Codes de statut DLR : états de message SMPP et ce qu'ils affirment vraiment

Les accusés de réception sont ce qui se rapproche le plus d'une vérité de terrain dans une pile SMS - et ce n'est toujours pas une vérité de terrain. Cet article mappe les valeurs message_state de SMPP v3.4 à ce que chacune affirme et n'affirme pas, quels états peuvent encore évoluer, comment le texte d'accusé et les familles d'erreurs réseau s'y intègrent, et comment les traiter dans les webhooks sans trop se fier à un seul champ de statut.

ACCEPTEDENROUTEDELIVEREDfinalEXPIREDfinalUNDELIVERABLEfinalREJECTEDfinalDELETEDfinalles états intermédiaires (petits points) peuvent encore changer ; les états finaux (grands points) ne le peuvent pas

Valeurs message_state SMPP v3.4 : ce que chacune affirme

SMPP v3.4 définit un petit ensemble de valeurs message_state utilisées dans les accusés deliver_sm et les réponses query_sm. Traitez-les comme des classifications rapportées par le réseau, pas comme une preuve forensique du comportement du terminal. La même étiquette peut provenir de différents hops avec des niveaux de confiance différents. Associez toujours l'état au texte d'accusé, à tout code d'erreur réseau, et à vos horodatages submit/done.

ENROUTE affirme que le message a été accepté dans le chemin de livraison et n'est pas encore dans un résultat terminal connu du nœud rapporteur. Il n'affirme pas que le terminal a sonné, que la requête HLR a réussi, ni que le message sera finalement livré. DELIVRD ou DELIVERED affirme qu'un nœud en aval a rapporté une livraison réussie au terminal ou à un endpoint store-and-forward accepté que le réseau traite comme livré. Il n'affirme pas la lecture par l'utilisateur, l'installation d'une app, ni que votre contenu s'est affiché correctement. EXPIRED affirme que la période de validité s'est écoulée sans rapport de livraison réussie jugé final par le réseau. Il n'affirme pas que le terminal était éteint tout le temps - seulement que le temps a expiré selon les règles du chemin.

DELETED affirme que le message a été retiré d'un centre de messages ou d'une file avant la livraison finale, en général par une action administrative ou une purge réseau. Il n'indique ni qui a initié la suppression, ni si un terminal a jamais vu le SMS. UNDELIVERABLE affirme que le réseau a conclu que la livraison ne peut aboutir dans les conditions actuelles. Il ne marque pas définitivement le MSISDN comme invalide pour toute tentative future ; les conditions changent. ACCEPTED affirme que le message a été accepté par une entité en aval qui ne renverra pas forcément une livraison classique au terminal - courant pour certains endpoints applicatifs ou sémantiques d'acceptation intermédiaire. Ce n'est pas un synonyme de DELIVERED.

UNKNOWN affirme que le nœud rapporteur ne peut pas rattacher le résultat à un état plus précis. Cela ne signifie pas que le message a disparu sans logs de votre côté ; cela signifie que l'accusé reçu est peu informatif. REJECTED affirme que le message a été refusé par une politique réseau ou plateforme avant ou à la place de l'achèvement normal de la tentative de livraison. Cela ne signifie pas toujours que le numéro est invalide - contenu, expéditeur, débit ou règles de blocage peuvent produire le même état selon le chemin.

Les comptes SMSRoute incluent des crédits de test gratuits qui prouvent la livraison avant paiement, et des outils de test de livraison sont disponibles dans le tableau de bord SMSRoute.

message_stateAffirmeN'affirme pas
ENROUTEEn cours sur un chemin rapporteurTerminal atteint ou succès éventuel
DELIVEREDRapport de succès en aval reçuAccusé de lecture, succès UX ou vérité immuable
EXPIREDFenêtre de validité écoulée sans succèsÉchec permanent du terminal ou du numéro
DELETEDRetiré du MC/file avant livraison finaleIdentité de l'acteur ou visibilité du terminal
UNDELIVERABLELe chemin a conclu que la livraison ne peut aboutir maintenantInvalidité permanente à vie
ACCEPTEDAccepté par un endpoint aux sémantiques DLR non classiquesLivraison terminal équivalente à DELIVERED
UNKNOWNAucune meilleure classification disponibleAbsence de tout log système
REJECTEDRefusé par politique ou règles de routageToujours un MSISDN invalide

États finaux versus intermédiaires

Les états intermédiaires peuvent encore changer. ENROUTE est l'état intermédiaire clair : un DELIVERED, EXPIRED, UNDELIVERABLE, REJECTED, DELETED ou même ACCEPTED ultérieur peut suivre. UNKNOWN doit être traité opérationnellement comme non final sauf si votre contrat amont en dispose autrement ; de nombreuses intégrations voient UNKNOWN remplacé quand un accusé plus clair arrive, et certaines ne reçoivent jamais de mise à jour.

Les états finaux sont ceux pour lesquels votre gestionnaire doit normalement cesser les tentatives de soumission : DELIVERED, EXPIRED, DELETED, UNDELIVERABLE, REJECTED, et typiquement ACCEPTED lorsque le chemin utilise ACCEPTED comme acceptation applicative terminale. Final signifie final pour cette identité de message sur ce chemin, pas final pour le résultat métier. Un DLR DELIVERED peut encore être erroné ; un EXPIRED peut être suivi d'un SMS tardif visible par l'utilisateur uniquement dans des configurations défectueuses ou multi-chemins, à traiter comme un signal de défaut plutôt qu'un comportement SMPP attendu.

Concevez les machines d'états autour de la corrélation par message id, pas autour de l'espoir. Si vous recevez ENROUTE, gardez la ligne ouverte. Si vous recevez un état final, fermez les retries sortants pour cet id, enregistrez les champs state et err, et ne rouvrez que selon une politique explicite de conflit d'id dupliqué que vous contrôlez. Ne repassez pas DELIVERED en ENROUTE parce qu'un second accusé paraît plus favorable : journalisez l'anomalie.

Convention de texte d'accusé et familles de codes d'erreur réseau

De nombreux accusés deliver_sm SMSC intègrent un court corps texte selon une convention durable de style ESM. Les champs apparaissent souvent comme jetons étiquetés : id (l'identifiant du message tel que le MC le connaît), sub (nombre de submits), dlvrd (nombre de délivrés), submit date, done date, stat (état textuel tel que DELIVRD, EXPIRED, UNDELIV, ACCEPTD, REJECTD) et err (code d'erreur réseau ou MC). Le parsing doit être défensif : espacement, zéros de remplissage des dates et orthographes de stat varient selon le chemin. Préférez le TLV message_state structuré quand présent, et utilisez stat comme corroboration plutôt que seul signal.

Le champ err n'est pas un dictionnaire universel. Opérateurs et hubs compressent des échecs distincts en codes qui se chevauchent. Travaillez par familles qualitatives plutôt que d'inventer des tables par opérateur. Famille abonné absent : le réseau n'a pas pu joindre l'abonné - éteint, hors couverture ou temporairement détaché, selon le hop. Famille mémoire terminal : le stockage de l'appareil ou de la SIM a refusé ou différé la réception. Famille d'interdiction : un barring d'expéditeur, de destination, de classe de contenu ou d'abonné a empêché l'aboutissement. Famille échec de routage : aucune route viable, réseau de destination injoignable depuis cet interconnect, ou format d'adresse rejeté avant livraison profonde. Ces familles guident retries et messages utilisateur ; elles ne justifient pas des mythes codés en dur qu'un seul code numérique signifie toujours une cause racine.

Mappez les familles au comportement produit avec retenue. Les issues abonné absent et mémoire terminal justifient souvent un retry limité, conscient de la validité, ou un suivi plus lent. Barring et de nombreux échecs de routage ne doivent en général pas être martelés par des resoumissions rapides du même payload. Quand err est absent ou zéro alors que stat indique un échec, croyez la classe d'échec et conservez l'accusé brut pour escalade support.

L'outil de consultation des codes d'erreur SMSRoute couvre les mêmes états de façon interactive.

EXPIRED versus REJECTED en pratique

EXPIRED et REJECTED sont tous deux typiquement finaux, mais répondent à des questions différentes. EXPIRED signifie que le message a pu tenter dans une période de validité et que cette fenêtre s'est terminée sans succès accepté par le nœud déclarant. Les causes se regroupent autour de l'indisponibilité du terminal, d'une livraison différée jamais aboutie, ou d'une latence de chemin au-delà du TTL fixé par vous ou le MC. REJECTED signifie un refus - politique, filtrage, adresse invalide ou non routable au hop de rejet, blocage commercial, ou déni similaire immédiat ou quasi immédiat - plutôt qu'un simple écoulement du temps.

Dans les handlers, EXPIRED invite à inspecter la configuration de validité, submit time versus done time, et si ENROUTE a persisté jusqu'au timeout. REJECTED invite à inspecter le format de destination (E.164 jusqu'à 15 chiffres), les permissions d'expéditeur, les règles de contenu, et si le rejet est survenu juste après le submit. Un REJECTED immédiat à latence quasi nulle est une histoire opérationnelle différente d'un long ENROUTE qui devient EXPIRED en bordure de validité. Ni l'un ni l'autre n'est un synonyme poli de l'autre ; les fusionner en un seul booléen failed jette le signal de retry et de conformité.

Signaux d'alerte de faux DLR

Parce que les DLR ont une valeur réputationnelle, traitez les accusés invraisemblables comme des incidents de premier plan. Signaux d'alerte : DELIVERED uniforme sur de grands ensembles de destinations mixtes sans variance dans les familles de résultats attendues en trafic réel, et latence invraisemblable - dates done au niveau du bruit de mesure du submit avec succès parfait, ou latences fixes qui ne varient pas avec la région de destination ou l'heure. Autre signal : un texte stat qui ne contredit jamais un err toujours à zéro sur des routes sujettes aux échecs, ou des message ids sans corrélation avec vos réponses de submit.

Quand des signaux d'alerte apparaissent, figez les hypothèses automatisées qui assimilent DELIVERED à la joignabilité utilisateur, conservez les PDU bruts ou payloads webhook, et vérifiez avec des expéditeurs contrôlés que vous opérez. Les comptes SMSRoute incluent des crédits de test gratuits qui prouvent la livraison avant paiement, et des outils de test de livraison sont disponibles dans le tableau de bord SMSRoute. Utilisez-les pour établir une base de mix d'états et de timings réalistes avant de confier une nouvelle route à la logique de production.

Le guide DLR SMSRoute explique les mécanismes webhook par lesquels ces états arrivent.

Comment les utiliser dans les handlers webhook

Structurez le webhook comme un corrélateur, pas un switch sur un seul champ. Clé sur le message id fournisseur renvoyé au submit ; stockez vous-même les horodatages de submit ; ingérez message_state ou stat, err et done date ; puis faites transitionner votre enregistrement interne avec une machine d'états explicite. Acceptez HTTP 200 uniquement après persistance durable de l'accusé pour éviter que les retries fournisseur doublent les effets de bord ; répondez HTTP 429 ou HTTP 500 seulement si vous avez vraiment besoin d'un retry, et gardez ces chemins idempotents.

Normalisez les états entrants dans votre propre enum qui préserve les distinctions SMPP : au minimum séparez delivered, expired, rejected, undeliverable, accepted, deleted, enroute et unknown. Attachez des tags de famille d'erreur qualitativement sans prétendre à des dictionnaires officiels d'opérateurs que vous ne maintenez pas. Pour ENROUTE et UNKNOWN non résolu, planifiez l'observation, pas un succès face utilisateur. Pour DELIVERED, marquez le succès transport et conditionnez encore les actions métier critiques à vos propres accusés applicatifs quand le domaine l'exige.

Enfin, journalisez p50 et p95 de la latence submit-to-done par classe de route pour que les schémas de DLR faux ou dégradés apparaissent comme des décalages de distribution plutôt que des anecdotes. Gardez la discipline de taille de payload à l'envoi : les règles de segmentation 160/153 GSM-7 et 70/67 UCS-2 façonnent encore splits et échecs partiels en aval, mais n'inventez pas de pourcentages de livraison. L'incertitude fait partie de la surface du protocole ; des handlers précis enregistrent ce qui a été affirmé, ce qui ne l'a pas été, et la suite prévue.

Questions fréquentes

Quelles sont les valeurs message_state SMPP v3.4 et lesquelles sont finales ?
L'ensemble v3.4 inclut ENROUTE, DELIVERED, EXPIRED, DELETED, UNDELIVERABLE, ACCEPTED, UNKNOWN et REJECTED. ENROUTE est intermédiaire et peut encore changer ; UNKNOWN est opérationnellement non final sauf si votre contrat amont en dispose autrement. DELIVERED, EXPIRED, DELETED, UNDELIVERABLE, REJECTED, et typiquement ACCEPTED sont traités comme finaux pour cet id de message sur ce chemin.
En quoi EXPIRED diffère-t-il de REJECTED sur un DLR SMS ?
EXPIRED signifie que la période de validité s'est écoulée sans succès accepté par le nœud déclarant après que le message a pu tenter la livraison. REJECTED signifie un refus selon des règles de politique, de routage ou de filtrage plutôt qu'une expiration. Rejets immédiats et longs chemins enroute-puis-expired ne doivent pas être fusionnés en un seul seau failed si vous vous souciez des retries et des correctifs de configuration.
Quels champs apparaissent dans un corps texte d'accusé de livraison SMPP classique ?
Les jetons étiquetés courants incluent id, sub, dlvrd, submit date, done date, stat et err. Utilisez message_state structuré quand disponible et traitez stat/err comme corroboration ; regroupez les codes err en familles qualitatives (abonné absent, mémoire terminal, barring, échecs de routage) plutôt que de les prendre pour une table universelle par opérateur.

Connexe