This demonstration presents three implementations of an SMS echo server using Telnyx's SMS API. The first implementation uses the aiohttp library; the second uses Flask; and the third is built using the standard library's HTTPServer.
The structure of the repository is as follows.
.
├── bin
│ └── demoserver <--- top level script with CLI
├── LICENSE
├── README.md
├── requirements.txt
├── setup.py
└── smsdemo
├── aiohttpserver <--- aiohttp implementation
│ └── __init__.py
├── constants.py <--- shared default constants used by all three
├── flaskserver <--- flask implementation
│ └── __init__.py
├── httpserver <--- http implementation
│ ├── __init__.py
│ └── handler.py
├── __init__.py
├── message.py <--- simple class to manipulates HTTP content
└── util.py <--- shared utility functions for sending and
validation message integrity
This implementation is a straightforward variant of the server example from the quick start guide here.
One POST route is added to the application and any blocking I/O operations such as reading request body and sending a request are handled asynchronously. (If you are not so familiar with asynchronous programming, there are a number of helpful tutorials out there, such as this Asynchronous I/O Walkthrough).
This is yet another straightforward implementation. The echo()
function is decorated with Flask's @app.route decorator. It only
accepts POST requests. The receive and echo functions in this case are
synchronous, i.e. blocking on I/O.
The python http.server is not ideal for this application, for two reasons: (1) You can't easily pass custom parameters, e.g. secret key, to the function that handles your request. (2) You have to do all the manual parsing of the request and en/decoding.
To solve the first problem, you need to wrap a factory function around
the class definition and return the class back to the invoking function,
as demonstrated in smsdemo/httpserver/handler.py. For the second
problem, you just have to be careful with classic Unicode vs bytes
distinction.
- Clone the repository.
- Create a virtual environment (using
virtualenvwrapper):
user@sms-demo:~/sms-demo$ mkvirtualenv -p /usr/bin/python3 sms-demo - Install dependencies:
(sms-demo) user@sms-demo:~/sms-demo$ pip install -r requirements.txt - Install this package under your path:
(sms-demo) user@sms-demo:~/sms-demo$ python setup.py install - Choose an implementation to run:
(sms-demo) user@sms-demo:~/sms-demo$ ./bin/demoserver Usage: demoserver [OPTIONS] COMMAND [ARGS]... Run a sample SMS echo server. The server accepts Telnyx SMS webhook deliveries and sends an echo of the message back to the sender. Options: -h, --host TEXT HTTP server IP. -p, --port INTEGER HTTP server port. -s, --secret TEXT Secret from your SMS messaging profile. [required] --help Show this message and exit. Commands: aiohttp Run the aiohttp-based demo server. flask Run the Flask-based demo server. http Run the HTTPServer-based demo server. (sms-demo) user@sms-demo:~/sms-demo$ ./bin/demoserver -h 0.0.0.0 -p 8089 \ -s MY-SUPER-SECRET-SECRET aiohttp
Please make sure that the -s parameter matches the message profile
secret that is set for your messaging profile in the [Telnyx Portal]
(https://portal.telnyx.com/).
- We recommend setting up a python virtual environment while developing your application, so that your native environment is preserved. You can find more information about virtual environments here.
- Please avoid hard coding your messaging profile secret for sending SMS in the production environment. If your secret is ever compromised, be sure to generate a new one through the Telnyx Portal.
- There are of course many other options for implementing such servers, e.g. by using the Twisted framework. We would love to expand these demo servers and would welcome any contributions.