Saltar al contenido
nvíame
Capítulo 3 de 512 min16 sep 2026

Entrega, reportes DLR y estados

Qué significa realmente 'entregado' y cómo modelar la máquina de estados de un mensaje.

Un DLR (Delivery Receipt) es el acuse que la red genera cuando un mensaje cambia de estado. El proveedor lo recibe del operador vía SMPP y te lo reenvía a tu webhook. Es la única fuente de verdad sobre si el mensaje llegó.

La máquina de estados

Cada proveedor usa nombres ligeramente distintos, pero el modelo es estable. Un mensaje nace queued, pasa a sent cuando sale hacia el operador, y termina en un estado final: delivered, undelivered, failed o expired.

queued ──▶ sent ──▶ delivered
   │          ├──▶ undelivered   (el operador lo rechazó)
   │          └──▶ expired       (venció la validez)
   └──▶ failed                    (rechazado antes de salir)

Cómo guardar los estados

Persiste cada evento en una tabla de historial y calcula el estado actual como el más avanzado recibido. Así resistes desorden, duplicados y reintentos del webhook.

Actualizar el estado del mensaje
+const RANK = { queued: 0, sent: 1, delivered: 2, undelivered: 2, failed: 2, expired: 2 };
+
function onStatus(evt) {
− db.messages.update(evt.id, {
− status: evt.status,
− });
+ db.events.insert(evt); // historial completo
+ const current = db.messages.get(evt.id);
+ if (RANK[evt.status] >= RANK[current.status]) {
+ db.messages.update(evt.id, { status: evt.status });
+ }
}
Mostrando: antes · haz clic para alternar

Códigos de error

Junto al estado, los DLR traen un código de error del operador: número inexistente, terminal bloqueado, spam detectado. Agrúpalos en categorías accionables —permanente o temporal— y deja de enviar a números con errores permanentes repetidos. Tu tasa de entrega y tu reputación con los operadores lo agradecerán.

Una máquina de estados honesta

Modela los estados como una máquina con transiciones permitidas: accepted → sent → delivered, o sent → failed, o sent → expired. Nunca permitas que un estado final retroceda. Los webhooks llegan desordenados con más frecuencia de la que crees, y un sent tardío no debe sobrescribir un delivered que ya registraste.

Cuando no recibes DLR alguno, no asumas éxito ni fracaso: el estado correcto es desconocido. Algunos operadores no reportan acuses para ciertos rangos de numeración, y tu panel debe mostrarlo así en lugar de inflar la tasa de entrega.

Se completa automáticamente al leer el 80%.

Comentarios (3)

Valentina Muñoz16 sep 2026

Algunos mensajes quedan en `sent` para siempre. ¿Debo reenviarlos?

Equipo nvíameAutor16 sep 2026

Primero espera el periodo de validez. Muchos operadores no envían DLR intermedios, y un `sent` sin respuesta tras 72 horas suele terminar en `expired`. Reenviar antes duplica el mensaje si el original estaba en cola.

Joaquín Vega16 sep 2026

Lo apliqué en el proyecto del trabajo. La sección «Entrega, reportes DLR y estados» me ahorró una discusión larga con el equipo: ahora tenemos un criterio compartido.

Matías Herrera16 sep 2026

¿Hay alguna diferencia importante si lo implemento en un servicio con varias instancias detrás de un balanceador?

Equipo nvíameAutor16 sep 2026

Sí: todo estado que hoy vive en memoria (contadores, sesiones, claves vistas) debe moverse a un almacén compartido con TTL, como Redis. Si no, cada instancia ve solo una parte de la historia.

Los comentarios se guardan solo en este navegador.