Passa al contenuto principale

Protocollo SMPP

Cos'è SMPP

SMPP (Short Message Peer-to-Peer) è un protocollo binario per connessioni affidabili e persistenti, progettato per l'invio di SMS su larga scala con tracciamento della consegna. Scegli SMPP quando hai bisogno di:

  • Connessioni persistenti per messaggistica ad alto volume
  • Notifiche di consegna in tempo reale tramite ricevute di consegna
  • Integrazione con infrastrutture di telecomunicazione esistenti

Modalità di connessione

SMPP supporta tre modalità di bind. L'allocazione predefinita è di 4 connessioni, che possono essere combinate tra le diverse modalità.

ModalitàDirezioneDescrizione
TX (Transmitter)Solo invioUtilizzata esclusivamente per l'invio di messaggi. Non può ricevere ricevute di consegna.
RX (Receiver)Solo ricezioneUtilizzata esclusivamente per ricevere ricevute di consegna e messaggi MO (Mobile Originated).
TRX (Transceiver)Invio e ricezioneBidirezionale: può sia inviare messaggi che ricevere ricevute di consegna sulla stessa connessione. Consigliata per la maggior parte delle integrazioni.

:::tip Configurazione consigliata Utilizza la modalità TRX per semplicità. Una singola connessione transceiver gestisce sia l'invio che la ricezione, riducendo la complessità e il sovraccarico delle connessioni. :::


Dettagli di connessione

ParametroValore
HOSTsmpp.agiletelecom.com
PORT2776 (TLS)
SYSTEM IDUsername dell'account
PASSWORDPassword dell'account
MODETX, RX o TRX
Login-AddrRangeVuoto
Login-SystemTypeVuoto
Login-TON1
Login-NPI1
Login-DCS0

:::warning Keep-Alive obbligatorio Invia un pacchetto ENQUIRE_LINK almeno ogni 30 secondi. Se non viene ricevuta alcuna risposta entro 5 minuti, la connessione verrà chiusa. :::


Esempi di codice

Python (smpplib)

pip install smpplib
import smpplib.client
import smpplib.consts
import smpplib.gsm

client = smpplib.client.Client("smpp.agiletelecom.com", 2776, allow_unknown_opt_params=True)
client.connect()
client.bind_transceiver(system_id="YOUR_SYSTEM_ID", password="YOUR_PASSWORD")

# Register delivery receipt handler
client.set_message_received_handler(lambda pdu: print(f"DLR received: {pdu.short_message}"))

parts, encoding_flag, msg_type_flag = smpplib.gsm.make_parts("Hello from SMPP!")
for part in parts:
client.send_message(
source_addr_ton=smpplib.consts.SMPP_TON_ALNUM,
source_addr="MySender",
dest_addr_ton=smpplib.consts.SMPP_TON_INTL,
destination_addr="393401234567",
short_message=part,
data_coding=encoding_flag,
registered_delivery=True,
)
client.listen() # blocks, waiting for DLRs

Node.js (smpp)

npm install smpp
const smpp = require("smpp");

const session = smpp.connect(
{ url: "smpp://smpp.agiletelecom.com:2776", auto_enquire_link_period: 30000 },
() => {
session.bind_transceiver({ system_id: "YOUR_SYSTEM_ID", password: "YOUR_PASSWORD" }, (pdu) => {
if (pdu.command_status === 0) {
session.submit_sm({
source_addr: "MySender",
destination_addr: "393401234567",
short_message: "Hello from SMPP!",
registered_delivery: 1,
}, (submitPdu) => {
console.log("Message ID:", submitPdu.message_id);
});
}
});
}
);

session.on("deliver_sm", (pdu) => {
console.log("DLR:", pdu.short_message.message);
session.deliver_sm_resp({ sequence_number: pdu.sequence_number });
});

Java (CloudHopper)

<!-- pom.xml -->
<dependency>
<groupId>com.cloudhopper</groupId>
<artifactId>ch-smpp</artifactId>
<version>5.1.0</version>
</dependency>
import com.cloudhopper.smpp.*;
import com.cloudhopper.smpp.impl.DefaultSmppClient;
import com.cloudhopper.smpp.type.*;

DefaultSmppClient client = new DefaultSmppClient();
SmppSessionConfiguration config = new SmppSessionConfiguration();
config.setHost("smpp.agiletelecom.com");
config.setPort(2776);
config.setSystemId("YOUR_SYSTEM_ID");
config.setPassword("YOUR_PASSWORD");
config.setType(SmppBindType.TRANSCEIVER);

SmppSession session = client.bind(config, new DefaultSmppSessionHandler() {
@Override
public PduResponse firePduRequestReceived(PduRequest req) {
if (req instanceof DeliverSm) {
System.out.println("DLR: " + new String(((DeliverSm) req).getShortMessage()));
}
return req.createResponse();
}
});

SubmitSm submit = new SubmitSm();
submit.setSourceAddress(new Address((byte) 0x05, (byte) 0x00, "MySender"));
submit.setDestAddress(new Address((byte) 0x01, (byte) 0x01, "393401234567"));
submit.setShortMessage("Hello from SMPP!".getBytes());
submit.setRegisteredDelivery((byte) 1);
session.submit(submit, 10000);

PHP (php-smpp)

composer require alexandr-mironov/php-smpp
<?php
require 'vendor/autoload.php';

use smpp\{Client, SMPP, transport\Socket};

$transport = new Socket(["smpp.agiletelecom.com"], 2776);
$transport->setRecvTimeout(30000);
$smpp = new Client($transport);

$transport->open();
$smpp->bindTransceiver("YOUR_SYSTEM_ID", "YOUR_PASSWORD");

$message = "Hello from SMPP!";
$from = new \smpp\Address("MySender", SMPP::TON_ALPHANUMERIC);
$to = new \smpp\Address("393401234567", SMPP::TON_INTERNATIONAL, SMPP::NPI_E164);

$messageId = $smpp->sendSMS($from, $to, $message);
echo "Message ID: {$messageId}\n";

$smpp->close();

Go (go-smpp)

go get github.com/fiorix/go-smpp
package main

import (
"fmt"
"github.com/fiorix/go-smpp/smpp"
"github.com/fiorix/go-smpp/smpp/pdu/pdufield"
)

func main() {
tx := &smpp.Transceiver{
Addr: "smpp.agiletelecom.com:2776",
User: "YOUR_SYSTEM_ID",
Passwd: "YOUR_PASSWORD",
Handler: smpp.HandlerFunc(func(p smpp.Pdu) {
fmt.Println("DLR received:", p.FieldList())
}),
}
conn := tx.Bind()
defer tx.Close()

<-conn // wait for connection

sm, err := tx.Submit(&smpp.ShortMessage{
Src: "MySender",
Dst: "393401234567",
Text: pdufield.Raw("Hello from SMPP!"),
Register: pdufield.DeliverySetting(1),
})
if err != nil {
panic(err)
}
fmt.Println("Message ID:", sm.RespID())
}

C# (.NET)

dotnet add package JamaaTech.SMPP.Net.Lib
using JamaaTech.Smpp.Net.Client;
using JamaaTech.Smpp.Net.Lib;

var client = new SmppClient();
client.Properties.Host = "smpp.agiletelecom.com";
client.Properties.Port = 2776;
client.Properties.SystemID = "YOUR_SYSTEM_ID";
client.Properties.Password = "YOUR_PASSWORD";
client.Properties.DefaultEncoding = DataCoding.UCS2;

client.MessageDelivered += (sender, args) =>
Console.WriteLine($"DLR: {args.ShortMessage.MessageId}");

client.Start();

var message = new TextMessage
{
SourceAddress = "MySender",
DestinationAddress = "393401234567",
Text = "Hello from SMPP!",
RegisterDeliveryNotification = true
};
client.SendMessage(message);

Ruby (ruby-smpp)

gem install ruby-smpp
require 'smpp'

config = {
host: "smpp.agiletelecom.com",
port: 2776,
system_id: "YOUR_SYSTEM_ID",
password: "YOUR_PASSWORD",
system_type: "",
source_ton: 5,
source_npi: 0,
}

EventMachine.run do
trx = Smpp::Transceiver.new(config, self)

trx.send_mt("MySender", "393401234567", "Hello from SMPP!")

trx.on_delivery_report do |dr|
puts "DLR received: #{dr}"
end
end

Codici di errore

Errori di bind e autenticazione

CodiceNomeDescrizione
1ESME_RINVMSGLENLunghezza del messaggio non valida
4ESME_RINVNUMRANGEIntervallo numerico non valido
5ESME_RALYBNDGià connesso (bound)
8ESME_RSYSERRErrore di sistema
10ESME_RINVSRCADRIndirizzo sorgente non valido
11ESME_RINVDSTADRIndirizzo destinazione non valido
13ESME_RINVBNDSTSStato di bind non valido
21ESME_RINVSCHEDOrario di consegna programmata non valido
69ESME_RPROHIBITEDESME non autorizzato a utilizzare la funzionalità specificata
88ESME_RTHROTTLEDErrore di throttling: troppe richieste
97ESME_RINVDCSSchema di codifica dati non valido
98ESME_RINVSRCADDRSUBUNITSottounità indirizzo sorgente non valida
259VENDOR_SPECIFIC_259Errore di autenticazione specifico del vendor
1026VENDOR_SPECIFIC_1026Errore di bind specifico del vendor

Errori di stato della consegna

Errori HLR

CodiceDescrizione
201Abbonato sconosciuto
202Teleservizio non provisionato
203Chiamata bloccata
204Abbonato assente (HLR)
205Abbonato assente (MSC)
206Abbonato non identificato
207Roaming non consentito
208Abbonato illegale
209Servizio bearer non provisionato
210Non consentito per l'abbonato
211Apparecchiatura illegale (IMEI in blacklist)
212Violazione di inoltro
213Rifiuto CUG
214Operazione SS illegale
215SS non disponibile
350Errore di sistema HLR

Errori MSC

CodiceDescrizione
401Consegna SM fallita
402Lista di attesa messaggi piena
403Errore di sistema (MSC)
404Dati mancanti
405Valore dati imprevisto
406Utente occupato
407Abbonato assente
408Timeout di consegna
409Congestione SC
410Funzionalità non supportata
411Nessuna consegna SME
412Messaggio annullato
413Indirizzo SC non valido
414Messaggio illegale
415Non abbonato SC
416USSD occupato
417Errore di codifica dati
418Classe messaggio non supportata
419Messaggio duplicato
550Errore di sistema MSC

Errori SMSC

CodiceDescrizione
615Scaduto (TTL del messaggio superato)
616Eliminato dall'operatore
617In coda (ancora in attesa)
618Non recapitabile

Altri errori

CodiceDescrizione
806Errore di portabilità del numero
901Rifiutato dal filtro
902Destinazione in blacklist
903Contenuto filtrato
904Loop rilevato

Sender ID

TipoLunghezza massimaEsempioCaso d'uso
Numerico16 caratteri+393401234567Messaggistica bidirezionale, risposte attese
Alfanumerico11 caratteriMyBrandMarketing, notifiche, messaggistica unidirezionale

:::caution Regolamento AGCOM In Italia, i sender ID alfanumerici sono soggetti al regolamento AGCOM 42/13/CIR. Il tuo sender ID deve essere pre-registrato e approvato prima dell'utilizzo. Contatta il supporto per la registrazione. :::


Tracciamento dei messaggi

Ogni messaggio inviato riceve un message ID univoco in formato UUID:

AGILE-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX

I timestamp delle ricevute di consegna seguono il formato:

yyMMddHHmmss

Esempio: 240315143022 = 15 marzo 2024 alle 14:30:22


Sicurezza: IP Binding

:::warning Whitelist IP Tutte le connessioni SMPP richiedono la whitelist degli IP. I tuoi indirizzi IP sorgente devono essere registrati presso Agile Telecom prima di poter stabilire una connessione. Contatta il supporto per aggiungere o aggiornare i tuoi IP autorizzati.

Le connessioni da IP non autorizzati verranno silenziosamente rifiutate. :::


FAQ

TX vs RX vs TRX: quale scegliere?

Utilizza TRX (Transceiver) a meno che tu non abbia un motivo specifico per separare i percorsi di invio e ricezione. TRX semplifica la tua integrazione gestendo entrambe le direzioni su una singola connessione.

Come ricevo i report di consegna?

Effettua il bind in modalità RX o TRX. I report di consegna arrivano come PDU DELIVER_SM con il campo esm_class impostato per indicare una ricevuta di consegna. Analizza il campo short_message per estrarre lo stato, il message ID e i timestamp.

Qual è il limite di throughput?

Il throughput predefinito è di 100 messaggi/secondo per account. Se hai bisogno di un throughput più elevato, contatta il tuo account manager per discutere gli aggiornamenti di capacità.