How to Build a Bulk SMS Service with Django and Twilio

March 09, 2023
Written by
Eme Lekwa
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Mia Adjei
Twilion

How to Build a Bulk SMS Service with Django and Twilio

The importance of SMS messaging to businesses can not be overemphasized. From sending a promotional message or an SMS alert about a change of policy, to sending one-time passwords to authorize transactions, there is so much you can do with SMS messaging.

This article teaches you how to leverage the Twilio SMS API to build a Bulk SMS application with Django. In this tutorial, you will build a Bulk SMS app that allows admin users to send messages to customers as SMS. With this app, you will see the power of the Twilio SMS API using the Django framework.

Takeaways:

In this article, you will learn:

  • How to integrate the Twilio SMS API into a Django project
  • How to send SMS messages using the Twilio Programmable SMS API
  • How to use Redis Queue for queuing of long-running jobs.

Prerequisites

You will need the following in order to fully follow along with this tutorial:

Verify your Python Installation

Django is a Python framework; as such, you need to have Python installed and use it as your development language. To confirm that you have Python installed, run the following command:

python3 --version

If Python is not installed, visit Download Python to install it based on your computer's operating system.

Make sure pip (Package Installer for Python) is also set up on your computer. pip is used for the installation of third-party dependencies. You can verify the installation by running the following command:

pip3 --version

Installing Django

This project makes use of the free and open-source Django framework, a Python web framework designed to fulfill deadlines and adhere to stringent software specifications.

Building web apps is fast with Django; you can create a complete web application from the ground up within a few hours. Thanks to Django, you can avoid many of the stressors that come along with web development, and instead can focus on writing your business logic.

Before installing Django, create a virtual environment. A virtual environment is an isolated Python environment on your computer. This makes it more likely that, although being dependent on the same local machine, your current project's dependencies won't also include those of other projects.

Run the following command to create a new virtual environment:

python3 -m venv env

You must specifically activate the virtual environment after creating it. To do this, run:

source env/bin/activate

With your virtual environment successfully created and activated, proceed by installing Django.

pip install django

Creating the project (SMSserviceproject)

A Django project is a website or application built using the Django framework. It consists of smaller submodules (apps) and configurations. A project can contain multiple apps, depending on the complexity of the website. A Django app is a self-contained set of models and views that can be plugged into a Django project. A project is an entire website, while an app is a small part of the project.

Create a new project called SMSserviceproject by running the following command:

django-admin startproject SMSserviceproject

Since "SMSserviceproject" is merely a variable name, you may give the project any name you choose as long as it is descriptive.

The App (SMSapp)

Next, create a new Django app. To create the app, run the following command:

python manage.py startapp SMSapp

With this, the app is created successfully. Next, add the app to the list of installed apps in SMSserviceproject/settings.py:

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

Test your app to ensure that everything has been installed and configured properly. To perform this operation, run the server with the following command:

python manage.py runserver

If you navigate to http://127.0.0.1:8000/, boom — you will see the image below, showing that Django is successfully installed, and Django is running. Congratulations on creating your first Django app.

Django server running

Integrating Twilio into the project

Twilio is a platform as a service (PaaS) company that offers Cloud communication services. Software engineers can use their services to create applications that can make and receive phone calls as well as send and receive text messages. Their API allows software engineers to easily automate and schedule text messages to remind users on their platform of upcoming events.

If you do not have a Twilio account, sign up for one here: Try Twilio Free.

For this project, you will need to install a few more dependencies — the Twilio Python Helper Library and django-environ. Install them now by running the following command in your activated virtual environment:

pip install twilio django-environ

Now that you have installed the Twilio library in the project, you will need to get your Twilio credentials.

Log in to the Twilio Console. On the dashboard, you will find your Account SID, Auth Token, and Twilio phone number. Take note of these values, as you will need them to configure your Django project:

Account SID, Auth Token, and phone number in Twilio Console

To keep sensitive information such as your Twilio keys hidden, create a .env file in the same directory as SMSserviceproject/settings.py and add your Twilio keys to the .env file as in the example below, replacing the placeholder text with your actual values:

MY_ACCOUNT_SID='XXXXXXXXXXXXXX'
TWILIO_AUTH_TOKEN='XXXXXXXXXXXXXX'
MY_TWILIO_NUMBER='+XXXXXXXXXX'

When entering your Twilio phone number, make sure to use E.164 format.

Next, if you plan to push your code to a GitHub repository, make sure to create a new file called .gitignore to ignore the .env file and keep your private keys safe. Inside the file, add the following line:

.env

Open SMSserviceproject/settings.py in your text editor. Add environ to the imports near the beginning of the file as follows:

from pathlib import Path
import environ

Then, after the ALLOWED_HOSTS line, initialize environ so you will be able to access the keys from the .env file:

ALLOWED_HOSTS = []
env = environ.Env()
environ.Env.read_env()

Now, add the following code to set the environment variables for your Django project. For the purposes of this tutorial, create a hard-coded list of the phone numbers you wish to send bulk SMS to, replacing the placeholder text below. Be sure to enter these phone numbers in E.164 format as well:

TWILIO_ACCOUNT_SID = env("MY_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = env("TWILIO_AUTH_TOKEN")
TWILIO_NUMBER = env("MY_TWILIO_NUMBER")
SMS_BROADCAST_TO_NUMBERS = [
   "+23XXXXXXXXXXX",
   "+23XXXXXXXXXXX", # use the format +1XXXXXXXXXX
 ]

Implementing the SMS Service

Open SMSapp/views.py and enter the following code:

from django.shortcuts import render
from twilio.rest import Client
from django.conf import settings                                                                                                                                                      
from django.http import HttpResponse

# Create your views here.

def broadcast_sms(request):
    message_to_broadcast = ("How are you")
    client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
    for recipient in settings.SMS_BROADCAST_TO_NUMBERS:
        print(recipient)
        if recipient:
            client.messages.create(to=recipient,
                                   from_=settings.TWILIO_NUMBER,
                                   body=message_to_broadcast)
    return HttpResponse("messages sent!" + message_to_broadcast, 200)

Here you define a function called broadcast_sms to send the SMS. This function declares the message and uses the Twilio client to create a new message, passing in the recipient numbers, the message body, and the Twilio phone number.

Next, create a new file in the SMSapp directory called urls.py. In this file, paste the following code:

from django.urls import path                                                                                                                                                        
from . import views

urlpatterns = [
   path(r'broadcast', views.broadcast_sms, name="default"),
]

From the code above, you expose the broadcast endpoint, which calls the broadcast_sms function you added to the view earlier.

Please note: a trial account can only send messages to verified numbers.

You will also need to make a change in SMSserviceproject/urls.py. Open the file and update the code so it matches the following:

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


urlpatterns = [
    path('', include('SMSapp.urls')),
    path('admin/', admin.site.urls),
]

Test that your application works by making the following curl request from a terminal window:

curl http://127.0.0.1:8000/broadcast

If you would rather test in the browser, http://127.0.0.1:8000/broadcast instead.

Once you have done this, your application will send out SMS to each of the phone numbers on the list you made earlier.

Sms Recieved

While the above code works and is fine for sending a small number of messages, but you'll hit rate limits as you increase the number of messages. To solve this problem, you need a task queue to queue sending the messages. Task queuing is necessary when dealing with long-running jobs that would dramatically reduce the performance of an HTTP response. This resource will help you to learn more about task queuing. In this tutorial, you will use Redis Queue for queuing your jobs.

Setting Up Redis Queue

Run the commands below to install Redis on your computer:

wget http://download.redis.io/releases/redis-7.0.9.tar.gz 
tar xzf redis-7.0.9.tar.gz 
cd redis-7.0.9 
make

Having successfully installed Redis on your machine, you need to install Redis Queue — a simple Python library that allows you to queue jobs and process them in the background with workers.

pip install rq rq-scheduler

Applying Redis Queue

Open SMSapp/views.py and replace the code in the file with the following:

from django.shortcuts import render
from twilio.rest import Client
from django.conf import settings                                                                                                                                                    
from django.http import HttpResponse
from datetime import datetime, timedelta
from redis import Redis
from rq import Queue

import os

os.environ['DJANGO_SETTINGS_MODULE'] = 'SMSserviceproject.settings'

q = Queue(connection=Redis())



# Create your views here.


def send_sms(from_, to, body):
   client = Client(settings.TWILIO_ACCOUNT_SID, settings.TWILIO_AUTH_TOKEN)
   client.messages.create(from_=from_, to=to, body=body)

def broadcast_sms(request):
   message_to_broadcast = ("How are you")
   delta = 0

   for recipient in settings.SMS_BROADCAST_TO_NUMBERS:
       print(recipient)
       if recipient:
           q.enqueue_in(timedelta(seconds=delta), send_sms, settings.TWILIO_NUMBER, recipient, message_to_broadcast)
           delta += 15
   return HttpResponse("messages sent!" + message_to_broadcast, 200)

In the above code, you have updated the views.py file to include Redis Queue. Here, you created an instance of a queue to track the jobs to be done and invoked the enqueue_in function to schedule a message to be sent out every 15 seconds.

Testing the application

To test the queuing capabilities, run the Redis server while in the redis-7.0.9 folder with the following command:

src/redis-server

If the Redis server started successfully, you should see log statements like those below.

Redis Server running

Next, open a different terminal window, activate your virtual environment, and start the Redis worker with the command below:

rq worker --with-scheduler

Once you have done this, you should see log statements like the following:

rq-worker running

Next, run your Django server, if it is not already running from earlier:

python3 manage.py runserver

As you when testing the application in a previous step, run the following curl command from a terminal window:

curl http://127.0.0.1:8000/broadcast

Below is an example output from the rqworker tab. The timestamp shows the time before the next scheduled job.

Jobs Executing

Test sending bulk SMS

Conclusion

In this tutorial, you have been able to build a simple bulk SMS application with the power of the Twilio SMS API. You also used Redis Queue to queue the messages, avoiding the rate limits and 429 error responses for making too many concurrent requests to the Twilio API. The entire code base can be found in this GitHub repository.   If you would like to continue developing this project, you can upgrade your account to be able to send SMS to any phone number, as a trial account works with only verified numbers.


Eme Anya Lekwa is a Software Engineer. He is passionate about how technology can be employed to ensure good governance and citizen political engagement. He is a mobile and web developer and a technical writer. He can be reached on LinkedIn.