Adding MMS Support To The Twilio.org Rapid Response Kit

October 23, 2014
Written by
Paul Hallett
Contributor
Opinions expressed by Twilio contributors are their own

twilio_disaster_relief_dog

Communication is a huge part of our lives and it is never more important than during times of need. When something bad happens or you need to make an important change in your life, communication is the medium with which you begin that process. We developed Rapid Response Kit to facilitate that communication during those times by providing a set of tools that could be downloaded and setup to provide some of most useful SMS and voice features one might want to use.

Sometimes though, SMS and voice calling isn’t the right tool for a job. For example, it might be easier to share a photo of a map rather than describe the directions. I hate to be clichéd but as the old adage says, “A picture is worth a thousand words”.

While looking at Rapid Response Kit, we had to ask ourselves “What value could MMS provide to people in emergency situations?” We already knew that updating a few existing tools to include MMS was useful, but building something new was paramount in our minds.  When something bad happens, communities create noticeboards with photos of missing family and loved ones, or pictures of useful information. Building a modern version of this would allow anyone with a phone to participate, so we decided to build a new tool called Noticeboard.

Let’s run through how we added MMS support to the Broadcast and Auto-Respond tools in Rapid Response Kit. We’ll also look a key feature of the new Noticeboard tool that uses inbound Twilio Webhook requests to extract media from the MMS messages.

What we’ll learn:

 

  • How to add MMS  to an existing Twilio REST API Request.
  • How to add MMS  to an existing TwiML document.
  • How to receive incoming MMS media from a Twilio webhook.
How to add MMS to an existing Twilio REST API Request.

 

The Broadcast tool allows users to quickly fire out SMS messages or voice calls to a list of numbers. This tool is one of the most useful tools in Rapid Response Kit due to the huge number of use cases it covers, for example: sending out “I’m okay!” phone calls to family and friends, or sending out the address of a meeting place in an SMS.

Wouldn’t it be great to able able to send out a picture as part of the broadcasted message? This would enable people to do new things such as sending out a picture of a loved one who is lost, or providing an image of a map for directions to a shelter.

To update the Broadcast app to support MMS, a new “Picture” field was added that takes a full path URL to an image on the web. A design decision to make this form field optional meant we needed to write some extra application logic to discover what is written in this field, most importantly, to make sure a real URL was being entered. The code needed to do this is pretty simple and can be seen on the highlighted line below. The full source can be seen on Github:

 


@app.route('/broadcast', methods=['POST'])
def do_broadcast():
    numbers = parse_numbers(request.form.get('numbers', ''))
    twiml = "<Response><Say>{}</Say></Response>"
    url = echo_twimlet(twiml.format(request.form.get('message', '')))
    media = check_is_valid_url(request.form.get('media', ''))

    client = twilio()

The function check_is_valid_url() wraps Python’s standard urlparse function to check that the submitted string is a URL. The string is considered a valid URL if the parsed scheme is  ‘http’ or ‘https’:

def check_is_valid_url(url):
    o = urlparse(url)
    if o.scheme in ['https', 'http']:
        return o.geturl()
    return None

 

If the string is not a URL, media becomes a type of None, an empty variable with unique properties. Now that we can get a valid URL, an extra parameter is added to the the REST API call creating a message:

 


client.messages.create(
    to=number,
    from_=request.form.get('twilio_number', None),
    body=request.form.get('message', ''),
    media_url=media,
)

 

It is good to explain what this will do. If the media value is a valid URL, then the string will contain the full path to an image. The Twilio Python Helper Library will then create a HTTP Request to Twilio asking it to send an MMS message to the to number. If however, the value is None, then the helper library will not generate an HTTP Request for MMS, but for SMS instead.

With that done (as well as adding in the new HTML form element) we’ve added optional MMS support to a piece of functionality that could only provide SMS, and all it took was a few extra lines of backend code.

How to add MMS support to an existing TwiML document

 

The Auto-Respond tool in Rapid Response Kit uses user provided input to generate TwiML that will automatically respond with whatever you want when your Twilio phone number is called or texted.  For example, a message with instructions on how to contact you, or detailed instructions on the best actions to take in a disaster scenario.

Adding MMS support to this tool is slightly different, as we’re not using the REST API anymore, we’re using TwiML instead. Once again we want to provide MMS support as an option, not as a requirement, so we’ll need to handle the optionality of the media value being empty. How can we do this and build the correct TwiML?

 

The input data is supplied by the HTML form above, so the first we’ll need to do is get the input values from that form and then use the the Response builder in the Python helper library to create our response, like so:

 

twiml_response = Response()
sms_message = request.form.get('body', '')
mms_url = check_is_valid_url(request.form.get('media', ''))
if mms_url:
    twiml_response.message(sms_message).media(mms_url)
else:
    twiml_response.message(sms_message)
return twiml_response.toxml()

You can see the entire code for this on Github here, but the bit we care about is written above. What exactly is this code doing? On line 1 a new Response object is instantiated as the twiml_response variable. Line 2 and 3 collect the body and media values from the form submission. We’re using the same check_is_valid_url function as before to determine that the string given in the media input is a valid URL.

We then compare the results of the mms_url variable to see if it has any content in it, and if it does (which means we have a valid URL) we use the twiml_response object to generate a message with media:

 


<?xml version=”1.0” encoding=”UTF-8”?>
<Response>
  <Message>
    <Body>I am the night!</Body>
    <Media>http://i.imgur.com/sTWG4MN.jpg</Media>
  <Message>
</Response>

If the mms_url is None (AKA – empty) then we just generate a standard message:

<?xml version=”1.0” encoding=”UTF-8”?>
<Response>
  <Message>
    <Body>I am the night!</Body>
  </Message>
</Response>

 

Finally, we’re returning an xml version of the twiml_response object using the toxml() method.

There you have it: MMS support can be added to an existing TwiML document with just a few tiny changes.

How to receive incoming MMS media from a Twilio webhook

 

Finally, lets look at Noticeboard, the newest tool we’ve add to Rapid Response Kit. It acts as a virtual noticeboard for people to post pictures of missing family, loved ones, or items. It can even be used just to share any media content with an audience. By using MMS as the medium for sharing these images, anyone with a phone is able to participate.

Part of the functionality of Noticeboard is to receive Twilio webhook requests whenever a new MMS message is sent to the Twilio number being used for the tool. If you’re familiar with handling these webhook requests, you probably already know that data about the inbound SMS or voice call is packaged up in the POST parameters of the HTTP request you receive. The same also applies for the MMS media that is delivered to you.

If media is being sent to us from a Twilio webhook request, we will see the following extra POST parameters in the incoming HTTP request:

In our code, we only want to get the first image from the incoming message so we will check to see if the parameter MediaUrl0 is included in the request.  If you wanted to share multiple images, you could loop through all of the included MediaUrl{N} parameters using the NumMedia parameter to know how many times to loop.

Let’s see how this was programmed in Rapid Response Kit. Feel free to check out the the full code on Github.

 

@app.route('/noticeboard/post', methods=['POST'])
def handle_noticeboard_inbound():

    pusher_key = app.config.get('PUSHER_KEY', None)
    pusher_secret = app.config.get('PUSHER_SECRET', None)
    pusher_app_id = app.config.get('PUSHER_APP_ID', None)

    p = Pusher(pusher_app_id, pusher_key, pusher_secret)

    p['rrk_noticeboard_live'].trigger(
        'new_message',
        {
            'image': request.values.get('MediaUrl0', None),
            'body': request.values.get('Body', None),
            'from': request.values.get('From', None)
        }
    )

    to = request.values.get('To','')
    r = Response()
    r.message(
        '''Thank you, your image has been posted
        to {0}noticeboard/live/{1}'''.format(request.url_root, to))

    return r.toxml()

To accept incoming MMS messages we created the handle_noticeboard_inbound() function which is linked to the route ‘/noticeboard/post’. This route receives the HTTP requests Twilio makes each time a user sends a message to our phone number.

When a request is made to this route, the function extracts the media URL, message body and the phone number of the sender from the request and uses Pusher to send that data to a web page that displays the images. Finally we create a simple TwiML message response with a link to the webpage and return it back to Twilio, who then passes the message back to the user as an SMS.

To test this new functionality I used hurl.it, a website that allows me to simulate the HTTP requests made by Twilio to my test server. Here is an example of the parameters I set up in hurl.it:

 

Voila: thats all it took to create a new tool in the Rapid Response Kit that uses inbound MMS messaging to accept photos and display them on a web page.

What we’ve just learned

 

Rapid Response Kit is a great set of tools for enabling communications when it is needed the most. Adding MMS messaging to the collection of communication mediums it provides will help to bring more value to the tool kit. The multiple methods of updating Rapid Response Kit that we covered are also some of the most common ways a Twilio application can be updated to support MMS:

  • Sending MMS messages with Twilio REST API calls.
  • Creating MMS message replies with TwiML.
  • Handling MMS in inbound Twilio webhook requests.

We used our Rapid Response Kit tool as an example of how this can be done with Python, but adding MMS to your Twilio application in any language should take almost no time at all, after all – we’re just handling HTTP requests and responses. Don’t forget to download the Rapid Response Kit and give it a whirl, it’s a great example of some of the tools that can be built with Twilio and it takes two minutes to install.