Correlazione dei messaggi A2P SMS: tracciabilità tra API, SMPP, fornitori e DLR
Progetta una catena di identificatori ed eventi per analizzare messaggi A2P SMS tramite API HTTP, SMPP, fornitori, tentativi, segmenti e ricevute di consegna, senza confondere l'accettazione con la consegna.

Perché l'identificatore del fornitore non è sufficiente
Un identificatore emesso da un fornitore è necessario, ma raramente basta a spiegare l'intero ciclo di vita di un SMS A2P. In genere identifica una specifica accettazione nel dominio di quel fornitore. Non rappresenta, da solo, la richiesta originale del cliente, la decisione di instradamento, un tentativo successivo, i segmenti di un messaggio concatenato o gli eventi che potrebbero arrivare in seguito.
Il problema emerge nelle operazioni reali: una richiesta può restare in coda, generare più di un tentativo, cambiare instradamento in base a una politica interna o ricevere un callback tardivo. Se il sistema conserva soltanto l'identificatore esterno, sarà difficile rispondere con precisione a cosa è stato inviato, quale tentativo ha prodotto un DLR e quale parte dell'evidenza proviene da ciascun sistema.
La regola operativa è mantenere un identificatore interno stabile per il messaggio logico e registrare, senza sostituirli, gli identificatori assegnati a ogni confine tecnico. L'identificatore del fornitore deve essere trattato come una chiave di correlazione all'interno di una relazione più ampia, non come l'identità globale del messaggio.
- Non equiparare l'accettazione del fornitore alla consegna al terminale.
- Non riutilizzare un ID del fornitore come ID interno di business.
- Non presumere che due fornitori utilizzino lo stesso formato, ambito o durata per i propri identificatori.
- Conservare le risposte e gli eventi originali insieme alla relativa interpretazione normalizzata.

Mappa della catena di tracciabilità
La tracciabilità deve modellare stati ed eventi, non soltanto una tabella finale degli stati. Una catena minima inizia con la richiesta ricevuta dal cliente, prosegue con la sua convalida e l'inserimento in coda, e registra ogni tentativo di invio creato dal sistema. Per ogni tentativo accettato da un fornitore, viene aggiunto l'identificatore restituito da quel fornitore. I DLR e i callback successivi vengono memorizzati come eventi separati.
Questo approccio evita una comune perdita di contesto: sovrascrivere lo stato precedente con l'ultimo evento ricevuto. Un DLR è evidenza di un evento successivo; non sostituisce l'evidenza che sia stata ricevuta una richiesta, che sia stato creato un tentativo o che un fornitore abbia risposto alla presentazione.
Una mappa pratica può seguire questa sequenza: richiesta del cliente, messaggio logico interno, decisione di instradamento, tentativo di invio, presentazione HTTP o SMPP, accettazione o errore del fornitore ed eventi di stato successivi. Quando esiste segmentazione, ogni segmento deve essere collegato al messaggio logico e, quando appropriato, al tentativo che lo ha generato.
- Richiesta del cliente: registra il riferimento del cliente, se presente, e l'ora di ricezione.
- Messaggio logico: rappresenta l'intenzione di inviare un contenuto a una destinazione.
- Tentativo: rappresenta una presentazione concreta tramite uno specifico instradamento o fornitore.
- Accettazione del fornitore: registra l'ID esterno e la risposta ricevuta.
- Evento DLR o callback: conserva il payload originale, l'ora di ricezione e l'associazione risultante.
- Stato derivato: deve poter essere ricostruito a partire dagli eventi, non sostituirli.

Modello di identificatori consigliato
Uno schema robusto separa gli identificatori per funzione e ambito. Il correlation ID collega la richiesta iniziale all'elaborazione interna. L'idempotency key protegge dai duplicati della stessa richiesta del cliente. Il message ID interno identifica il messaggio logico. L'attempt ID identifica ogni presentazione concreta. Il provider message ID registra l'identificatore restituito da un fornitore per una specifica accettazione.
Queste chiavi non sono intercambiabili. In particolare, un nuovo tentativo non deve ricevere lo stesso attempt ID, anche se rappresenta lo stesso messaggio logico. Analogamente, due richieste ripetute non dovrebbero creare messaggi logici distinti se viene riconosciuta la stessa idempotency key valida nell'ambito della politica definita dalla piattaforma.
Genera ID interni con sufficiente unicità e mantienili opachi per i clienti esterni, salvo diversa previsione del contratto di integrazione. La struttura dell'ID non deve rivelare numeri di telefono, contenuto, fornitore, instradamento o informazioni operative sensibili.
- correlation ID: creato alla ricezione dell'operazione o del contesto di business; collega sistemi interni e registri correlati.
- idempotency key: fornita dal cliente o definita dall'integrazione; rileva le ripetizioni della stessa operazione.
- message ID interno: creato all'accettazione del messaggio logico nel sistema proprietario; è stabile durante il suo ciclo di vita.
- attempt ID: creato per ogni tentativo di presentazione; cambia a ogni nuovo tentativo o cambio di instradamento.
- provider message ID: ricevuto dopo l'accettazione di un tentativo da parte del fornitore; può avere un formato opaco e specifico del fornitore.
- event ID: creato al momento dell'acquisizione di ogni callback, DLR o risultato di interrogazione; consente di deduplicare e verificare gli eventi.
Cosa deve creare ogni parte e cosa non deve essere riutilizzato
Il cliente può fornire una idempotency key o un riferimento di business. La piattaforma deve creare i propri ID di correlazione, messaggio, tentativo ed evento. Ogni fornitore può restituire il proprio identificatore di messaggio. Questa distribuzione consente di mantenere responsabilità chiare ed evita che una chiave con ambito limitato diventi impropriamente una chiave universale.
Non riutilizzare una idempotency key come message ID, né un message ID interno come attempt ID. Non trasformare nemmeno un provider message ID in un riferimento del cliente. Questi riutilizzi sembrano semplificare il modello all'inizio, ma impediscono di rappresentare nuovi tentativi, migrazioni di instradamento e discrepanze tra sistemi.
Se un'integrazione HTTP consente di aggiungere parametri personalizzati all'URL di callback, questi possono fungere da indizio aggiuntivo per l'associazione. Tuttavia, non sostituiscono l'ID nativo del fornitore né giustificano l'omissione della convalida dell'origine, della registrazione completa dell'evento e della riconciliazione successiva.
- Una richiesta ripetuta può condividere la stessa idempotency key, ma non deve produrre due messaggi logici se la politica la riconosce come duplicata.
- Un messaggio logico può avere molti tentativi.
- Ogni tentativo può ricevere zero, uno o più identificatori esterni, a seconda dell'interfaccia e degli eventi disponibili.
- Un callback ricevuto non deve generare automaticamente un nuovo messaggio quando il suo riferimento è sconosciuto.
- L'associazione deve registrare metodo e livello di confidenza: esatta, probabile o non risolta.
Relazioni uno a uno e uno a molti: messaggi, segmenti, tentativi, instradamenti e DLR
Il messaggio logico è l'entità centrale, ma non coincide sempre con una sola presentazione né con una sola unità tecnica SMS. Un contenuto concatenato può essere suddiviso in più segmenti. Uno stesso messaggio può generare più tentativi. Ogni tentativo può transitare su un instradamento diverso e produrre eventi successivi separati.
Modella esplicitamente queste relazioni. Un messaggio logico può avere uno o più segmenti; ogni segmento può richiedere il proprio risultato tecnico. Un messaggio logico può avere uno o più tentativi, mentre un tentativo deve appartenere a un solo messaggio logico. Un tentativo può avere una decisione di instradamento registrata e uno o più eventi del fornitore o DLR associati.
In SMPP, i messaggi concatenati possono essere correlati tramite sar_msg_ref_num, sar_total_segments e sar_segment_seqnum. Il riferimento SAR viene generato dall'originatore per consentire il riassemblaggio. È utile conservarlo come attributo tecnico di segmentazione, ma non deve sostituire il message ID interno della piattaforma.
- Messaggio logico a segmenti: uno a molti.
- Messaggio logico a tentativi: uno a molti.
- Tentativo a fornitore o instradamento: normalmente uno a uno per presentazione, sebbene debba essere mantenuta la cronologia delle decisioni.
- Tentativo a eventi: uno a molti.
- Segmento a DLR: può essere uno a molti quando vi sono eventi ripetuti, cambiamenti di stato o evidenza ricevuta tramite più di un canale.
HTTP e SMPP: differenze pratiche di correlazione
In un'API HTTP, il fornitore risponde in genere con un identificatore della risorsa o del messaggio. È opportuno salvarlo insieme alla risposta iniziale, al timestamp e allo stato iniziale. I callback successivi devono essere associati innanzitutto tramite tale identificatore nativo, quando presente. Se il fornitore espone un'interrogazione della risorsa, questa serve per riconciliare callback mancanti o stati non finali.
In SMPP, il sequence_number correla una PDU di richiesta con la risposta associata all'interno di una sessione asincrona. Viene assegnato dall'originatore della PDU, incrementato in modo monotono e mantenuto nella risposta associata. È pertanto un riferimento di trasporto di breve durata e non un identificatore permanente del messaggio tra sistemi o fornitori.
La risposta submit_sm_resp può restituire un message_id assegnato dall'SMSC. Questo ID è opaco e appartiene al dominio dell'SMSC. In un DLR, il TLV receipted_message_id identifica il messaggio oggetto della ricevuta tramite lo stesso ID opaco restituito all'accettazione della presentazione originale. Conserva sia il valore originale sia il DLR completo per dimostrare come è stata effettuata l'associazione.
Per richiedere DLR in SMPP, si usa registered_delivery in submit_sm o data_sm. Lo standard contempla la richiesta del risultato finale di successo o errore, oppure del solo errore finale. La richiesta di una ricevuta non garantisce che arrivi un evento, che abbia un formato uniforme o che dimostri una ricezione indipendente sul terminale.
- HTTP: collega la risposta di creazione, l'ID nativo e ogni callback al tentativo corrispondente.
- SMPP sequence_number: utilizzalo per richiesta-risposta nella sessione, mai come identificatore persistente di business.
- SMPP message_id: memorizzalo come ID esterno assegnato a una presentazione accettata.
- SMPP receipted_message_id: utilizzalo come chiave principale di associazione del DLR quando è presente e corrisponde.
- SMPP user_message_reference: può essere utile se viene propagato, ma è un TLV facoltativo; non progettare una garanzia sulla sua presenza.
- DLR all'interno di short_message: non presumere un formato universale; la specifica SMPP indica che può essere specifico del fornitore.
Campi operativi da registrare
Gli identificatori spiegano quali oggetti sono correlati; i metadati spiegano cosa è accaduto e in quali condizioni. Registra timestamp separati per ricezione della richiesta, creazione del messaggio, creazione del tentativo, invio al fornitore, risposta del fornitore, ricezione del callback e aggiornamento derivato. Evita di utilizzare un unico campo data per tutte queste fasi.
Conserva la destinazione in una rappresentazione normalizzata e separata dai riferimenti operativi. Per gli SMS, E.164 è un utile riferimento per la normalizzazione internazionale dei numeri. Tuttavia, un numero normalizzato non deve essere usato come chiave esclusiva di correlazione: più messaggi possono essere indirizzati alla stessa destinazione e i dati di destinazione sono potenzialmente personali.
Registra mittente, codifica, lunghezza e numero di segmenti, configurazione DLR richiesta, interfaccia utilizzata, risultato della convalida e una versione della politica di instradamento applicata. La versione della politica consente di spiegare una decisione storica senza dedurla dalla configurazione attuale.
- Timestamp con fuso orario e fonte dell'orologio chiaramente definiti.
- Destinazione normalizzata e protetta come dato potenzialmente personale.
- Mittente utilizzato nella presentazione, senza presumere che identifichi il reale mittente.
- Codifica, dimensione e segmentazione effettiva.
- Canale e interfaccia: HTTP, SMPP o altro adattatore interno.
- Instradamento o fornitore selezionato e versione della politica di instradamento.
- Richiesta DLR, risposta di accettazione, codice di errore e payload originale dell'evento.
- Metodo di associazione e livello di certezza.
Callback duplicati, fuori ordine o senza riferimento riconoscibile
I callback sono eventi asincroni. Possono arrivare duplicati, fuori ordine, con campi aggiuntivi o senza il riferimento previsto. Il progetto corretto non consiste nel fidarsi dell'ordine di arrivo, ma nel conservare ogni evento e calcolare uno stato derivato mediante regole esplicite.
Per deduplicare, calcola un'impronta del payload originale e combina, quando possibile, fornitore, identificatore esterno, tipo di evento, stato riportato e timestamp di ricezione. La deduplicazione deve contrassegnare gli eventi equivalenti senza eliminare l'evidenza ricevuta. Se due eventi hanno lo stesso riferimento ma dati differenti, conservali come record distinti e annota la discrepanza.
Quando un riferimento non viene riconosciuto, memorizza l'evento in un'area di quarantena o tra gli eventi non associati. Non creare una relazione basandoti soltanto su corrispondenze di destinazione, orario o contenuto: questi attributi possono produrre falsi positivi. Applica associazioni probabilistiche solo se la politica operativa lo consente, etichettandole come tali e mantenendo l'evento originale inalterato.
I parametri di callback possono variare a seconda del canale e del tipo di evento, e possono anche essere estesi. I ricevitori devono tollerare nuovi campi e conservare il payload senza richiedere che tutti i fornitori utilizzino lo stesso schema.
- Persisti prima il payload originale e le relative intestazioni rilevanti.
- Convalida autenticità e provenienza secondo il meccanismo documentato da ciascun fornitore.
- Deduplica senza eliminare l'evidenza originale.
- Non presumere l'ordine cronologico dall'ordine di ricezione.
- Mantieni gli eventi non associati per indagini e riconciliazione.
- Non elevare un'associazione probabile a certezza senza un riferimento verificabile.
Domande frequenti
Il message_id SMPP identifica un messaggio in modo globale?
No. Il message_id restituito in submit_sm_resp è un identificatore opaco assegnato dall'SMSC. È utile per correlare la presentazione accettata a un DLR quando questo include receipted_message_id, ma non deve essere trattato come un riferimento globale tra fornitori o piattaforme.
A cosa serve sequence_number in SMPP?
Serve a correlare una PDU di richiesta con la risposta associata all'interno di una sessione SMPP asincrona. Viene assegnato dall'originatore della PDU e non deve essere utilizzato come identificatore persistente del messaggio.
Un DLR conferma che il destinatario ha letto l'SMS?
No. Un DLR riporta uno stato di consegna comunicato dalla catena di messaggistica. Anche l'accettazione da parte di un fornitore non equivale alla consegna al terminale. Deve essere documentato quale evento è stato ricevuto, da chi proviene e qual è il suo ambito.
Devo dipendere da user_message_reference per correlare i DLR SMPP?
Non come unica base del progetto. SMPP prevede user_message_reference come parametro facoltativo e la sua propagazione non deve essere data per garantita. Mantieni sempre la mappatura tra l'attempt ID interno e il message_id restituito dall'SMSC.
Cosa devo fare se arriva un callback senza un identificatore noto?
Conserva l'evento originale come non associato, registra la sua provenienza e applica la riconciliazione con il fornitore quando possibile. Non creare un'associazione definitiva basandoti soltanto su numero, orario o contenuto, perché potresti collegare messaggi distinti.
Per quanto tempo devo conservare i registri di tracciabilità?
Definisci il periodo in base alla finalità operativa, agli obblighi applicabili e alle politiche di sicurezza. Applica minimizzazione, limitazione della conservazione, controlli di accesso e integrità. Separa gli identificatori operativi dai dati personali, come destinazione, mittente o contenuto.
Fonti consultate
- SMPP Protocol Specification v3.4, Issue 1.2SMPP Developers Forum
- Messages resourceTwilio
- Best Practices for Messaging Delivery Status LoggingTwilio
- Outbound Message Status in Status CallbacksTwilio
- E.164: The international public telecommunication numbering planInternational Telecommunication Union
- A guide to the data protection principlesInformation Commissioner's Office