eSMS AfricaeSMS Africa
SMPP Gateway

Troubleshooting

Common SMPP bind errors, connection failures, and how to fix them.

Connection refused / timeout

Symptom: Connection refused or Connection timed out when connecting to smpp.esmsafrica.io:2775.

Causes and fixes:

  1. Firewall blocking outbound port 2775 - Ensure your network allows outbound TCP on port 2775. Check both host firewall (iptables, ufw) and network-level rules.

  2. Wrong port - The only supported port is 2775. There is no port 8775, 5775, or plaintext 2775.

  3. DNS resolution failure - Verify smpp.esmsafrica.io resolves: nslookup smpp.esmsafrica.io.


TLS handshake failure

Symptom: Connection establishes but drops immediately, or you see SSL handshake failed / protocol version errors.

Causes and fixes:

  1. Client does not support TLS 1.3 - TLS 1.3 is required. Upgrade your TLS library. Python: ssl.PROTOCOL_TLS_CLIENT with Python 3.7+ and OpenSSL 1.1.1+. Node.js: 12+ supports TLS 1.3 natively.

  2. smpplib not passing TLS context - Pass a ssl.SSLContext to client.connect(ssl=ctx), not ssl=True:

    ctx = ssl.create_default_context()
    client.connect(ssl=ctx)  # correct
  3. Corporate proxy stripping TLS - Some proxies intercept TCP. Connect directly or configure a TLS passthrough.


ESME_RBINDFAIL (0x0000000E) - Bind rejected

Symptom: bind_*_resp returns command_status=0x0000000E.

Causes and fixes:

  1. Wrong system_id or password - Double-check your credentials. Credentials are case-sensitive.

  2. system_type mismatch - Leave system_type as an empty string "" unless you were specifically told otherwise.

  3. IP not whitelisted - If your account has IP whitelisting enabled, ensure the source IP of your connection is on the allowlist. Contact noc@esmsafrica.io to add an IP.

  4. Too many concurrent binds - If you have reached your concurrency limit, new binds will be rejected. Unbind idle sessions or request a higher limit.


ESME_RINVSRCADR (0x0000000A) - Invalid source address

Symptom: submit_sm_resp returns command_status=0x0000000A.

Cause: The source_addr (sender ID) you used has not been approved on your account.

Fix: Use an approved sender ID. Check your account portal for the list of approved sender IDs, or request a new one. In the meantime you can use your account's default sender ID.

Also verify source_addr_ton matches the sender type:

  • Alphanumeric text ID → source_addr_ton=5, source_addr_npi=0
  • E.164 number → source_addr_ton=1, source_addr_npi=1

ESME_RTHROTTLED (0x00000058) - Rate limit exceeded

Symptom: submit_sm_resp returns command_status=0x00000058.

Cause: You are submitting faster than your configured throughput window.

Fix:

  1. Add a rate limiter in your client code to stay within the configured TPS.
  2. Open multiple binds and distribute submissions across them.
  3. Contact noc@esmsafrica.io to increase your throughput limit.
rate_limiter.py
import time

class RateLimiter:
    def __init__(self, tps: int):
        self.min_interval = 1.0 / tps
        self.last = 0.0

    def wait(self):
        elapsed = time.monotonic() - self.last
        if elapsed < self.min_interval:
            time.sleep(self.min_interval - elapsed)
        self.last = time.monotonic()

limiter = RateLimiter(tps=80)  # stay under 100 TPS limit

for msg in messages:
    limiter.wait()
    client.send_message(...)

No DLR received

Symptom: Messages are delivered but no deliver_sm DLR arrives on your session.

Causes and fixes:

  1. registered_delivery not set - You must set registered_delivery=1 in every submit_sm to request a DLR.

  2. Using a TX-only bind - DLRs can only arrive on a TRX (bind_transceiver) or RX (bind_receiver) bind. A pure TX bind cannot receive PDUs.

  3. Not calling listen() - In smpplib, you must call client.listen() to enter the receive loop. Without it, inbound PDUs are silently dropped.

  4. Not acknowledging deliver_sm - If you don't respond with deliver_sm_resp, the gateway stops sending DLRs on that bind after a short time. Always acknowledge every deliver_sm.

  5. Short code / long code not configured for MO - For MO traffic, your number must be registered for inbound routing. Contact support.


Duplicate DLRs

Symptom: The same DLR is received multiple times.

Cause: Your application did not acknowledge deliver_sm within the timeout window, causing the gateway to resend.

Fix: Respond to every deliver_sm immediately with deliver_sm_resp. Store processed message_id values and deduplicate if necessary:

dedup.py
seen_ids = set()

def message_received(pdu):
    msg = pdu.short_message
    if isinstance(msg, bytes):
        msg = msg.decode('latin-1')
    dlr = parse_dlr(msg)
    if dlr and dlr['id'] not in seen_ids:
        seen_ids.add(dlr['id'])
        process_dlr(dlr)

Connection drops / lost bind

Symptom: Bind succeeds but the connection closes after a period of inactivity.

Fix: Send enquire_link every 30 seconds and handle enquire_link_resp. Most libraries support this via a timer or auto_enquire_link_period option.

keepalive.py
import threading

def keepalive(client, interval=30):
    while True:
        time.sleep(interval)
        try:
            client.enquire_link()
        except Exception:
            break  # connection lost - trigger reconnect

threading.Thread(target=keepalive, args=(client,), daemon=True).start()

Implement reconnect logic with exponential backoff:

reconnect.py
import time

def connect_with_retry(system_id, password, max_attempts=10):
    delay = 2
    for attempt in range(max_attempts):
        try:
            ctx = ssl.create_default_context()
            client = smpplib.client.Client('smpp.esmsafrica.io', 2775, timeout=30)
            client.connect(ssl=ctx)
            client.bind_transceiver(system_id=system_id, password=password)
            return client
        except Exception as e:
            print(f'Attempt {attempt + 1} failed: {e}. Retrying in {delay}s...')
            time.sleep(delay)
            delay = min(delay * 2, 60)
    raise RuntimeError('Could not reconnect after max attempts')

Getting help

If you cannot resolve an issue:

  1. Collect the full error, bind credentials (system_id only, never password), and your client library version.
  2. Email noc@esmsafrica.io or use the chat in the portal.

NOC engineers are available 24/7 for production issues.

On this page