better-smpp

Quickstart

Send your first message in five minutes.

This walks through a complete round trip: a server that authenticates binds and accepts submissions, and a client that connects, binds, sends a message and receives the delivery receipt.

1. Start a server

server.ts
import { SmppServer } from "@better-smpp/server";
import { randomUUID } from "node:crypto";

const server = new SmppServer({
  systemId: "MYSMSC",
  // Return true to accept, false for ESME_RBINDFAIL, or a CommandStatus code.
  onBind: (session, pdu) =>
    pdu.systemId === "demo" && pdu.password === "secret",
});

server.on("session", (session) => {
  session.on("submit_sm", async (pdu) => {
    const messageId = randomUUID();
    await session.respond(pdu, { messageId });

    // Push a delivery receipt back a moment later.
    setTimeout(() => {
      void session.deliverSm({
        sourceAddr: pdu.destinationAddr,
        destinationAddr: pdu.sourceAddr,
        esmClass: 0x04, // delivery receipt
        receiptedMessageId: messageId,
        messageState: 2, // DELIVERED
        shortMessage: `id:${messageId} sub:001 dlvrd:001 stat:DELIVRD err:000 text:`,
      });
    }, 100);
  });
});

const port = await server.listen({ port: 2775 });
console.log(`SMSC listening on :${port}`);

2. Connect a client

client.ts
import { SmppClient } from "@better-smpp/client";

const client = new SmppClient({
  url: "smpp://demo:secret@localhost:2775",
  enquireLink: 30_000, // keepalive + dead-link detection
});

await client.connect();
await client.bindTransceiver(); // credentials come from the URL

client.on("receipt", (receipt) => {
  console.log(`message ${receipt.messageId}: ${receipt.state}`);
});

const result = await client.submitSm({
  destinationAddr: "46709771337",
  shortMessage: "Hello from better-smpp!",
  registeredDelivery: 1,
});
console.log(`accepted as ${result.messageId}`);

Run both and you'll see the submit accepted and the parsed receipt arrive:

accepted as 1a0e3f0c-…
message 1a0e3f0c-…: DELIVRD

What just happened

  • The client parsed the smpp:// URL for host, port and bind credentials, opened the TCP connection, and performed the bind_transceiver handshake — rejecting with a typed SmppCommandError if the server had said no.
  • The server's onBind hook authenticated the bind while inbound PDUs were held.
  • submitSm resolved with the response; had the message been longer than one segment, it would have been split into concatenated parts automatically.
  • The inbound deliver_sm was recognized as a delivery receipt, parsed into a typed object, emitted as the receipt event, and acknowledged automatically.

Next steps

On this page