Sending messages
submitSm with automatic concatenation, encodings, and the other operations.
submitSm
const result = await client.submitSm({
destinationAddr: "46709771337",
shortMessage: "Hello!",
registeredDelivery: 1, // request a delivery receipt
});submitSm resolves with a SubmitResult:
interface SubmitResult {
messageId: string | undefined; // id of the first (or only) segment
messageIds: string[]; // all segment ids, in order
segments: number; // how many submit_sm PDUs were sent
responses: SubmitSmRespPdu[]; // every response, in order
}It rejects with SmppCommandError on any non-ESME_ROK response.
Automatic concatenation
Text longer than one message is split transparently — 160 GSM septets / 140 octets / 70 UCS2 characters for singles; 153 / 134 / 67 per segment. Splitting is encoding-aware: GSM escape pairs and UTF-16 surrogate pairs are never cut, and all segments share one reference number.
const result = await client.submitSm({
destinationAddr: "46709771337",
shortMessage: "A long marketing blast… ".repeat(30),
});
result.segments; // e.g. 4
result.messageIds; // one id per segmentConfigure the transport method — 6-octet concat UDH (default) or SAR TLVs — via the client options:
new SmppClient({ concatenation: { method: "sar" } }); // sar_* TLVs
new SmppClient({ concatenation: { wideRef: true } }); // 16-bit UDH refs
new SmppClient({ concatenation: false }); // send as-is (old behavior)Buffers and messages with an explicit udh are never split — you own the framing.
Encodings
Leave dataCoding unset and the most compact encoding is detected per message —
GSM 03.38 → Latin-1 → UCS2 — and stamped onto the PDU:
await client.submitSm({ destinationAddr: "...", shortMessage: "hello" }); // GSM, dataCoding 0x01
await client.submitSm({ destinationAddr: "...", shortMessage: "привет" }); // UCS2, dataCoding 0x08Force an encoding by setting dataCoding explicitly (DATA_CODING.UCS2, …); binary
payloads go through untouched as Buffers with DATA_CODING.BINARY.
Timeouts and cancellation
Every operation accepts per-request options:
const controller = new AbortController();
const pending = client.submitSm(params, {
timeoutMs: 5_000,
signal: controller.signal,
});
controller.abort(); // rejects with SmppAbortErrorOther operations
// Payload in the message_payload TLV instead of short_message:
await client.dataSm({ destinationAddr: "...", messagePayload: "payload" });
// Message lifecycle management:
const status = await client.querySm({ messageId: "abc", sourceAddr: "1000" });
await client.replaceSm({ messageId: "abc", sourceAddr: "1000", shortMessage: "new" });
await client.cancelSm({ messageId: "abc", sourceAddr: "1000", destinationAddr: "2000" });For anything not covered — submit_multi, broadcast commands, custom vendor PDUs —
use the raw escape hatch:
const resp = await client.request({
command: "submit_multi",
sourceAddr: "1000",
destAddress: [
{ destAddrTon: 1, destAddrNpi: 1, destinationAddr: "46709771337" },
{ dlName: "vip-customers" },
],
shortMessage: "multi-destination message",
});See Custom commands for vendor extensions.