SkillAgentSearch skills...

Sms

A Go library for encoding and decoding SMSs

Install / Use

/learn @warthog618/Sms

README

sms

A Go library for encoding and decoding SMSs.

go.dev reference Build Status Coverage Status Go Report Card License: MIT

sms is a Go library for encoding and decoding SMS TPDUs, as specified in 3GPP TS 23.040 and 3GPP TS 23.038.

The initial impetus was to provide functionality to send and receive SMSs via a GSM modem, but the library may be generally useful anywhere encoding and decoding SMS TPDUs or their fields is required.

Features

Supports the following functionality:

  • Creation of SMS TPDUs from UTF-8 strings, including emoji's 😁
  • Segmentation of long messages into several concatenated SMS TPDUs
  • Automatic selection of alphabet and language when encoding
  • Decoding of SMS TPDUs into UTF-8 strings
  • Reassembly of concatenated SMS TPDUs into a long message
  • Support for all GSM character sets
  • Encoding and decoding SMS TPDUs in PDU mode for exchange with GSM modems

Usage

import "github.com/warthog618/sms"

In the following usage examples the error handling is omitted for brevity.

Encode

Creating the TPDUs to contain a message is referred to as encoding.

A one-off message can be encoded using sms.Encode:

tpdus, _ := sms.Encode([]byte("hello world"))
for _, p := range tpdus {
    b, _ := p.MarshalBinary()
    // send binary TPDU...
}

Sending multiple messages requires maintaining multiple counter fields and encoding them in the TPDU. This is performed by an sms.Encoder:

e := sms.NewEncoder()
for {
    msg := <- msgChan
    tpdus, _ := e.Encode(msg)
    for _, p := range tpdus {
        b, _ := p.MarshalBinary()
        // send binary TPDU...
    }
}

Unmarshal

Reassembling received TPDUs into a complete message is a multi-step process. The first step is to unmarhsal the binary SMS TPDU into a TPDU object using sms.Unmarshal:

pdu, _ := sms.Unmarshal(bintpdu)

Decode

A single segment TPDU can be decoded using sms.Decode:

msg, _ := sms.Decode([]*tpdu.TPDUs{pdu})

For concatenated messages, the set of TPDUs containing a message is reassembled into a complete message using sms.Decode:

msg, _ := sms.Decode(tpdus)

Collect

The segments of concatenated messages must be collected before they can be decoded. The Collector collects received segments and returns the complete set once the final segment is received.

c := sms.NewCollector()
for {
    bintpdu := <- pduChan
    pdu, _ := sms.Unmarshal(bintpdu)
    tpdus, _ := c.Collect(pdu)
    if len(tpdus) > 0 {
        msg, _ := sms.Decode(tpdus)
        // handle msg...
    }
}

Options

The core API is aimed at the most common use cases, those performed to the mobile station. e.g. By default, sms.Encode creates an SMS-SUBMIT TPDU and only uses the default character set. By default, sms.Decode uses all character sets. By default, sms.Unmarshal assumes the TPDU is mobile terminating.

The behaviour of the core API functions can be altered for other use cases using optional parameters.

e.g. to specify the destination number for a SMS-SUBMIT message:

tpdus, _ := sms.Encode("hello",sms.To("12345"))

or to encode a message using a particular character set, if necessary:

tpdus, _ := sms.Encode("hello ٻ",sms.WithCharset(charset.Urdu))

or to specify the encoding of a SMS-DELIVER message:

tpdus, _ := sms.Encode("hello",sms.AsDeliver,sms.From("12345"))

or to unmarshal a TPDU from the mobile station:

pdu, _ := sms.Unmarshal(bintpdu,sms.AsMO)

The full set of supplied options:

Option | Category | Description ---|---|--- WithReassemblyTimeout(duration,handler)|Collect|Limit the time allowed to wait for the TPDUs of a complete reassembly WithTemplate(tpdu)|Encode|Use the provided TPDU as the template for encoded TPDUs. WithTemplateOption(tpdu.Option)|Encode|Apply the provided option to the template TPDU during encoding. To(number)|Encode|Set the DA of the encoded TPDU to the number provided From(number)|Encode|Set the OA of the encoded TPDU to the number provided WithAllCharsets|Decode,Encode|Make all GSM7 character sets available WithDefaultCharset|Decode,Encode|Make only the default character set available WithCharset(nli...)|Decode,Encode|Make the specified character set(s) available WithLockingCharset(nli...)|Decode,Encode|Make the specified character set(s) available as a locking character set WithShiftCharset(nli...)|Decode,Encode|Make the specified character set(s) available as a shift character set AsSubmit|Encode|Encode the TPDU as a SMS-SUBMIT (default) AsDeliver|Encode|Encode the TPDU as a SMS-DELIVER As8Bit|Encode|Force the encoding of user data as 8-bit AsUCS2|Encode|Force the encoding of user data as UCS-2 AsMO|Unmarshal|Treat the TPDU as originating from the mobile station AsMT|Unmarshal|Treat the TPDU as terminating at the mobile station (default)

Tools

The cmd directory contains basic commands tools to exercise, debug and demonstrate the core functionality of the library, including:

The following examples demonstrate the example commands, and their code provides some examples of using the library.

Submit Encoding

Creating an SMS to send:

$ smssubmit -number 12345 -message "Hello world"
Submit TPDU:
010105912143f500000bc8329bfd06dddf723619

Long messages are split into a concatenated message spanning several TPDUs:

smssubmit -number 12345 -message "this is a very long message that does not fit in a single SMS message, at least it will if I keep adding more to it as 160 characters is more than you might think 😁"
Submit TPDU 1:
410105912143f500088c050003010301007400680069007300200069007300200061002000760065007200790020006c006f006e00670020006d0065007300730061006700650020007400680061007400200064006f006500730020006e006f0074002000660069007400200069006e00200061002000730069006e0067006c006500200053004d00530020006d0065007300730061
Submit TPDU 2:
410205912143f500088c05000301030200670065002c0020006100740020006c0065006100730074002000690074002000770069006c006c002000690066002000490020006b00650065007000200061006400640069006e00670020006d006f0072006500200074006f0020006900740020006100730020003100360030002000630068006100720061006300740065007200730020
Submit TPDU 3:
410305912143f5000844050003010303006900730020006d006f007200650020007400680061006e00200079006f00750020006d00690067006800740020007400680069006e006b0020d83dde01

Deliver Decoding

Decoding an SMS received from a GSM modem in PDU mode:

$ smsdeliver -p 07911614220991F1040B911605935713F200008140806113912304D7F79B0E
+61503975312: Woot

Concatenated Message Decoding

Concatenating and displaying a message split into multiple SMS-DELIVER TPDUs.

$ smsdeliver 400B911605935713F20008814080611373238C050003C00301007400680069007300200069007300200061002000760065007200790020006C006F006E00670020006D0065007300730061006700650020007400680061007400200064006F006500730020006E006F0074002000660069007400200069006E00200061002000730069006E0067006C006500200053004D00530020006D0065007300730061 400B911605935713F20008814080611373238C050003C0030200670065002C0020006100740020006C0065006100730074002000690074002000770069006C006C002000690066002000490020006B00650065007000200061006400640069006E00670020006D006F0072006500200074006F0020006900740020006100730020003100360030002000630068006100720061006300740065007200730020 440B911605935713F200088140806113832344050003C00303006900730020006D006F007200650020007400680061006E00200079006F00750020006D00690067006800740020007400680069006E006B0020D83DDE01
+61503975312: this is a very long message that does not fit in a single SMS message, at least it will if I keep adding more to it as 160 characters is more than you might think 😁

General TPDU Decoding

Decoding the Submit TPDU created above:

$ smsdecode -o 010105912143f500000bc8329bfd06dddf723619
TPDU: SMS-SUBMIT
TP-MTI: 0x01 Submit
TP-RD: false
TP-VPF: 0x00 Not Present
TP-RP: false
TP-UDHI: false
TP-SRR: false
TP-MR: 1
TP-DA: +12345
TP-PID: 0x00
TP-DCS: 0x00 7bit
TP-VP: Not Present
TP-UD: 00000000  48 65 6c 6c 6f 20 77 6f  72 6c 64                 |Hello world|

Decoding the Deliver TPDU above:

$ smsdecode -p 07911614220991F1040B911605935713F200008140806113912304D7F79B0E
SMSC: +61412290191
TPDU: SMS-DELIVER
TP-MTI: 0x00 Deliver
TP-MMS: true
TP-LP: false
TP-RP: false
TP-UDHI: false
TP-SRI: false
TP-OA: +61503975312
TP-PID: 0x00
TP-DCS: 0x00 7bit
TP-SCTS: 2018-04-08 16:31:19 +0800
TP-UD: 00000000  57 6f 6f 74                                       |Woot|

Decoding the first Deliver TPDU of the concatenated message above:

$ smsdecode 400B911605935713F20008814080611373238C050003C00301007400680069007300200069007300200061002000760065007200790020006C006F006E00670020006D0065007300730061006700650020007400680061007400200064006F006500730020006E006F0074002000660069007400200069006E00200061002000730069006E0067006C006500200053004D00530020006D0065007300730061
TPDU: SMS-DELIVER
TP-MTI: 0x00 Deliver
TP-MMS: false
TP-LP: false
TP-RP: false
TP-UDHI: true
View on GitHub
GitHub Stars73
CategoryDevelopment
Updated3mo ago
Forks30

Languages

Go

Security Score

97/100

Audited on Dec 23, 2025

No findings