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
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
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-…: DELIVRDWhat just happened
- The client parsed the
smpp://URL for host, port and bind credentials, opened the TCP connection, and performed thebind_transceiverhandshake — rejecting with a typedSmppCommandErrorif the server had said no. - The server's
onBindhook authenticated the bind while inbound PDUs were held. submitSmresolved with the response; had the message been longer than one segment, it would have been split into concatenated parts automatically.- The inbound
deliver_smwas recognized as a delivery receipt, parsed into a typed object, emitted as thereceiptevent, and acknowledged automatically.