Sending SMSes with Twilio and Python

Somebody recently asked me if I knew of a good way to send text messages to a list of phone numbers on a regular schedule. They had a few people who needed daily reminders about a task for a week or so and wanted to automate the process. I've been meaning to play with Twilio for a while now and this seemed like a good place to start.

After deciding to give Twilio a try the process went something like this:

  1. Set up a Twilio account.
  2. Download their Python helper module.
  3. Look through the module's source code and the SMS quickstart guide.
  4. Write a script to send out messages.

Here's what I came up with to test things out, broken into smaller chunks.

import twilio

# Twilio REST API version
API_VERSION = '2010-04-01'

# Twilio AccountSid and AuthToken
ACCOUNT_SID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ACCOUNT_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'

# Outgoing Caller ID
CALLER_ID = '4155992671';

Right up at the top we import Twilio's helper module - you'll need to have it installed somewhere on your Python path for this to work. We'll use it a little later on to handle authenticating our Twilio account and sending requests to their server. After that we're just declaring which API version we're using, our account credentials and the phone number we want to send messages from. If you've bought a number from Twilio already then use that as your CALLER_ID, if you haven't got around to it yet then use the developer sandbox number. You'll need all of this later on to construct your request.

# Twilio SMS resource path
SMS_PATH = '/%s/Accounts/%s/SMS/Messages' % (API_VERSION, ACCOUNT_SID)

SMS_PATH is the URL where we need to send our request. In full, you'll be POSTing to https://api.twilio.com/[API_VERSION]/Accounts/[ACCOUNT_SID]/SMS/Messages but the helper module will insert the first piece for you.

# Create a Twilio REST account object
account = twilio.Account(ACCOUNT_SID, ACCOUNT_TOKEN)

We're finally making use of the helper module. Account is a class that provides methods for making REST requests to Twilio's API. When you create an instance of Account you provide your account credentials so that the helper module can handle authorisation for you.

# People we'll be messaging
people = {'John': '+11234567890',
          'Mary': '+11234567891',
         }

Easy enough. Just a dictionary of names and contact numbers for the people we want to SMS. You could just use a list of phone numbers but I want to personalise the messages slightly so names are necessary.

# Send a message to everyone in our people dict
for name, number in people.items():
    # Construct our message
    message = 'Hello %s please remember to check your mail today.' % (name)
    # Send an SMS with a POST
    account.request(path=SMS_PATH,
                    method='POST',
                    vars={'To': number,
                          'From': CALLER_ID,
                          'Body': message,
                          })

Finally, the meat of our little script. It really is this easy - put together a personalised message for each person and send it using our account object's request method. In this case Account.request() takes three arguments: The path to Twilio's SMS URL, an HTTP method and a dictionary containing our message data.

If you're sending from the developer sandbox phone number then you can only send to numbers that you've validated as outgoing numbers through Twilio. If you try to send to a number you haven't validated you'll get a 400: Bad Request error.

The whole point of all this was to automate the process of sending reminder messages, so I want to run my script as a cron job. You could do that with what we have so far but if it's going to be running unattended then some basic logging is a good idea. Here's an improved version, which will log sent messages or errors so that you can check up on it.