Skip to main content

smpp34

crates.io docs.rs CI license

A pure-Rust implementation of the SMPP 3.4 protocol (Short Message Peer-to-Peer): a PDU codec plus an asynchronous (tokio) client and server built on a listener-trait model.

The same engine ships two ways from one source tree, one version: a Rust crate (cargo add smpp34, zero Python dependencies) and a Rust-backed Python wheel (pip install smpp34) that exposes the identical async client/server to asyncio. The whole SMPP machinery — framing, windowing, timers, codec — runs in the Rust/tokio core; Python crosses the GIL only once per message, and the extension is free-threaded ("no-GIL") ready. See Python below.

  • Client — bind to an SMSC as an ESME (transmitter, receiver or transceiver), send submit_sm / data_sm, and receive deliver_sm and session events through your own SmppClientListener.
  • Server — accept ESME binds and dispatch submit_sm, data_sm, cancel_sm, … to your SmppServerListener; push MT traffic back out with deliver_sm.
  • Codec — encode/decode every SMPP 3.4 PDU, including optional TLV parameters.

Sessions handle the SMPP timers (session_init, enquire_link, inactivity, response), sequence-number windowing, and optional TLS.

Supported PDUs

bind_transmitter · bind_receiver · bind_transceiver (+ resps) · outbind · unbind · enquire_link · submit_sm · submit_sm_multi · deliver_sm · data_sm · query_sm · cancel_sm · replace_sm · alert_notification · generic_nack, plus arbitrary TLV (optional parameter) encode/decode.

Install

cargo add smpp34

Quick start — server

Implement SmppServerListener and hand it to an SmppServer. Every trait method has a default, so you override only the PDUs you care about — typically on_bind_transceiver and on_submit_sm.

use std::sync::Arc;
use std::net::{IpAddr, Ipv4Addr};
use async_trait::async_trait;
use smpp34::{
    SmppServer, SmppServerListener, SmppConnectionInformation, SmppError,
    bind_transceiver, bind_transceiver_resp, submit_sm, submit_sm_resp,
};

struct MyEsmeHandler;

#[async_trait]
impl SmppServerListener for MyEsmeHandler {
    async fn on_bind_transceiver(
        &self, req: bind_transceiver, _c: &SmppConnectionInformation, _s: &String,
    ) -> bind_transceiver_resp {
        if req.system_id == "esme1" && req.password == "secret" {
            req.accept("MySMSC".to_string(), Some(0x34))   // 0x34 = SMPP v3.4
        } else {
            req.reject(SmppError::ESME_RINVPASWD)
        }
    }

    async fn on_submit_sm(
        &self, req: submit_sm, _c: &SmppConnectionInformation, _s: &String,
    ) -> submit_sm_resp {
        // ... route the message ...
        req.accept("message-id-1".to_string())
    }

    // Every other method has a sensible default (binds reject, on_data_sm /
    // on_cancel_sm reject, on_unbind acks, notifications no-op), so you override
    // only what you need.
}

#[tokio::main]
async fn main() {
    let listener = Arc::new(MyEsmeHandler);
    let mut server = SmppServer::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 2775, listener);
    server.start().await;          // spawns the accept loop
    tokio::signal::ctrl_c().await.unwrap();
    server.stop().await;
}

Quick start — client

Bind to an SMSC, then submit once the bind completes (the on_smsc_bound callback hands you an SMSC you can submit through).

use std::sync::Arc;
use smpp34::client::{SmppClient, BIND_TYPE};

// `listener` implements SmppClientListener; its on_smsc_bound callback hands
// you the bound `SMSC` handle to submit through.
let listener = Arc::new(MyClientHandler::new());
let mut client = SmppClient::new(
    "smsc.example.net".to_string(), 2775, /* tls = */ false,
    BIND_TYPE::TRX,
    "esme1".to_string(), "secret".to_string(), "GATEWAY".to_string(),
    /* addr_ton */ 0, /* addr_npi */ 0, /* address_range */ String::new(),
    listener.clone(),
    /* window_size */ 20,
);
client.start().await;
// inside on_smsc_bound(smsc, _): use the fluent builder (only set what you need)
//   smsc.submit_sm()
//       .source_addr("12345")
//       .destination_addr("31600000000")
//       .short_message(b"hello")
//       .send().await?;

Python

pip install smpp34 gives a Rust-backed wheel exposing the same async client/server to asyncio. The hot path stays in the Rust/tokio core; the Python layer is an event-pull bridge that crosses the GIL once per message. abi3 wheels cover CPython 3.9+, plus free-threaded ("no-GIL") builds.

pip install smpp34

Client — connect() binds and returns an Smsc; await sends and inbound events:

import asyncio, smpp34

async def main():
    client = smpp34.Client(host="smsc.example.net", port=2775,
                           system_id="esme1", password="secret", bind_type="TRX")
    smsc = await client.connect()
    resp = await smsc.submit_sm(destination_addr="31600000000",
                                source_addr="12345", short_message=b"hello")
    print(resp.message_id, resp.is_success)

    # pull inbound deliver_sm (MO / DLR) — one GIL crossing per message
    ev = await smsc.next()                       # DeliverSmEvent | Disconnected
    if isinstance(ev, smpp34.DeliverSmEvent):
        print(ev.source_addr, ev.short_message)
    await smsc.unbind()

asyncio.run(main())

Server — await next() yields an Esme when a client binds, a SubmitSmEvent per inbound message (answer with accept/reject), or Unbound:

import asyncio, smpp34

async def main():
    server = smpp34.Server(host="0.0.0.0", port=2775, system_id="MySMSC")
    await server.start()
    sessions = {}
    while True:
        ev = await server.next()
        if isinstance(ev, smpp34.Esme):
            sessions[ev.session_id] = ev          # stash the MT send handle
        elif isinstance(ev, smpp34.SubmitSmEvent):
            ev.accept(message_id="abc")           # or ev.reject(smpp34.ESME_RMSGQFUL)
            # push MT back to that ESME (here, a delivery receipt):
            await sessions[ev.session_id].deliver_sm(
                source_addr=ev.destination_addr, destination_addr=ev.source_addr,
                esm_class=0x04, short_message=b"id:abc stat:DELIVRD")

asyncio.run(main())

Codec — encode/decode PDUs without any I/O:

pdu = smpp34.SubmitSm(source_addr="12345", destination_addr="31600000000",
                      short_message=b"hello")
wire = pdu.encode()
msg = smpp34.decode(wire)        # -> typed SubmitSm / DeliverSm / RawPdu

Runnable samples: python/examples/ (and the Rust equivalents in examples/ — client.rs / server.rs). A throughput and leak harness lives in python/perf/, mirroring the Rust examples/{perf_loopback,leak_check}.rs.

Optional parameters (TLVs)

Inbound TLVs are on pdu.tlvs in wire order, with typed accessors from the TlvList trait. Outbound, the builders take them directly:

use smpp34::{Tlv, TlvTag, TlvList};

// ESME -> SMSC
smsc.submit_sm()
    .source_addr("12345")
    .destination_addr("31600000000")
    .tlv(TlvTag::MessagePayload, "a body past the 254-byte short_message limit")
    .tlv(TlvTag::UserMessageReference, 42u16.to_be_bytes())
    .tlv_raw(0x1403, [0xAA, 0xBB])          // vendor-specific tag
    .send().await?;

// SMSC -> ESME: a delivery receipt is TLVs, nothing else
esme.deliver_sm()
    .source_addr("31600000000")
    .destination_addr("12345")
    .esm_class(0x04)
    .tlvs([
        Tlv::from_c_string(TlvTag::ReceiptedMessageId, "abc"),
        Tlv::from_u8(TlvTag::MessageStateTlv, 2),   // DELIVERED
    ])
    .send().await?;

// reading, on either side
let dlr_id = request.tlvs.receipted_message_id();

For a PDU built up front (relaying a decoded one, or data_sm, whose message body only exists as the message_payload TLV) use the *_pdu send methods — the session assigns the sequence number:

let pdu = data_sm::new(0, String::new(), 1, 1, "12345".into(), 1, 1, "31600000000".into(), 0, 0, 8)
    .with_tlvs([Tlv::from_tag(TlvTag::MessagePayload, body)]);
smsc.send_data_sm_pdu(pdu).await?;

In Python, tlvs= takes a list of Tlv(tag, value) and the tag constants are on the module:

await smsc.submit_sm("31600000000", b"hi", source_addr="12345", tlvs=[
    smpp34.Tlv(smpp34.TLV_USER_MESSAGE_REFERENCE, (42).to_bytes(2, "big")),
    smpp34.Tlv(smpp34.TLV_MESSAGE_PAYLOAD, b"the real body"),
])

ev = await smsc.next()
print([(hex(t.tag), t.value) for t in ev.tlvs])

All 44 spec-defined tags are in TlvTag / smpp34.TLV_*; unknown and vendor-specific tags (0x1400-0x3FFF) pass through byte for byte.

TLS

Pass tls = true to SmppClient::new to bind over TLS. The TLS transport is rustls (via tokio-rustls, ring backend), so no system TLS library is needed to build or run.

  • TLS 1.2 and 1.3, ECDHE key exchange with AEAD ciphers only. A peer limited to RSA key exchange or CBC suites cannot be reached.
  • The server certificate is verified against the operating system's trust store (SSL_CERT_FILE / SSL_CERT_DIR are honoured), and against the address you passed, hostname or IP. It must carry a matching subjectAltName; a certificate that only names the host in its CN is rejected.
  • No client certificate (mTLS) and no per-client CA yet.

Timers & windowing

SmppServer::new / SmppClient::new use sensible default timers. Use the *_with_default_timers constructors to set session_init, enquire_link, inactivity and response timers (milliseconds) and the buffer / window size explicitly.

Performance

Measured on a 24-core AMD Ryzen AI 9 HX 370 (single box — the SMSC and ESME are co-located, so the load generator competes for cores; separate hosts scale further). Reproduce with cargo bench and perf/docker-compose.yml.

Codec — single core, criterion (cargo bench):

Operation Throughput
submit_sm decode ~6.6 M PDU/s
submit_sm encode ~12.3 M PDU/s
deliver_sm decode / encode ~6.8 M / ~12.6 M PDU/s
TLV decode / encode ~20 M / ~14 M /s

End-to-end — real TCP, full submit_sm round-trip (send → submit_sm_resp):

Load Throughput Peak RSS
1 ESME, window 64 ~180k submit_sm/s 6 MB
4 ESMEs, window 64 ~635k submit_sm/s 7 MB

The SMSC server sustains 625k+ submit_sm/s even pinned to half the cores; past a few sessions the single-box benchmark is bound by the co-located load generator, not by smpp34.

Rust vs Python (and free-threading)

Both languages drive the same Rust/tokio engine, so the protocol work — framing, windowing, timers, codec — runs at full Rust speed either way. The difference is the Python boundary: the event-pull bridge crosses the GIL once per message.

Path Throughput Notes
Rust — 4 ESMEs, window 64 ~635k submit_sm/s full multi-threaded tokio core
Python — single asyncio loop ~25k submit_sm/s one GIL crossing per message (release wheel)
Codec decode — GIL CPython ~4.5M PDU/s (flat vs threads) the GIL serialises the pyo3 call
Codec decode — free-threaded, 4 threads ~12M PDU/s no GIL → real parallelism

A few things worth knowing:

  • Build matters. A maturin develop debug build is ~3× slower; published wheels are --release. The ~25k/s figure is a release build.
  • Tune the tokio pool with SMPP34_WORKER_THREADS (default 2). On a many-core box, a large pool thrashes the GIL on every future completion and throughput drops (24 threads ≈ 17k/s vs 1 thread ≈ 28k/s); on a free-threaded build, raise it.
  • Free-threaded ("no-GIL") is correctness-clean — the full test suite passes with the GIL off (sys._is_gil_enabled() == False) — and lets CPU-bound Python work (the codec, your per-message handlers) run in parallel, as the codec row shows. Single-process async I/O is bounded by the shared tokio runtime, so scale that across processes.
  • ~25k submit_sm/s on one event loop is already well above the per-bind rate limits carriers typically impose.

Reproduce: python/perf/perf_loopback.py (COUNT=200000 SESSIONS=4 WINDOW=64), the thread-scaling demo python/perf/perf_threads.py, and the leak check python/perf/leak_check.py — all after a release build (maturin develop --release).

Profiling

A CPU flamegraph of the loopback under load (scripts/flamegraph.sh) puts ~99.98% of samples in the kernel (the socket/syscall path) — the user-space codec barely appears. smpp34 is syscall-bound, not CPU-bound: at these rates the cost is the ~600k+ read/write syscalls per second plus the runtime's wakeups, not parsing (the codec runs at millions of PDUs/sec). The remaining headroom is therefore I/O batching — coalescing writes and cutting wakeups — not faster code.

Memory

scripts/mem_leak_test.sh installs a counting global allocator and asserts live bytes stay flat (exact — unlike noisy RSS) across both codec round-trips and bind/unbind churn. RSS holds at single-digit MB while pushing millions of PDUs. (The bind/unbind check found and now guards a real session-teardown leak — see the changelog.)

SMPP 3.4 compliance

The PDU / TLV / session support matrix is in docs/COMPLIANCE.md; docs/COMPARISON.md maps smpp34 against other SMPP stacks.

MSRV

Rust 1.80.

Stability

The SMPP 3.4 codec and the client/server session handling are used in production, and the crate follows Semantic Versioning: the public Rust API is the contract. The 17-argument send_submit_sm / send_deliver_sm remain available, but the submit_sm() / deliver_sm() builders are the recommended way to send.

License

MIT © Real Time Telecom B.V.

Maintained by Real Time Telecom B.V. — carrier-grade telecom infrastructure in Rust.

Metadata

Release files for smpp34 1.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for smpp34 1.5.1
File Size Uploaded Provenance Actions
smpp34-1.5.1.tar.gz 142.2 kB With provenance Details for smpp34-1.5.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for smpp34 1.5.1
File Actions
smpp34-1.5.1-cp314-cp314t-win_amd64.whl CPython 3.14 CPython 3.14 free-threading Windows x86-64 Details for smpp34-1.5.1-cp314-cp314t-win_amd64.whl
smpp34-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64 Details for smpp34-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
smpp34-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64 Details for smpp34-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl
smpp34-1.5.1-cp39-abi3-win_amd64.whl CPython 3.9 abi3 Windows x86-64 Details for smpp34-1.5.1-cp39-abi3-win_amd64.whl
smpp34-1.5.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.9 abi3 Linux glibc 2.17+ x86-64 Details for smpp34-1.5.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
smpp34-1.5.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.9 abi3 Linux glibc 2.17+ ARM64 Details for smpp34-1.5.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
smpp34-1.5.1-cp39-abi3-macosx_11_0_arm64.whl CPython 3.9 abi3 macOS 11.0+ ARM64 Details for smpp34-1.5.1-cp39-abi3-macosx_11_0_arm64.whl
smpp34-1.5.1-cp39-abi3-macosx_10_12_x86_64.whl CPython 3.9 abi3 macOS 10.12+ x86-64 Details for smpp34-1.5.1-cp39-abi3-macosx_10_12_x86_64.whl

Total release size: 13.8 MB

Release files / smpp34-1.5.1.tar.gz

Download URL smpp34-1.5.1.tar.gz
Size 142.2 kB
Tags Source
SHA-256 checksum
How to use checksums
362c3ce57f7c60dec78fcdeaebc34be096233cce065f40b7bab230f03b448a72
BLAKE2b-256 checksum
How to use checksums
d085721d6d7eb97f7624ded64db5c5348d8f66e216dc39f7f2a0103ea015d356
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp314-cp314t-win_amd64.whl

Download URL smpp34-1.5.1-cp314-cp314t-win_amd64.whl
Size 1.5 MB
Tags CPython 3.14 CPython 3.14 free-threading Windows x86-64
SHA-256 checksum
How to use checksums
ecae94e09114073d0021e5974fc61f306015e1de7c1d860b3bfbdad4f1c2a783
BLAKE2b-256 checksum
How to use checksums
75df2a2dce4688b81413c0ac72945c2220fd9b5d965cbdefd213267cc173faed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL smpp34-1.5.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 1.8 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
d660df977ca483c343a8e1c24540f2229274780c357a152bc00da8fdbafcf73b
BLAKE2b-256 checksum
How to use checksums
cbf4db3d0aeca0f8c1669bfd8198d80de2e64f74cbcc3e9e6263e4d679985a54
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl

Download URL smpp34-1.5.1-cp314-cp314t-macosx_11_0_arm64.whl
Size 1.7 MB
Tags CPython 3.14 CPython 3.14 free-threading macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9bc1a2c97a831afa1e63f2d0f78b530719e4f6210f660480f9f6a1dd9e6b29be
BLAKE2b-256 checksum
How to use checksums
86e2456855ea9c2a1a3b06b2ca198d4a1da12adf3a118c9ccbded52b0651eeae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp39-abi3-win_amd64.whl

Download URL smpp34-1.5.1-cp39-abi3-win_amd64.whl
Size 1.6 MB
Tags CPython 3.9 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
fd06ce753da2f20d016bdf66a56100f6ea9aadd73c914ed72a6b1f36a111bd7e
BLAKE2b-256 checksum
How to use checksums
006cd0f101d56960dc489eaaa3e63c016d0e91925f4da96884fffbd3d6db17dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL smpp34-1.5.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 1.8 MB
Tags CPython 3.9 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
a2d74a81e997de8ffde89066dd8b3868a9f9b8e89e97eed0aa1bfad077bc431f
BLAKE2b-256 checksum
How to use checksums
48ce856d94a40d912738537338f8547961c437b86375059fe6f238300bfba86a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL smpp34-1.5.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 1.9 MB
Tags CPython 3.9 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
bebc1988987716e37792c82d39fd28a2a8602e8f911a8e4d0b563edc4abef775
BLAKE2b-256 checksum
How to use checksums
fc23a2798a9782481e12299bf12f2d228d156b5bf35406ce1743aed0947aa184
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp39-abi3-macosx_11_0_arm64.whl

Download URL smpp34-1.5.1-cp39-abi3-macosx_11_0_arm64.whl
Size 1.7 MB
Tags CPython 3.9 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
1f5d12056943932362c2683fccef6f59b954ad343acc9bd38c926784b31f585f
BLAKE2b-256 checksum
How to use checksums
8a1b43a8c82e0b213ef816b3ec091936ec172e6be354187d4bc4b703d455fd63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / smpp34-1.5.1-cp39-abi3-macosx_10_12_x86_64.whl

Download URL smpp34-1.5.1-cp39-abi3-macosx_10_12_x86_64.whl
Size 1.7 MB
Tags CPython 3.9 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
1e9894b6dfb10d0b47019b54daadbad7bf0efd438e54e16972dc471f704b0241
BLAKE2b-256 checksum
How to use checksums
0c0da1390b5e1352468ee8a22d17aae203bf38d5a66deae2daf7e97bdf74a2e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for smpp34 1.5.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 9 files in this release have been uploaded with provenance metadata.

Select from 9 files

Attestation for smpp34-1.5.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.5.1 This release

9 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page