Getting Started with Python, Bottle and Twilio SMS / MMS

August 05, 2016
Written by
Matt Makai
Twilion

Python, Bottle and Twilio SMS / MMS

Python applications can easily send and respond to text and picture messages using a web API. Outbound messages are sent through Twilio’s RESTful API, while inbound messages are received by your application when Twilio makes an HTTP POST request. We will walk through how to set up a Bottle web app to handle both SMS and MMS messages.

Tools We Need

You’ll need Python 2 or 3. Although, Python 3 is recommended by the developer community for all new applications. Install one of those two Python versions on your system. We also need the following:

All the code for this tutorial can be found in an open source GitHub repository.
If you need help configuring your development environment before we dive into writing our application, check out this handy guide on setting up Python 3, Bottle and Gunicorn on Ubuntu 16.04 LTS.

Installing Application Dependencies

Our application will use the Twilio Python helper code library to send and reply to messages. Bottle and the helper library are installable from PyPI into a virtual environment. Open your terminal and use the virtualenv command to create a new virtual environment:

virtualenv bottlemessages

Invoke the virtualenv’s activate script, which makes it the active Python installation for our shell. Note that you need to do this in every terminal window that you want this virtualenv to be used.

source bottlemessages/bin/activate

The command prompt will change after activation to the name of the virtual environment within parentheses, like this example shown here:

bottle-virtualenv.png

Use the pip command to install the Bottle and Twilio Python packages into your virtual environment.

pip install bottle twilio

We installed the required dependencies. Now the Python code that is run with the virtualenv activated will be able to use those packages. It’s time to buy a phone number that we can use to build our Bottle web app that will handle SMS and MMS messages.

Obtain a Phone Number

Head over to the Twilio website and sign up for a free account or sign into your existing Twilio account.

Twilio sign up screen.

Twilio trial accounts allow you to send and receive messages to your own phone number. Trials are great for initial development before your application goes live. Upgrade your account to to send and receive messages to and from any phone number.

If you need a new phone number or want to see the existing numbers you have, go to the manage phone numbers screen via that link or click the “#” on the left Console navigation bar.

Twilio Console left nav phone numbers screen.

With our accounts credentials and a Twilio phone number in hand, we can write some Python code to send outbound messages.

Sending SMS Messages with Bottle

The Bottle web app will have two routes. One route will allow us to test that the app is running. The other route will handle and respond to incoming HTTP POST requests from Twilio. Create a new file named app.py in your in the directory where you want to store this Python project.
Write the following code in the new app.py file.

from bottle import (post, request, response, route, run, )
from twilio.rest import TwilioRestClient

# copy in your Twilio Account SID and Auth Token from Twilio Console
client = TwilioRestClient("account sid", "auth token")

@route('/')
def check_app():
    # returns a simple string stating the app is working
    return "Bottle web app up and running!"


@route('/send-sms/<to_number>/<from_number>/<message_body>/')
def outbound_sms(to_number, from_number, message_body):
    # use the Twilio helper library to send an outbound SMS
    # via the REST API
    client.messages.create(to=to_number, from_=from_number,
                           body=message_body)
    # this response is sent back to the web browser client
    return "SMS sent to " + to_number


if __name__ == '__main__':
    # use the Bottle framework run function to start the development server
    run(host='127.0.0.1', port=5000, debug=True, reloader=True)

The lines starting with # are comments that give explanations for what the code lines below them are executing. Bottle web apps define URL routes with the @route and @post decorators, depending on the type of HTTP request the route should handle, whether a GET or POST, respectively.
We need to grab our account credentials, the Account SID and Auth Token, from the Twilio Console, to instantiate the client object.

account-sid-auth-token.png

We can start up the Bottle development server now that we have our Twilio account credentials plugged into the app.py code. Make sure your virtual environment remains activated so that the application can use the Bottle and Twilio code libraries we installed earlier. Give the Bottle app a try by running it with python app.py.

python-app-py.png

Open a web browser and go to localhost:5000 (or 127.0.0.1:5000). We should see “Bottle web app up and running!” on the screen.
bottle-app-up.png

We can test the SMS sending function via the /send-sms/ URL. For example, try this URL to send the message “About to take a drive down the I-95” from your Twilio number to another phone number (make sure to replace the “from” and “to” numbers in the URL):

http://localhost:5000/send-sms///about to take a drive down the i-95/

A simple success message should tell us that the SMS was sent to the recipient phone number.

send-sms.png

Give it a second for the SMS to arrive and we should see something like the following if you’ve got an iPhone, or the equivalent on an Android:
sms-success.png

We’ve got a skeleton of our Bottle app running that can send outbound SMS. Now we can add some MMS picture messaging into the mix.

Sending MMS Messages

Sending MMS message is very similar to how we just sent SMS, except that we need one more argument for our create_message function. We can specify a media_url with a URL to a picture in .gif, .jpg or .png format to send that as part of our MMS. It’s also possible to send movies and sound clips, which you can read more about in the docs.

Enhance the existing app.py file with the following new highlighted lines.

from bottle import (post, request, response, route, run, )
from twilio import twiml
from twilio.rest import TwilioRestClient


# copy in your Twilio Account SID and Auth Token from Twilio Console
client = TwilioRestClient("account sid", "auth token")

# this URL variable can be dynamic or customized later
MMS_URL = "https://wiki.factorio.com/images/Fast_transport_belt_fulldensity.gif"


@route('/')
def check_app():
    # returns a simple string stating the app is working
    return "Bottle web app up and running!"


@route('/send-sms/<to_number>/<from_number>/<message_body>/')
def outbound_sms(to_number, from_number, message_body):
    # use the Twilio helper library to send an outbound SMS
    # via the REST API
    client.messages.create(to=to_number, from_=from_number,
                           body=message_body)
    # this response is sent back to the web browser client
    return "SMS sent to " + to_number


@route('/send-mms/<to_number>/<from_number>/<message_body>/')
def outbound_mms(to_number, from_number, message_body):
    # uses the Twilio helper library to send an outbound MMS
    # via the REST API
    client.messages.create(to=to_number, from_=from_number,
                           body=message_body, media_url=MMS_URL)
    return "MMS sent to " + to_number


if __name__ == '__main__':
    # use the Bottle framework run function to start the development server
    run(host='127.0.0.1', port=5000, debug=True, reloader=True)

Let’s give our app’s new MMS code a try. Try this URL in the browser, but replace the phone numbers with your Twilio number and the number you want to send the MMS to:

http://localhost:5000/send-mms///my favorite new game/

send-mms.png

Here’s what it looks like when we successfully receive the MMS:

mms-success.png

What if we want to respond to incoming SMS and MMS messages with our Bottle app? There is one issue with our web app running on our local development environment. Twilio cannot send a the HTTP POST request to the web app server. We can fix that issue during development by using a localhost tunneling tool.

Ngrok Localhost Tunneling

Ngrok is a localhost tunneling tool that bridges your local development environment to an external URL. Download and install the Ngrok version that’s appropriate for your operating system.

We can run Ngrok locally and expose our Bottle app that is running on port 5000. Run this command within the directory where the Ngrok executable is located.

./ngrok http 5000

ngrok.jpg

Cool, now we can use the Forwarding URL so Twilio can send POST requests to our application when there is an inbound SMS. Replace the URL in the text box with your own Forwarding URL, like I did in this screenshot.

ngrok-works.jpg

We can now set up Twilio to send a POST request to our application through Ngrok. Go to the manage phone numbers screen and click on the phone number you want to configure for replying to text messages.

Scroll down and look for the “Messaging” header. Change the “A Message Comes in” text box to input the ngrok Forwarding URL plus the “/twilio” route, as shown in the screenshot below.

Paste the ngrok Forwarding URL into the Twilio webhook configuration text box.

Click the “Save” button so that our changes take effect.
Update the app.py file with the following new highlighted function that will handle Twilio’s POST requests when an SMS or MMS is sent to our phone number.

from bottle import (post, request, response, route, run, )
from twilio import twiml
from twilio.rest import TwilioRestClient


# copy in your Twilio Account SID and Auth Token from Twilio Console
client = TwilioRestClient("account sid", "auth token")

# this URL variable can be dynamic or customized later
MMS_URL = "https://wiki.factorio.com/images/Fast_transport_belt_fulldensity.gif"


@route('/')
def check_app():
    # returns a simple string stating the app is working
    return "Bottle web app up and running!"


@route('/send-sms/<to_number>/<from_number>/<message_body>/')
def outbound_sms(to_number, from_number, message_body):
    # use the Twilio helper library to send an outbound SMS
    # via the REST API
    client.messages.create(to=to_number, from_=from_number,
                           body=message_body)
    # this response is sent back to the web browser client
    return "SMS sent to " + to_number


@route('/send-mms/<to_number>/<from_number>/<message_body>/')
def outbound_mms(to_number, from_number, message_body):
    # uses the Twilio helper library to send an outbound MMS
    # via the REST API
    client.messages.create(to=to_number, from_=from_number,
                           body=message_body, media_url=MMS_URL)
    return "MMS sent to " + to_number


@post('/twilio')
def inbound_sms():
    twiml_response = twiml.Response()
    # obtain message body from the request. could also get the "To" and 
    # "From" phone numbers as well from parameters with those names
    inbound_message = request.forms.get("Body")
    response_message = "I don't understand what you meant...need more code!"
    # we can use the incoming message text in a condition statement
    if inbound_message == "Hello":
        response_message = "Well, hello right back at ya!"
    twiml_response.message(response_message)
    # we return back the mimetype because Twilio needs an XML response
    response.content_type = "application/xml"
    return str(twiml_response)


if __name__ == '__main__':
    # use the Bottle framework run function to start the development server
    run(host='127.0.0.1', port=5000, debug=True, reloader=True)

Our application is ready to go – time to give our phone number a try! Send “Hello” or whatever text you want to your phone number. Here is what the result looks like on my iPhone.

sms-response.png

Nice work! This concise Bottle web app is a good start to build more complicated programs.

What’s next?

Awesome, our Bottle application can send and reply to inbound SMS and MMS messages. There’s so much more our application can do. Here are several more in-depth tutorials that’ll help you take the next step towards making your Python applications even more useful:

If you have questions or comments, please contact me via the following channels:

  • Twitter: @mattmakai
  • GitHub: mattmakai
  • Email: makai@twilio.com
  • Twitch (live coding along with other Twilio Developer Evangelists): Twilio channel