This project exposes a RESTful API to send SMS messages using the SMPP (Short Message Peer-to-Peer) protocol.
It also includes a web UI for easy usage.
There's a live demo here.
You'll need an SMSC server to try it out (you can find free test servers by searching for smsc test server).
Note: On the live demo you can send at most 50 messages in bulk form (there's a hard-coded cap).
The backend is a RESTful API built using django and django REST framework, and the SMPP functionality is provided by python-smpplib.
phonenumbers is used to validate the source and destination addresses.
The /api/bind endpoint takes a JSON request of two types:
-
connectrequestThis request has the following structure, with the types specified:
{ "command":"connect", "systemId": string, "hostname": string, "password": string, "port": int, "systemType": string, "useSSL": bool, "reconnect": bool, }The fields
command,systemId,hostname,password, andsystemTypeare required, the rest are optional and will be set to default values if not provided.The API sends a response with an HTTP status code and, if the request was successful, a
sessionidcookie.Note:
reconnectis currently not implemented. -
disconnectrequestThis request is simply:
{ "command":"disconnect", }Note: This request requires a valid
sessionidcookie to be sent (the one that was provided on the response to aconnectrequest).
In this case there's only one type of request, with the types specified:
{
"messageText": string,
"sourceAddr": string,
"sourceAddrTON": int,
"sourceAddrNPI": int,
"destAddr": string,
"destAddrTON": int,
"destAddrNPI": int,
"serviceType": string,
"bulkSubmitEnable": bool,
"bulkSubmitTimes": int,
"dataCoding": int,
"submitMode": string,
}
The fields messageText, sourceAddr, and destAddr are required, the rest are optional and will be set to default
values if not provided.
Note: sourceAddr and destAddr must be international phone numbers (ie they must include the country code).
Note 2: Currently, the only submiteMode implemented is shortMessage.
The user can get the SMPP logs from the server by connecting through websockets to ws://<your-site>/ws/api/. The JSON
sent by the server includes the log message generated by python-smpplib and the bound state of the user:
{
"logMessage": string,
"isBound": bool,
}
This functionality is provided by django channels using a Redis backend.
The UI is made on ReactJS using MUI (ex Material-UI).
Form validation is done with React Hook Form and the websocket connection is handled with React useWebSocket.
Google's libphonenumber is used to validate the source and destination addresses.
There are scripts included to provision, build, and deploy this project on Google Cloud Platform (GCP), using Google Kubernetes Engine (GKE) to host the API and a Storage Bucket to hold the static content (the React frontend). This is done by running a daphne ASGI server, using Docker containers and kubernetes for deployment.
Note: This was tested on a freshly-installed Ubuntu 20.04 LTS.
Clone this repo and cd into it:
git clone https://github.com/m4rtinpf/smpp-client
cd smpp-client
Create a file called config with this content (filling out the missing values):
DJANGO_SECRET_KEY=
GCP_PROJECT_ID=
GCP_MEDIA_BUCKET=
# Cloud Storage bucket gsutil URI
STATIC_GSUTIL=gs://"$GCP_PROJECT_ID"_"$GCP_MEDIA_BUCKET"/static
# Cloud Storage bucket public URL
STATIC_URL=http://storage.googleapis.com/"$GCP_PROJECT_ID"_"$GCP_MEDIA_BUCKET"/static/
# Docker container URL
DOCKER_CONTAINER=gcr.io/"$GCP_PROJECT_ID"/polls
# Static files path
STATIC_PATH=./frontend/static
Note: the GCP_PROJECT_ID must be globally unique (
go here for more info on project IDs;
and here for bucket names).
Run the (semi-)automated script:
bash ./provision.sh
After the pods are ready, you can get the public IP address of the load balancer by running kubectl get services polls
and noting the EXTERNAL-IP.
Run:
bash ./build.sh
Run:
bash ./deploy.sh
And it's done! You can look at your site by going to the IP address from the provisioning step.