Sending MMS with Twilio Programmable SMS, Python and Django

March 13, 2020
Written by
David Fundakowski
Contributor
Opinions expressed by Twilio contributors are their own

Sending MMS with Twilio Programmable SMS, Python and Django

Modern communication through texting includes so much more than simple text messages. People use images, GIFs, audio files, web links, and any other media in messages in order to communicate with each other effectively. Twilio Programmable SMS makes it extremely simple to send basic SMS, but it’s just as simple to send MMS media like GIFs and images.

In this tutorial, you will be setting up a Django project using virtual environments, creating a free Twilio account, provisioning a phone number, and finally, creating an app to respond to inbound SMS with either a GIF, an image, or a basic SMS.

By the end of this tutorial, you will be able to:

  • Set up a free Twilio account
  • Parse inbound SMS content using Twilio Programmable SMS in a Django app
  • Respond to inbound SMS with a GIF, an image, or an SMS depending on the inbound message

mms example use

Tutorial requirements

To follow this tutorial you need the following components:

  • Python 3.6 or newer. If your operating system does not provide a Python interpreter, you can go to python.org to download an installer.
  • A text editor. Visual Studio Code is a great cross-platform option with extremely helpful plugins, linters, and extensions.
  • ngrok. We will use this handy utility to connect the Django application running on your system to a public URL that Twilio can connect to. This public URL will be used to expose your local web server to the public Internet. If you don’t have ngrok installed, you can download a copy for Windows, MacOS or Linux.
  • A smartphone that can send and receive MMS messages
  • A Twilio account. If you are new to Twilio create a free account now. If you use this link to register, you will receive a $10 credit when you upgrade to a paid account.

Configure your free Twilio account

After you set up your free Twilio account using the link in the Tutorial Requirements, you can access the Twilio Console. The first step if you made a free trial account is to provision a phone number by clicking the “Get a Trial Number button”. Follow the prompts after clicking the link to choose your new number.

get a twilio trial number

The Twilio dashboard should now have a phone number aligned to your account.

twilio trial number

If you already have an account, you can use an existing number or navigate to the Phone Numbers section of the Console and provision a new number. Click the ellipsis on the left side of the screen, click Phone Numbers, and then pick a number of your choosing:

twilio console

phone numbers option in twilio console

Create a Python virtual environment

The first step in this tutorial is to make a virtual environment where you will install both Django and the Twilio REST library.

For Linux and MacOS:

$ mkdir MMSMessenger
$ cd MMSMessenger
$ python3 -m venv mmsmessenger-venv
$ source mmsmessenger-venv/bin/activate
(mmsmessenger-venv) $ pip3 install django==2.2 twilio

For Windows users:

$ md MMSMessenger
$ cd MMSMessenger
$ python -m venv mmsmessenger-venv
$ mmsmessenger-venv\Scripts\activate
(mmsmessenger-venv) $ pip install django==2.2 twilio

Start your MMS project

At this point, you are ready to start developing your MMS sending app using Django. With your virtual environment still activated, create your Django project, your MMS app, do an initial model migration, and start a local server:

(mmsmessenger-venv) $ django-admin startproject MMSMessenger .
(mmsmessenger-venv) $ django-admin startapp mms
(mmsmessenger-venv) $ python manage.py migrate
(mmsmessenger-venv) $ python manage.py runserver

Open a browser, navigate to http://127.0.0.1:8000/, and if you see a web page with a success message, you have successfully started your Django project and app!

django app running

Configure your project settings and files

Now that you have a project, an app, and provisioned a Twilio phone number, there are a few things that need to be added to the project in order for it to start sending messages. If you haven’t stopped the local server yet, use Ctrl+C to stop your runserver in your terminal/command prompt.

First, add the mms app to the list of installed apps in the Django project. This list is located in the settings.py file located in the MMSMessenger directory:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'mms.apps.MmsConfig' # new value
]

Next, add ngrok and your localhost to the list of allowed hosts also located in settings.py:

ALLOWED_HOSTS = [
    '.ngrok.io',  # new value
    '127.0.0.1'  # new value
]

Finally, add a blank urls.py file to the mms app directory using your code editor. Your files and the mms app directory should now look like this

mms
│   admin.py
│   apps.py
│   models.py
│   tests.py
│   urls.py
│   views.py
│   __init__.py

Add URL routes and view for MMS handling

At this point in the project, you are ready to start writing the logic to handle inbound SMS to your Twilio number. The goal here is to write a view in the mms app to execute the MMS response code, add that view to a specific URL path, and then add that URL path as a webhook for your Twilio phone number in the Twilio Console. We will be adding the logic incrementally and testing along the way to confirm everything is working.

The first step is to get a basic MMS response up and running that will reply with an image when you send an SMS to your Twilio phone number. Start by writing a basic view in mms/views.py that creates a Messaging Response, adds a text body, a medial URL (in this case, a link to an image), and replies to an inbound SMS:

from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

from twilio.twiml.messaging_response import MessagingResponse

# Create your views here.

@csrf_exempt
def mms_reply(self):

    response = MessagingResponse()
    msg = response.message("Hello world!")
    msg.media("https://i.imgur.com/HLHBnl9.jpeg")

    return HttpResponse(str(response))

Next up is adding URL pattern routes to generate a path to this view. First, add an entry to the URL patterns in the project-level MMSMessenger/urls.py file:

from django.contrib import admin
from django.urls import path, include # new include import

urlpatterns = [
    path('admin/', admin.site.urls),
    path('mms/', include('mms.urls')) # new path
]

Now add a single entry in the new urls.py file in the mms directory that will call the mms_reply view:

from django.urls import path

from .views import mms_reply

urlpatterns = [
    path('', mms_reply, name='mms_reply')
]

Add a webhook to the Twilio phone number

You now have a complete path to the mms_reply view and are just about ready to start sending SMS to your Twilio number. The next steps are to start a local server and then start ngrok to expose your local server to the public Internet. In a terminal or command prompt with your virtual environment activated, start your server:

(mmsmessenger-venv) $ python manage.py runserver

Now open another terminal or command prompt and start ngrok:

$ ngrok http 8000

If ngrok started successfully, the terminal should look like below:

ngrok screenshot

You should now be able to open a browser and navigate to the HTTPS URL listed as Forwarding in the ngrok window, which should give you a “Page not found” error because we are asking for the / URL but the application only implements a view for /mms.

page not found

You can now add a URL to your Twilio number in the UI. From the Twilio Console, click the ellipsis icon on the left side:

twilio console

Then navigate to your Phone Numbers and select your number:

phone numbers option in twilio console

After clicking on your number, scroll down to the Messaging options. In the section labelled “A Message Comes In”, add your ngrok URL and make sure the mms portion of the URL is included. For example, the complete URL would be similar to https://8ff8606c.ngrok.io/mms/, but with a different ngrok subdomain:

configure webhook

Make sure the left side dropdown is set to “Webhook” and the right side one to “HTTP POST”. Click “Save” at the bottom of the screen.

Now, pick up your personal phone, and text something to your Twilio number! If all of the directions were followed, ngrok is running, your local server is running, and your webhook is properly configured, you should be greeted with a “Sent from your Twilio trial account - Hello world!” message and an image generated by your Django app! If you are using a free account, your message will include a “Sent from your Twilio trial account” prefix in the message.

first mms application demo

Add view logic to read inbound SMS

The last step of this tutorial is to add some basic if/else logic in the view to determine what action should happen when you SMS different things to your Twilio number. In this section, you will add logic to read the inbound SMS content, and based on the content, reply with an image, a GIF, and SMS, or an invalid reply/welcome message.

In the views.py file in the mms app, replace the existing mms_reply code with the following code:

@csrf_exempt
def mms_reply(request):
    """
    Parse the inbound sms body and set the messaging response
    based on the replied number
    """
    request_body = request.POST.get('Body')
    response = MessagingResponse()

    media_link = ''
    msg_body = ''

    if request_body=='1':
        msg_body = 'Gotta love a GIF!'
        media_link= 'https://i.imgur.com/BwmtaWS.gif'
    elif request_body=='2':
        msg_body='Enjoy this image!'
        media_link='https://i.imgur.com/zNxhPjp.jpeg'
    elif request_body=='3':
        msg_body='Have a wonderful day'
        media_link=''
    else:
        msg_body="""Invalid Option. Welcome to MMSMessenger
        Reply with 1 to receive a GIF, 2 for an image, or 3 for an SMS!"""

    msg = response.message(str(msg_body))
    if media_link:
        msg.media(media_link)
    
    return HttpResponse(response)

Once you save the updated file, the Django app should automatically recognize the changes and restart the local server. At this point, you have an interactive app that will reply with different kinds of media based on the content of your messages!

final application demo

 

Limitations of Twilio MMS

Twilio Programmable SMS makes MMS messaging extremely simple. However, if you are planning an application that will be using widespread MMS messaging across all carriers and handling more than images and GIFs, it is wise to understand the limitations of MMS on the Twilio platform.

Twilio will automatically format and resize .gif, .jpeg, and .png files based on the destination device capability. It can accept a wide range of additional media types, but they will not be transcoded and modified for the destination device. There are also limits on size and amount of media files when sending MMS from your Twilio number to devices on different carriers.

In addition to types, counts, and size of media, you will need to consider how non-MMS enabled devices, numbers and carriers will handle your message. Twilio uses a resource called MMS Converter to replace your media in the message with a short link to the media instead. This feature needs to be configured and enabled in the Programmable SMS portion of your Console before it can be used.

Accepted Content Types for Media

Size Limits for MMS Media Messages

Getting Started with MMS Converter

Wrap up

Congratulations on making an MMS messaging app in Django using Twilio! Communication today is made up of so much more than simple text messages, and Twilio Programmable SMS makes it so easy to connect with your users and customers using MMS.

For next steps, head over to the Twilio Programmable SMS API docs and look at some other things that can be added to your app! Also, read through the links in the Limitations of Twilio MMS section of this tutorial to learn more about the intricacies of sending MMS with different media types to different carriers.

David Fundakowski is a senior data architect and full stack developer in Kansas City. Reach out through LinkedIn or Twitter if you want to connect!