Aufbau eines SMPP-Zustellberichts
Wenn Sie eine SMS mit registered_delivery = 1 senden, schickt das SMSC später eine deliver_sm-PDU über einen Receiver- oder Transceiver-Bind zurück. Bit 0x04 im esm_class kennzeichnet sie als Zustellbericht statt als eingehende Nachricht, und ihr short_message enthält den Bericht als Text. Anhang B der SMPP-v3.4-Spezifikation nennt dieses Format als Beispiel, und fast alle SMSCs halten sich daran: id:IIIIIIIIII sub:SSS dlvrd:DDD submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DDDDDDD err:E text:….
Da Anhang B nur ein Beispiel und keine feste Regel ist, weichen echte Berichte ab: Schlüssel in Kleinbuchstaben, zusätzliche Leerzeichen, submit_date mit Unterstrich, zwölfstellige Zeitangaben mit Sekunden oder fehlendes text. Dieser Decoder akzeptiert all diese Varianten und meldet fehlende Felder.
- id: die Nachrichten-ID, die das SMSC in submit_sm_resp zurückgegeben hat. Damit ordnen Sie den Bericht Ihrer Nachricht zu. Das Beispiel der Spezifikation zeigt 10 Zeichen, viele SMSCs verwenden aber längere IDs, teils hexadezimal.
- sub und dlvrd: die Anzahl eingereichter und zugestellter Nachrichten, dreistellig. Sie sind vor allem für Verteilerlisten relevant; bei einer einzelnen SMS steht meist 001 und 001 (oder 000).
- submit date und done date: wann die Nachricht eingereicht wurde und wann sie ihren Endstatus erreichte, nach der Uhr des SMSC.
- stat: der End- oder Zwischenstatus als Code aus 7 Buchstaben, etwa DELIVRD.
- err: ein dreistelliger Fehlercode, netz- oder SMSC-spezifisch; 000 bedeutet kein Fehler.
- text: die ersten 20 Zeichen der ursprünglichen Nachricht, oft gekürzt oder leer.
- Optionale TLVs liefern diese Daten teils sauberer: receipted_message_id (0x001E), message_state (0x0427) und network_error_code (0x0423).
DLR-stat-Codes und ihre Bedeutung
SMPP v3.4 definiert acht Nachrichtenstatus. ENROUTE und ACCEPTD sind Zwischenstände, alle anderen endgültig. Unsere API normalisiert alle Kanäle auf sechs Webhook-Status (SUBMITTED, SENT, DELIVERED, READ, FAILED, REJECTED), und der Decoder zeigt für jeden stat-Wert die nächstliegende Entsprechung. Diese Zuordnung ist unverbindlich: Die genaue Regel für Ihr Konto wird beim Onboarding bestätigt.
- DELIVRD (message_state 2): auf dem Endgerät zugestellt. Nächstliegender Webhook-Status: DELIVERED.
- ACCEPTD (6): formal „vom Kundenservice im Namen des Teilnehmers manuell gelesen“, doch die meisten SMSCs senden es als Zwischenbericht „vom Netz angenommen“. Nächstliegend: SENT.
- ENROUTE (1): noch unterwegs, etwa für einen erneuten Versuch eingereiht. Nächstliegend: SENT.
- UNDELIV (5): nicht zustellbar, etwa eine ungültige oder inaktive Nummer. Nächstliegend: FAILED.
- EXPIRED (3): die Gültigkeitsdauer lief ab, bevor das Endgerät erreichbar war, oft weil es ausgeschaltet oder ohne Empfang war. Nächstliegend: FAILED.
- DELETED (4): vor der Zustellung gelöscht, etwa per cancel_sm. Nächstliegend: FAILED.
- REJECTD (8): vom Netz oder einer SMS-Firewall abgelehnt, etwa wegen einer nicht registrierten Absenderkennung oder gesperrter Inhalte. Nächstliegend: REJECTED.
- UNKNOWN (7): das SMSC hat keinen Endstatus. Werten Sie es als unbestätigt, nicht als nachgewiesenen Fehlschlag.
err-Codes: warum es keine allgemeingültige Liste gibt
Das Feld err ist drei Zeichen breit, und die SMPP-Spezifikation legt seine Werte nicht fest. 000 bedeutet immer kein Fehler, alle anderen Werte stammen vom SMSC-Hersteller, vom Netzbetreiber oder von einem zwischengeschalteten Aggregator. Manche SMSCs reichen GSM-MAP-Fehlerursachen durch (zum Beispiel ist MAP-Fehler 1 ein unbekannter Teilnehmer und 27 ein abwesender Teilnehmer), andere verwenden eigene Tabellen.
Enthält der Bericht das TLV network_error_code (0x0423), ist es verlässlicher: Das erste Oktett gibt den Netztyp an (3 steht für GSM), die nächsten beiden den Fehlercode. Ein DELIVRD-Bericht mit err ungleich null ist widersprüchlich und sollte mit Ihrem Anbieter geklärt werden; der Decoder markiert ihn.
command_status-Fehler und Zustellberichte
SMPP meldet Probleme zu zwei Zeitpunkten. Der command_status in submit_sm_resp kommt nach Millisekunden und sagt, ob das SMSC Ihre Anfrage angenommen hat; 0x00000000 (ESME_ROK) heißt angenommen, nicht zugestellt. Der Zustellbericht folgt Sekunden bis Tage später und enthält das endgültige Ergebnis.
Die command_status-Werte sind in Abschnitt 5.1.3 von SMPP v3.4 definiert. Im Betrieb am häufigsten sind 0x00000058 ESME_RTHROTTLED (vereinbarte Nachrichten pro Sekunde überschritten: drosseln und mit exponentiellem Backoff erneut senden), 0x00000014 ESME_RMSGQFUL (Warteschlange voll: abwarten), 0x0000000A und 0x0000000B (ungültige Absender- oder Zieladresse) sowie 0x0000000D oder 0x0000000E (Bind fehlgeschlagen oder falsches Passwort). Die Werte 0x00000400 bis 0x000004FF sind für herstellerspezifische SMSC-Fehler reserviert; fragen Sie dazu Ihren Anbieter.
Zeitangaben, Zeitzonen und Zustelldauer
Zeitangaben im Bericht folgen JJMMTThhmm, viele SMSCs hängen Sekunden an (JJMMTThhmmss). Eine Zeitzone fehlt: Maßgeblich ist die Uhr des SMSC, meist UTC. Der Decoder zeigt die Zeiten so, wie sie im Bericht stehen, und berechnet die Laufzeit als done date minus submit date. Das ist unabhängig von der Zeitzone, solange beide Werte von derselben Uhr stammen.
Die Laufzeit ist ein guter Qualitätsindikator. Ein OTP an ein erreichbares Endgerät ist normalerweise in Sekunden zugestellt. Lange Laufzeiten mit anschließendem EXPIRED deuten auf ausgeschaltete oder roamende Geräte hin, und ein done date vor dem submit date bedeutet, dass die Uhren abweichen. Minutengenaue Zeitangaben können keine Laufzeiten unter einer Minute messen; SMSCs mit Sekunden sind daher vorzuziehen.
Zustellberichte im Betrieb zuverlässig verarbeiten
Beantworten Sie jede deliver_sm mit deliver_sm_resp, auch wenn Ihre Verarbeitung scheitert; sonst sendet das SMSC sie erneut und drosselt womöglich den Bind. Speichern Sie den Rohbericht und verarbeiten Sie ihn asynchron und idempotent anhand der Nachrichten-ID, denn Berichte können doppelt oder in falscher Reihenfolge eintreffen: Ein verspätetes ENROUTE darf nie ein DELIVRD überschreiben.
Wenn Sie lieber keine Berichte parsen möchten, liefert unsere REST-SMS-API dieselben Informationen als normalisierte Webhook-Status, und verpasste Berichte lassen sich mit POST /sms/resendDlr erneut zustellen. SMPP-Binds über TLS stehen für hohe Volumen und Reseller bereit.
