# OTP SMS delivery and fraud

A one-time password proves control of a number at the moment it is entered. It does not prove identity, and a delivery receipt does not prove that a person read it. Delivery, interception, number recycling and the form itself decide whether the check holds.

- An OTP proves control of a number at that moment, not identity.

- A delivery receipt reports a network state, not that a person read the code.

- Number recycling, SIM swap, forwarding and phishing are the main ways a code leaks.

- Rate limits, sender registration and number checks reduce abuse; none proves identity.

## What an OTP proves

An OTP answers one question: can the person in front of you receive a message on this number right now? That is useful for account recovery and login, because it ties the session to something the user controls. It is not an identity document. The number can be recycled, moved to a new SIM, forwarded, or read by someone else in the household.
The distinction matters at the design stage. If the action is low value, an OTP is proportionate. If the action moves money, changes a password or adds a payee, pair the code with a second check: a delay, a confirmation in an existing session, a call-back to a known channel or a manual review. The code is one factor, not the whole decision.

### The path, and the places a code can leak

The same chain that delivers the code also creates the places where it can be observed, delayed or sent to the wrong handset.

Alt: A seven-step SMS path from application to handset and delivery receipt, marked as a path with several points where a code can leak.

The application submits the code to a gateway, the message center looks up the subscriber, and the serving switch delivers to the handset. A receipt returns on the same chain. A code can leak at the application, at the handset, at the number itself or through the person who receives it. The network path explains the delivery; it does not explain the human who shares the code.

| Item | Value | Note |
| --- | --- | --- |
| First state · 1 | Application |  |
| First state · 2 | SMPP gateway |  |
| First state · 3 | SMSC |  |
| First state · 4 | HLR / HSS |  |
| First state · 5 | MSC / MME |  |
| First state · 6 | Handset |  |
| First state · 7 | Delivery receipt |  |

Source: 3GPP TS 23.040: SMS architecture (https://www.3gpp.org/ftp/Specs/archive/23_series/23.040/)

## Where an OTP leaks

A SIM swap moves the number to a new card. The attacker persuades a store or a support line that they are the owner, and the next code goes to the new SIM. Number recycling has the same effect without an attacker: a carrier reassigns a dormant number, and the new holder receives a code meant for the old account. Both are reasons to check whether a number was recently ported or reassigned.
Forwarding and voicemail-to-text send the message to another inbox. Phishing copies the form and collects the code directly, so the network never sees an attack. Interception on the network path is rarer and outside the application's control; the practical response is a second factor, not a longer code. Read the [OTP glossary entry](/en/resources/glossary/otp/) for the definitions.

## Controls that help

Limit how often a number, an IP address and a device can request a code. Use a short validity, one use per code, and bind the code to the session that requested it. Register the sender and keep the content plain: a code that looks like marketing may be filtered, and a filtered code produces a support ticket, not a login.
Check the number before you trust it. A number that cannot receive SMS, was ported recently or has a history of resets deserves a second step. For high-value actions, require an existing session or a second channel. Log the request, the submit, the receipt and the code entry as separate events, so you can tell a delivery problem from a user problem.
Design the code itself with the same care. Generate it from a cryptographic source, store a hash, expire it in minutes, allow one successful use and cap the attempts per code and per session. Do not reveal whether the number exists. Create the account record before the send, so a retry cannot open an account that never completes.

### Five metrics, with definitions

| Metric | Definition | What it tells you |
| --- | --- | --- |
| Delivery rate | Delivered receipts divided by submitted messages | Whether the network accepted the message; not whether a person read it |
| Completion rate | Codes entered divided by delivered messages | Whether the message and the form worked for the user |
| Time to deliver | Median and 95th percentile from submit to receipt | Whether the route is slow, and how long a user waits before resending |
| Resend rate | Resends divided by delivered messages | Whether users wait too long, mistype, or never see the first message |
| Block rate | Requests rejected by risk rules divided by attempts | Whether the rules are too tight, too loose, or the traffic is abusive |

Track them by market, sender and route. A single global average hides the route that is failing.

## Measure the flow, not the send

A send that returns a message ID is not a delivered code. A delivered code is not a completed login. Build the funnel from the events you control: submit, receipt, code entry, success. Then compare it with the provider's view. A gap between your delivery rate and the provider's may be a receipt that never reached your handler, not a message that never reached the handset.
Review the flow when a metric moves. A drop in completion with a stable delivery rate points to the form, the code expiry or the sender. A drop in delivery with a stable submit rate points to the route, the number or the content filter. A rise in resends points to time to deliver. Fix the step the data names, not the step that is easiest to change.
Set a review date for the whole flow. Numbers change hands, routes change and templates age. A flow that worked at launch can fail quietly six months later, with the same code and the same provider.

### Check what you learned

**A user forwards the code to a friend. Does the code still prove identity?**

No. It proves that the number could receive the code at that moment. Anyone who has the code can use it.

**A receipt says delivered, but the user never sees the code. What do you check?**

The handset state, the messaging app and spam filter, the sender, and the route. A delivered receipt is the network's state, not the handset display.

**Why is completion rate more useful than delivery rate?**

Delivery stops at the network. Completion includes the user, the code expiry and the form, which is where most failures show up.

## FAQ

**Is an OTP the same as two-factor authentication?**

An OTP can be the second factor. On its own it is one factor: possession of the number at that moment.

**Are longer codes safer?**

Length helps against guessing, but it does not stop a SIM swap, forwarding or phishing. Add a second check for high-value actions.

**Can a delivery receipt prove the user read the code?**

No. It reports a network state such as delivered, expired or undelivered. It says nothing about reading or typing.

**Should we resend automatically?**

Resend on a user action, not on a timer. Automatic resends multiply cost and can mask a route problem.

**What should we log?**

The request, the submit and its message ID, the receipt and its state, and the code entry result. Keep them as separate events with timestamps.

**Receipts say delivered but users get nothing. What should we check before switching provider?**

Your own side first, because a delivery receipt says the network accepted the message, not what the handset showed. Run the template through the [SMS content pre-check](/en/tools/content-precheck/), count its segments with the [SMS segment counter](/en/tools/sms-segments/), and read the submit and receipt codes with the [SMPP and DLR code decoder](/en/tools/smpp-decoder/). If those are clean, test the failing destination on your own handsets before you move traffic, one destination at a time.

## Sources

- [3GPP TS 23.040: Technical realization of the Short Message Service](https://www.3gpp.org/ftp/Specs/archive/23_series/23.040/) — Accessed: 2026-10-19
- [3GPP TS 23.003: Numbering, addressing and identification](https://www.3gpp.org/ftp/Specs/archive/23_series/23.003/) — Accessed: 2026-10-19
- [SMPP delivery receipts: message states](https://smpp.org/smpp-delivery-receipt.html) — Accessed: 2026-10-19

Updated: 2026-11-03