Maxi SMSC Simulator

Guide

SMPP Delivery Receipts: deliver_sm Format, Statuses and How to Test Them

How SMPP delivery receipts (DLRs) are built, what each stat value means and how to test every outcome with an SMSC simulator.

When you send a message over SMPP, the first answer you get is submit_sm_resp. It only tells you that the SMSC accepted the message. What happened next, whether the phone received it or not, arrives later as a delivery receipt (DLR). Handling receipts correctly is one of the most error-prone parts of an SMPP client, so it deserves its own tests.

How a delivery receipt reaches your client

  1. The client sends submit_sm with registered_delivery set to request a receipt.
  2. The SMSC answers with submit_sm_resp containing a message_id.
  3. When the final outcome is known, the SMSC sends deliver_sm to the client on a receiver (RX) or transceiver (TRX) session.
  4. The client replies with deliver_sm_resp.

The bits of registered_delivery that matter are the lowest two: 0x01 requests a receipt for the final outcome, success or failure; 0x02 requests a receipt only on failure; 0x00 requests none.

Recognizing a receipt: esm_class 0x04

A receipt is a normal deliver_sm, and the field that tells it apart from an incoming message is esm_class. In a receipt the message type bits are set to "SMSC delivery receipt", which gives esm_class = 0x04. Your client should branch on this value, not on the text of the message.

The receipt text format

SMPP v3.4 describes the receipt text in an informative appendix, so real SMSCs vary slightly. The common shape is:

id:8f2c1a70-5d3e-4c1b-9a47-2b6e0d1c9f35 sub:001 dlvrd:001 submit date:2609241030 done date:2609241031 stat:DELIVRD err:000 text:Hello world
FieldMeaning
idThe message id returned in submit_sm_resp. Use it to match the receipt to your message.
subNumber of short messages originally submitted.
dlvrdNumber of short messages delivered.
submit dateWhen the message was submitted, format YYMMDDhhmm.
done dateWhen it reached its final state, same format.
statThe final state of the message.
errA network or SMSC specific error code, when there is one.
textThe first characters of the original message.

SMSCs may also send the same information in TLVs: receipted_message_id (0x001E) and message_state (0x0427). Parse both, and prefer the TLVs when they are present.

Message states

statmessage_stateMeaning
DELIVRD2Delivered to the destination.
EXPIRED3Validity period expired before delivery.
DELETED4Deleted, for example by the SMSC or by a cancel request.
UNDELIV5Undeliverable.
ACCEPTD6Accepted, for example read on the recipient's behalf. Not a delivery.
UNKNOWN7The state is unknown.
REJECTD8Rejected.

Of these, DELIVRD is a success, EXPIRED, DELETED, UNDELIV and REJECTD are failures, and ACCEPTD and UNKNOWN are ambiguous: decide in your business logic how they should be treated. The state ENROUTE (1) is intermediate and can appear in query_sm_resp.

What to test

  • Every stat value. Your code should never crash on a value it does not know.
  • Matching. The receipt id must map to a stored message. Test ids that are UUIDs or longer than 10 characters, since not every SMSC uses short numeric ids.
  • Delay. Receipts can come after seconds or hours. Check timeouts and pending states.
  • Missing receipts. Decide when a message without a receipt is treated as failed.
  • Duplicates and out-of-order receipts for the same message.
  • Multipart messages. Each part may get its own receipt.
  • Acknowledgement. Send deliver_sm_resp for every receipt, otherwise some SMSCs resend it.

Testing receipts in a simulator

With a real network you cannot order a receipt with stat:EXPIRED on demand. A simulator can. In Maxi, you create a delivery report scheme for each client account: a name, a delay in seconds before the report is sent, and the statuses that are valid together with their percentages. For example, a scheme of 90% Delivered and 10% Not Delivered generates both outcomes across a batch of messages, and you can include Expired and Pending shares as well. The panel lets you watch the SMS queue and the report queue live, and statistics for all processed messages. The reports are returned to clients connected through SMPP on RX or TRX, and to API and REST API clients on the state URLs configured in the account.

Maxi returns a positive response with a message_id in UUID format, which is a good way to check that your client does not assume short numeric ids. The configuration guide shows the scheme setup, and you can contact us or register to try it. To learn which connection can receive receipts, read about SMPP bind types.

Keep reading

Ready to test your SMS traffic?

Get your SMPP simulator in minutes and use it free for 3 days — or tell us what you need and we will help you choose a plan.