Files
smpp-js/interop-tests/research/smsc-simulators.md
T

167 lines
31 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SMPP SMSC-side test targets for `@larvit/smpp`
Research date 2026-09-05. All claims cite the URL they came from; anything not confirmed by a primary source is marked **unverified**.
## Quick comparison
| Candidate | Language | License | Maintained? | Docker tag (pinned) | SMPP port | SMPP versions |
|---|---|---|---|---|---|---|
| SMPPSim (Selenium Software) | Java | GPLv2 [sourceforge](https://sourceforge.net/projects/smppsim/) | Stalled — homepage `seleniumsoftware.com` returns Cloudflare 522 as of this research; last SourceForge file 2015-05-22; community fork last touched 2024-01-09 | none published — build your own | 2775 | 3.3/3.4 implied, not confirmed |
| Jasmin SMS Gateway | Python/Twisted | ISC-style (see repo) [github](https://github.com/jookies/jasmin) | Source active (last push 2026-04-26), last **tagged release** 0.11.0 (2023-11-10) | `jookies/jasmin:0.11.0` [dockerhub](https://hub.docker.com/r/jookies/jasmin/tags) | 2775 | 3.4 |
| Kannel + opensmppbox | C | BSD-style (Kannel) | Kannel core: last stable 1.4.5, 2018-06-19 [kannel.org](https://www.kannel.org/); opensmppbox (pruiz fork): last commit 2014-04-22 [github](https://github.com/pruiz/kannel-opensmppbox) | none — build from source | 2345 (configurable) | 3.3/3.4/5.0 |
| Kannel `fakesmsc` | C | BSD-style | same as Kannel | n/a | configurable (e.g. 10000) | **none — not SMPP at all** |
| Melrose Labs SMSC Simulator (hosted) | closed-source | proprietary | Actively run (commercial service) | n/a — hosted | 2775 (8775 TLS) | 3.3/3.4/5 |
| Melrose Labs SMSC Simulator (OSS, old code) | C++ | MIT [github](https://github.com/melroselabs/smpp-smsc-simulator) | Dormant, last push 2023-07-15, explicitly "old version" | none published | 2775 | subset of 3.4 |
| ukarim/smscsim | Go | MIT [github](https://github.com/ukarim/smscsim) | Source active (last push 2025-12-12); Docker tags stop at 0.2.0 | `ukarim/smscsim:0.2.0` (no newer semver tag) [dockerhub](https://hub.docker.com/r/ukarim/smscsim/tags) | 2775 (env `SMSC_PORT`) | subset of 3.4 |
| mdouchement/smsc3 | Go | MIT [github](https://github.com/mdouchement/smsc3) | Last push 2024-05-09, small project | none published — Dockerfile in repo | 20001 | 3.4 |
| K2InformaticsGmbH/smsc_simulator | Erlang | Apache-2.0 [github](https://github.com/K2InformaticsGmbH/smsc_simulator) | Abandoned, last commit 2018-08-31 | none | configurable | SMPP + UCP |
| MavoCz/smscsim (cloudhopper-based) | Java | unverified | unverified last-commit date | none | configurable (CLI `-p`) | 3.3/3.4/5.0 (via cloudhopper) |
| fizzed/cloudhopper-smpp | Java | Apache-2.0 [github](https://github.com/fizzed/cloudhopper-smpp) | Last push 2020-10-12 | none — library + demo, not a packaged sim | demo-configurable | 3.3/3.4/most of 5.0 |
| jsmpp `SMPPServerSimulator` example | Java | Apache-2.0 [github](https://github.com/opentelecoms-org/jsmpp) | jsmpp itself very active (last push 2026-06-17); the example is a demo class, not a packaged tool | none — sample code | example-configurable | 3.4/3.3 |
| node-smpp | JS | MIT [github](https://github.com/farhadi/node-smpp) | Last push 2023-12-28 | none — library, build your own server | n/a | 5.0 (back-compat with 3.4) |
| MikeSafonov/smpp-server-mock | Java (JUnit ext.) | MIT [github](https://github.com/MikeSafonov/smpp-server-mock) | Last push 2023-03-10 | none — embedded-in-test only, not standalone | n/a | unverified |
| Restcomm/TeleStax SMSC Gateway simulator | Java/JSLEE | unverified | project largely dormant post-TeleStax | none published | 2776 (sample) | unverified, full carrier-grade stack |
| OsmoMSC SMPP interface | C | AGPL (Osmocom) | Actively maintained as part of Osmocom NITB/MSC, but it's a *client* interface for external ESMEs bound to a live MSC core, not a standalone SMSC simulator you spin up in Docker | none | configurable | unverified |
| smscsim.smpp.org (public) | closed | n/a | unverified, listed on smpp.org | hosted | 2775 | unverified, 2 SMS/s cap |
Ozeki NG SMS Gateway and NowSMS both ship free/trial tiers with an SMPP server mode, but are Windows-first, closed-source products; skipped per task scope beyond this line.
---
## 1. SMPPSim (Selenium Software)
1. **Source**: originally `seleniumsoftware.com/downloads.html`; that domain currently returns an HTTP 522 (Cloudflare "origin unreachable") when fetched directly — confirmed via both WebFetch and a raw `curl` from this research session, so the vendor's own site is effectively down right now. SourceForge mirror: [sourceforge.net/projects/smppsim](https://sourceforge.net/projects/smppsim/) — license **GPLv2**, "Currently hosted by Selenium Software", last file dated **2015-05-22**. A community fork with docs/props preserved: [komuw/smpp_server_docker](https://github.com/komuw/smpp_server_docker) (last push 2019-06-04), user-guide mirrored at [user-guide.htm](https://github.com/komuw/smpp_server_docker/blob/master/SMPPSim/docs/user-guide.htm). Not actively maintained by any single fork; version history in the mirrored guide references up to v2.6.6.
2. **Docker**: no maintainer-published image with a pinned version tag exists. Two build-yourself Dockerfiles found:
- [kwahome/smpp-sim-docker](https://github.com/kwahome/smpp-sim-docker) (repo last pushed 2024-01-09) — its own `Dockerfile` builds `openjdk:7-jre-alpine` + bundled `SMPPSim/`, but its `docker-compose.yml` instead pulls a pre-built `blackorder/smppsim:latest`**only a `latest` tag exists** on that Docker Hub repo (pushed ~2 years ago, single tag) [dockerhub](https://hub.docker.com/r/blackorder/smppsim/tags). Since no full-patch-version tag is published anywhere, to comply with "never floating tags" you must build the image yourself from the Dockerfile and apply your own version tag.
- `bitsensedev/smpp-sim` on Docker Hub: single `latest` tag, pushed **9+ years ago** — effectively abandoned, do not use.
- Ports (from the Dockerfile env defaults): SMPP **2775**, HTTP admin **8884** (some older docs say port 88 — verify against the image you build).
- Default credentials (env `SYSTEM_IDS` / `PASSWORDS`): `smppclient1,smppclient2,smppclient3` / `password,password,password` [Dockerfile](https://raw.githubusercontent.com/kwahome/smpp-sim-docker/master/Dockerfile).
3. **SMPP versions**: not explicitly stated in any surviving doc; behavior suggests 3.3/3.4-era PDU set. Whether it validates `interface_version` at bind — **unverified**, no mention in the mirrored user guide.
4. **Delivery receipts**: yes, when `registered_delivery_flag` is set on `submit_sm`. Controlled by percentage knobs: `PERCENTAGE_DELIVERED`, `PERCENTAGE_UNDELIVERABLE`, `PERCENTAGE_ACCEPTED`, `PERCENTAGE_REJECTED`, plus `PERCENTAGE_THAT_TRANSITION` (chance of an intermediate state before final), `DELAY_DELIVERY_RECEIPTS_BY` (delayed DLR, ms), `MAX_TIME_ENROUTE`. TLV vs text-body format not documented; message-id format documented only as "randomised … with configurable prefix" — hex/decimal notation unverified.
5. **Long messages**: UDH/`sar_*`/`message_payload` handling not documented in any surviving guide fragment — unverified, treat as untested.
6. **Encodings**: only one hard fact recovered — binary MO messages (hex-prefixed with `0x` in the inject form) get `data_coding` auto-set to 4. GSM7 packed-vs-unpacked, Latin-1, UCS-2 behavior — unverified.
7. **MO injection**: three documented methods — (a) web form `/inject_mo.htm`, (b) "loopback" mode that turns a `submit_sm` back into a `deliver_sm`, (c) MO service reading a `deliver_messages.csv` file. Also supports SMSC-initiated **outbind** (`OUTBIND_ENABLED=true` + `OUTBIND_ESME_*` env vars) to test your library's outbind handling.
8. **Fault injection**: queue-full simulation via `INBOUND_QUEUE_MAX_SIZE`/`OUTBOUND_QUEUE_MAX_SIZE` and `DELAYED_INBOUND_QUEUE_MAX_ATTEMPTS`; on `ESME_RMSGQFUL` the mirrored guide says SMPPSim "will attempt to deliver the MO message again, after a delay" (v2.6.0 note). `MO_DELIVERY_MESSAGES_PER_MINUTE`/`DELIVERY_MESSAGES_PER_MINUTE` throttles delivery rate. Explicit `ESME_RTHROTTLED` triggering — unverified.
9. **TLS**: not mentioned anywhere in the surviving docs — treat as unsupported.
10. **Minimal run** (build-yourself, since no pinned image exists):
```
git clone https://github.com/kwahome/smpp-sim-docker
cd smpp-sim-docker
docker build -t local/smppsim:<your-tag> .
docker run -p 2775:2775 -p 8884:8884 local/smppsim:<your-tag>
```
Bind with `system_id=smppclient1`, `password=password`, port 2775.
11. **Quirks**: primary vendor site down (522) at research time; ecosystem is a scatter of unofficial Docker forks with inconsistent port numbers (88 vs 8884) between older and newer docs — verify against whichever build you actually use.
## 2. Jasmin SMS Gateway
1. [jookies/jasmin](https://github.com/jookies/jasmin), license per repo (ISC-style, see `LICENSE`), Python/Twisted. Repo actively committed (last push 2026-04-26) but last **tagged release is 0.11.0, 2023-11-10** [releases](https://github.com/jookies/jasmin/releases). Docs: [docs.jasminsms.com](https://docs.jasminsms.com/).
2. **Docker**: `jookies/jasmin:0.11.0` (full patch tag exists and matches the GitHub release) [dockerhub tags](https://hub.docker.com/r/jookies/jasmin/tags). Needs RabbitMQ + Redis as separate containers — not standalone.
```
docker run -d -p 1401:1401 -p 2775:2775 -p 8990:8990 jookies/jasmin:0.11.0
```
Ports: **2775** SMPP server, 1401 HTTP API/panel, 8990 `jcli` telnet console [docker/README.md](https://github.com/jookies/jasmin/blob/master/docker/README.md). No default smpp-server credentials are pre-provisioned — you create a `system_id`/`password` via `jcli` (`smppccm`/`user -a` commands) after startup.
3. **SMPP version**: 3.4 [SMPP Server API docs](https://docs.jasminsms.com/en/latest/apis/smpp-server/index.html). `interface_version` enforcement at bind — not documented; **unverified**.
4. **Delivery receipts**: yes. Jasmin's DLR pipeline (`DLRLookup`/`DLRThrower`) tracks the message in Redis and, when the original submission came in over `smpps`, pushes the receipt back as a `deliver_sm`/`data_sm` on the same bind [messaging flows](https://docs.jasminsms.com/en/latest/messaging/index.html). Whether it's TLV (`receipted_message_id`/`message_state`) or text-body — not confirmed from docs; a `dlr_msgid` connector setting (0/1/2) exists specifically to reconcile hex-vs-decimal message-id mismatches between `submit_sm_resp` and `deliver_sm` — but that knob lives on **outbound SMPP client connectors** (Jasmin acting as ESME to an upstream real SMSC), not on the `smpps` server your library binds to [Google Groups thread](https://groups.google.com/g/jasmin-sms-gateway/c/KRqUA6e569w). When Jasmin itself is the SMSC (your library binds to its `smpps`), the message id it generates is its own internal **UUID**-based id [Google Groups](https://groups.google.com/g/jasmin-sms-gateway/c/KRqUA6e569w) and should therefore be self-consistent between `submit_sm_resp` and the DLR — good for testing your library's "normalise across submit_sm_resp vs receipt" logic in the *opposite* direction (assert it does NOT need to normalise when ids already match).
5. **Long messages**: two segmentation strategies documented for MT — **SAR** (`sar_msg_ref_num`/`sar_total_segments`/`sar_segment_seqnum`, "preferred by most SMSCs") and **UDH** (prepended header + `UDHI_INDICATOR_SET` in `esm_class`, "for older system compatibility") [DeepWiki summary of Jasmin SMPP protocol support](https://deepwiki.com/jookies/jasmin/3.3-smpp-protocol-support) (secondary source — treat as indicative, not primary).
6. **Encodings**: capacity figures imply **packed** GSM7 (160 chars / 153 segmented = the standard packed math), 8-bit binary 140/134 bytes, UCS-2 70/67 chars [same DeepWiki page]. Not a primary source — verify empirically before relying on it.
7. **MO injection**: bind your library as receiver/transceiver on `smpps`; anything Jasmin routes to that connector arrives as `deliver_sm`. Separately, Jasmin's HTTP API/interceptor stack can push MO content to an HTTP webhook (`deliverSmHttpThrower`) instead — not needed for SMSC-side ESME testing, only relevant if you want Jasmin to also fan MO out to HTTP [interception docs](https://docs.jasminsms.com/en/latest/interception/index.html).
8. **Fault injection**: `submit_throughput` exists as a per-connector throttling parameter but its exact unit/effect and how to disable it are not resolved even in the project's own issue tracker — [issue #913](https://github.com/jookies/jasmin/issues/913) is open/stale with no documented answer. No documented way to force `ESME_RTHROTTLED`/`ESME_RMSGQFUL`, refuse binds, or drop the TCP connection on demand — unverified/likely absent.
9. **TLS**: the `[smpp-server]` config section in the shipped `jasmin.cfg` has **no TLS/SSL directives at all** [jasmin.cfg](https://github.com/jookies/jasmin/blob/master/misc/config/jasmin.cfg) — the SMPP *server* role does not support TLS. (An outbound SMPP *client* connector does have `useSSL`/`SSLCertificateFile` options, irrelevant here.)
10. **Minimal config** — `[smpp-server]` section, defaults: port 2775, `sessionInitTimerSecs=30`, `enquireLinkTimerSecs=30`, `inactivityTimerSecs=300`, `responseTimerSecs=60`, `pduReadTimerSecs=10`, `dlr_expiry=86400` [jasmin.cfg](https://github.com/jookies/jasmin/blob/master/misc/config/jasmin.cfg). After boot, create a user via `jcli`:
```
jcli -h 127.0.0.1 -p 8990 # telnet console
> user -a
> uid myesme
> gid mygroup
> username myesme
> password mypassword
> ok
```
11. **Quirks**: no packaged Docker Compose bundling RabbitMQ+Redis is officially shipped — you must wire those yourself. No release/Docker tag newer than late 2023 despite ongoing source commits — verify current `master` behavior differs from 0.11.0 before trusting docs literally.
## 3. Kannel + opensmppbox (and why `fakesmsc` doesn't help)
1. **Kannel** core: [kannel.org](https://www.kannel.org/), C, BSD-style license. Confirmed via the vendor's own homepage: last **stable release 1.4.5, 2018-06-19**; nothing newer since [kannel.org news list, fetched directly]. Effectively unmaintained upstream.
**opensmppbox** (the actual SMPP-server add-on): canonical doc is the [OpenSMPPBox User's Guide](https://www.kannel.org/download/1.4.4/gateway-1.4.4/addons/opensmppbox/doc/userguide.xml) ("developed by Chimit Ltd, maintained by the Kannel Group"). The most complete GitHub mirror, [pruiz/kannel-opensmppbox](https://github.com/pruiz/kannel-opensmppbox), has its last commit **2014-04-22** — 11+ years stale.
2. **Docker**: no official image. Build from source against a Kannel `bearerbox` build; no maintained Dockerfile found. Default port **2345** (`opensmppbox-port`); credentials live in a flat file set via `smpp-logins` (username/password/system-type/IP-restriction per line).
3. **SMPP versions**: "compliance to SMPP v3.3, SMPP v3.4 & SMPPv5.0" per the user guide. `interface_version` bind-time validation — not documented, unverified.
4. **Delivery receipts**: opensmppbox stores/forwards DLRs from Kannel's `bearerbox` (multiple backends: internal, MySQL, PostgreSQL, Oracle, SQLite3, MS-SQL) and "rewrites [them] to appear that they originated from OpenSMPPBox" back to the bound ESME. TLV vs text, exact `esm_class`, intermediate/failure/delayed-DLR simulation — not documented in the guide; unverified.
5. **Long messages**: supports `message_payload` TLV as an alternative to UDH concatenation when explicitly enabled; UDH re-splitting behavior on the MO side — unverified.
6. **Encodings**: guide only states it can "define the data coding type of the short message" — packed vs unpacked GSM7 behavior unverified.
7. **MO injection**: MO routing targets a specific bound ESME "based on shortcode, SMSC id, or randomly if unconfigured" — i.e. inbound traffic through Kannel's normal SMSC drivers gets forwarded to whichever ESME opensmppbox picks; no direct CLI/HTTP "inject one MO now" tool documented for opensmppbox itself (Kannel's own `fakesmsc`, see below, cannot fill this gap because it doesn't speak SMPP).
8. **Fault injection / TLS**: not documented for opensmppbox in the guide; unverified — treat as unsupported until proven otherwise.
9. **`fakesmsc` clarification (important)**: Kannel ships a **separate** testing tool `test/fakesmsc` that connects to `bearerbox`'s core `smsc = fake` group. Per Kannel's own 1.4.5 user guide (fetched directly from kannel.org): *"Fake SMSC is a simple protocol to test out Kannel. It is not a real SMS center, and cannot be used to send or receive SMS messages from real phones. So, it is ONLY used for testing purposes."* Its wire format is a trivial line-based text protocol (`sender receiver type message...`), confirmed from the `fakesmsc.c` usage text — **it does not speak SMPP at all**. It exists only to test Kannel's own HTTP `sendsms` interface end-to-end without a real carrier link. It is **not usable** to interoperability-test an external SMPP client library, despite superficially sounding like an SMSC simulator. Use opensmppbox for that instead.
10. **Minimal opensmppbox config** (from the [user guide](https://www.kannel.org/download/1.4.4/gateway-1.4.4/addons/opensmppbox/doc/userguide.xml)):
```
group = smpp-logins
smpp-logins = /etc/opensmppbox/smpp-logins.txt
opensmppbox-port = 2345
```
and in `smpp-logins.txt`: `myuser mypass VMA 0.0.0.0/0`
11. **Quirks**: Kannel's core `smpp` SMSC driver (Kannel acting as *client* connecting outbound to a real SMSC) is well documented and supports `interface-version` (hex string, default `"34"`), `msg-id-type` (bit-flags for hex/decimal `submit_sm_resp` vs `deliver_sm`), `max-pending-submits` (window, default 10), `enquire-link-interval` (default 30s), `use-ssl`/`ssl-client-cert` — but that's the *wrong direction* for this task (it's Kannel-as-ESME, not Kannel-as-SMSC). Given both Kannel and opensmppbox have had no significant commits in a decade, this path is the highest-effort, lowest-payoff of the "must include" list.
## 4. Melrose Labs SMSC Simulator
Two distinct things share the name:
- **Hosted public/commercial service** at `smscsim.melroselabs.com:2775` — closed-source, run by Melrose Labs.
- **Old open-source code** at [melroselabs/smpp-smsc-simulator](https://github.com/melroselabs/smpp-smsc-simulator), MIT license, C++11, single-file (`smscsimulator.cpp`) — repo explicitly says it "represents old version of existing SMSC Simulator service available online … newer version of code not published." Last push 2023-07-15.
1. Homepages: [melroselabs.com/services/smsc-simulator](https://melroselabs.com/services/smsc-simulator/), technical details at [smsc-simulator-technical-details](https://melroselabs.com/services/smsc-simulator/smsc-simulator-technical-details/), dedicated-instance doc at [ssg docs](https://ssgdocs.melroselabs.com/docs/smsc-simulator) / [scrollhelp](https://melroselabs.scrollhelp.site/dss/dedicated-smsc-simulator).
2. **Docker**: OSS repo has a `docker-compose.yml`; no image tag confirmed (repo has only source + compose, no published registry tag found). Default port 2775 in both the OSS code and the hosted service.
3. **SMPP versions**: "SMPP v3.3, v3.4 and v5" for the hosted service [technical details page]. `submit_sm_resp` message-id length differs by version: **8 characters for v3.3, 64 characters for v3.4 and v5** [same page] — hex/decimal notation not stated.
4. **Delivery receipts**: hosted shared service — text `short_message` receipt *plus* TLVs `receipted_message_id` and `message_state` (value 2 = DELIVERED) [technical details page]; shared/free tier is "delivered" status only, <1s after `submit_sm_resp`. **Dedicated** instances are configurable via a `dlr.conf`: DELIVERED(2)/EXPIRED(3)/DELETED(4)/UNDELIVERABLE(5)/ACCEPTED(6)/UNKNOWN(7)/REJECTED(8) with percentages, plus `--dlrlatency` (default 3s) for delayed DLRs, and a per-ESME `shouldReturnUndeliveredReceipts` override [dedicated simulator docs](https://melroselabs.scrollhelp.site/dss/dedicated-smsc-simulator).
5. **Long messages**: `message_payload` TLV (0x0424) supported on `submit_sm`/`deliver_sm`/`data_sm` [technical details page]. UDH / `sar_*` handling not documented — unverified.
6. **Encodings**: not documented for either tier — unverified; test empirically.
7. **MO injection**: on the shared simulator, MO is triggered by encoding **the bound system_id's digits into the destination address** (prepend/append ≥2 digits, min 8 chars total) [technical details page] — an unusual, non-obvious convention, worth automating carefully. Dedicated instances configure acceptable MSISDNs per-ESME via `esme_<systemid>.config`.
8. **Fault injection**: dedicated instance's `dlr.conf`/`shouldReturnUndeliveredReceipts` cover DLR-level faults; explicit `ESME_RTHROTTLED`/`ESME_RMSGQFUL`/bind-refusal/connection-drop simulation not documented for either tier — unverified.
9. **TLS**: shared service — "TLS 1.1 and up are supported for SMPP sessions. SSL and TLS 1.0 are not supported," on a separate port **8775** [main service page]. Dedicated instances also offer TLS as a paid option.
10. **Minimal use**: bind to `smscsim.melroselabs.com:2775` with credentials issued after signing up for a free developer account ([python tutorial](https://developers.melroselabs.com/docs/send-sms-with-smpp-using-python) shows the PDU shape but not the signup flow itself).
11. **Quirks / limits**: shared service capped at 100 SMS/sec; a separate, apparently-independent free public simulator is listed at `smscsim.smpp.org:2775` (max 2 SMS/sec) via [smpp.org's testing page](https://smpp.org/smpp-testing-development.html) — relationship to Melrose Labs unverified. Melrose Labs also offers standalone browser tools worth knowing about: an [SMPP client](https://melroselabs.com/) (bind/submit without installing anything), [SMPP Load Test](https://melroselabs.com/), and an [SMPP Analyser](https://melroselabs.com/) that captures a session to a downloadable pcap.
## 5. ukarim/smscsim — best lightweight OSS option
1. [github.com/ukarim/smscsim](https://github.com/ukarim/smscsim), Go, MIT, "Lightweight, zero-dependency and stupid SMSc simulator." GitHub push activity is current (last push 2025-12-12) — the most recently-touched OSS candidate found besides Jasmin/jsmpp.
2. **Docker**: `ukarim/smscsim` on Docker Hub. Highest **semver** tag is `0.2.0` (pushed ~3 years ago per Docker Hub); newer builds exist only as commit-hash tags (e.g. `a2c646d`, ~2 years ago) with no semver — **use `ukarim/smscsim:0.2.0` for a reproducible pinned tag**, or pin the specific commit-hash tag if you need the newer build and accept it's not semver.
```
docker run -p 2775:2775 -p 12775:12775 ukarim/smscsim:0.2.0
```
Ports: SMPP `2775` (env `SMSC_PORT`), web UI `12775` (env `WEB_PORT`). No auth/credentials required by default.
3. **SMPP version**: implements "only a small subset of the SMPP3.4 specification." PDUs: `bind_transmitter`, `bind_receiver`, `bind_transceiver`, `unbind`, `submit_sm`, `enquire_link`, `deliver_sm_resp`. Explicitly: **"simulator does not perform PDU validation"** — so it will not reject a bad `interface_version` or malformed PDU; not useful for negative-path bind testing.
4. **Delivery receipts**: fixed — DLR always returned ~2s after `submit_sm` with `message_state` **always DELIVERED**; no way to simulate other states except via the `FAILED_SUBMITS` fault-injection flag below. TLV vs text not detailed in the README.
5. **Long messages**: not documented — given the minimal PDU set, treat UDH/`sar_*`/`message_payload` support as unverified/likely absent.
6. **Encodings**: not documented — unverified.
7. **MO injection**: web page at `http://localhost:12775` sends a `deliver_sm` to the active session — simplest MO-injection UX of any candidate here.
8. **Fault injection**: `FAILED_SUBMITS=1` env var — even sequence numbers get a `submit_sm` system-error response, odd sequence numbers get an undeliverable DLR. No throttling, no bind refusal, no connection-drop simulation.
9. **TLS**: not mentioned — unsupported.
10. **Minimal run**: shown above; no config file, everything is env vars.
11. **Quirks**: "does not perform PDU validation" is explicit in the README — good for happy-path/throughput testing, useless for asserting your library correctly handles a *rejecting* SMSC.
## 613. Other candidates (condensed)
| Candidate | Notes |
|---|---|
| [mdouchement/smsc3](https://github.com/mdouchement/smsc3) | Go, MIT, SMPP3.4-based, port 20001 (SMPP)/6000 (HTTP). MO injection via `POST /deliver` with JSON `{session, sender, recipient, message}`. Has Dockerfile+compose but built around integrating with Kannel specifically. Last push 2024-05-09, low adoption (10 stars). |
| [K2InformaticsGmbH/smsc_simulator](https://github.com/K2InformaticsGmbH/smsc_simulator) | Erlang, Apache-2.0, speaks both SMPP and UCP. Abandoned — **last commit 2018-08-31**. Configured/driven from the Erlang shell (`smsc_simulator:start(smpp,10000)`), no Docker. Skip unless you specifically need UCP too. |
| [MavoCz/smscsim](https://github.com/MavoCz/smscsim) | Java, built on cloudhopper-smpp, so inherits 3.3/3.4/5.0 support and real PDU validation. Multi-port CLI (`-p 34567 34568 34569`), sends DLRs after a configurable fixed/random delay round-robin to connected RX/TRX binds. No Docker; requires Maven build + editing Spring XML for anything beyond port/log-level. Last-commit date unverified. |
| [fizzed/cloudhopper-smpp](https://github.com/fizzed/cloudhopper-smpp) (successor to [twitter-archive/cloudhopper-smpp](https://github.com/twitter-archive/cloudhopper-smpp), which is archived) | Java library, Apache-2.0, not a packaged simulator — but ships runnable demo classes (`make server`, `make server-echo`, `make simulator`, `make ssl-server`) covering SSL and PDU-dump. Good as a base to *write* a custom fixture, not a drop-in server. Last push 2020-10-12. |
| [jsmpp](https://github.com/opentelecoms-org/jsmpp) `jsmpp-examples/.../SMPPServerSimulator.java` | Java, Apache-2.0. jsmpp itself is very actively maintained (**last push 2026-06-17**) — best-maintained *library* in this whole survey. The bundled `SMPPServerSimulator` example demonstrates DLR sending and SSL, but is example code, not a packaged/dockerized tool — expect to fork and extend it. |
| [farhadi/node-smpp](https://github.com/farhadi/node-smpp) | Node.js, MIT, implements SMPP v5 (backward compatible with 3.4), includes both client and server APIs, supports `ssmpp://` TLS, UDH via `message_payload`, and encoding auto-detection (ASCII/Latin1/UCS2). No packaged simulator binary — you write ~30 lines of server code yourself. Last push 2023-12-28. Small existing forks built on it: [tiltroom/fakesmpp](https://github.com/tiltroom/fakesmpp), [theodorosidmar/smpp-server-simulator](https://github.com/theodorosidmar/smpp-server-simulator) (returns error on 1-in-10 `submit_sm`) — neither independently verified for maintenance/quality here. |
| [MikeSafonov/smpp-server-mock](https://github.com/MikeSafonov/smpp-server-mock) | Java, MIT, JUnit5-extension/Spring-Boot-starter mock server for *your own* test suite (assert on captured `SubmitSm`s) — not a standalone server you point an arbitrary client at. Only useful if you also write JVM-side interop tests. Last push 2023-03-10. |
| Restcomm/TeleStax SMSC Gateway "SMPP Simulator" | Bundled GUI test tool inside the RestComm SMSC Gateway product (`$SMSC_HOME/tools/TelScale-smpp-simulator/bin/run.sh`), default `system_id=test/password=test`, port 2776, transceiver bind, address range `6666` [docs](https://github.com/RestComm/smscgateway/blob/master/docs/adminguide/sources/src/main/resources/en-US/Chapter-smpp-simulator.xml). This is really a load-test client for RestComm's own gateway, not an installable-alone SMSC simulator — and the whole product requires a JSLEE stack. High setup cost for low unique coverage; skip unless you're specifically validating against a carrier-grade SS7-adjacent stack. |
| OsmoMSC SMPP interface | C, part of Osmocom's core-network stack (actively maintained as infrastructure, not as a "test double"). Its SMPP interface lets an ESME bind to a *real* (if simulated-radio) mobile-network MSC to send/receive SMS to subscribers — valuable only if you're also running an Osmocom test network; far too heavy just to test an SMPP library. Treat as out of scope for this project. |
| `smscsim.smpp.org` | Free public SMSC simulator, host/port from [smpp.org's testing page](https://smpp.org/smpp-testing-development.html): `smscsim.smpp.org:2775`, capped at 2 SMS/sec, delivered-only DLRs, per-IP connection limits. Ownership/maintenance unverified — treat as a convenience fallback, not a primary target. |
| Ozeki NG SMS Gateway / NowSMS | Both have a free/trial tier with SMPP server capability, both are closed-source and Windows-first (Ozeki explicitly; NowSMS also ships Linux/Docker in some tiers but is paid-oriented) — out of scope per task instructions beyond this line. |
---
## Recommendation — set these up first
1. **ukarim/smscsim** (Docker `ukarim/smscsim:0.2.0`) — near-zero setup cost, fastest possible CI smoke test: bind, submit, get a DLR, inject an MO from the web UI. Its explicit "no PDU validation" and single fixed DLR state are limitations, not blockers, for a first pass.
2. **Jasmin SMS Gateway** (Docker `jookies/jasmin:0.11.0` + RabbitMQ + Redis) — the only candidate here that is a real, still-developed production SMS gateway with a proper SMPP **server** role, HTTP management, and a DLR pipeline distinct from a toy simulator. Exercises your library against genuinely different internals (Python/Twisted, AMQP-backed message routing) than the Go/Java toys.
3. **Melrose Labs hosted SMSC Simulator** (`smscsim.melroselabs.com:2775`, free tier) — a public, independently-run, closed-box target you don't control, which is exactly the point: it validates your library against an implementation you cannot special-case for. Its TLS port (8775) also covers your TLS interop case for free without standing up your own CA. Follow up with a **dedicated** instance (paid) once you need to script specific DLR failure/latency states via `dlr.conf`.
4. **SMPPSim, built yourself from `kwahome/smpp-sim-docker`** — despite the dead upstream site and lack of a pinned tag, it's the only candidate with rich, config-file-driven **fault injection** (percentage-based delivered/undeliverable/rejected/accepted, intermediate-state transition chance, delayed DLRs, outbind support, MO queue-full retry behavior). Worth the one-time cost of building and tagging your own image specifically to cover the failure- and delay-injection matrix nothing else here offers as cleanly.
Skip Kannel/opensmppbox and `fakesmsc` for now: both Kannel and opensmppbox have had no meaningful commits in a decade, opensmppbox's interop behavior (TLS, throttling, interface_version validation) is entirely undocumented, and `fakesmsc` — despite the name — doesn't speak SMPP at all, so it cannot test this library regardless of effort spent.