Using Twilio SendGrid To Send Emails from Python Django Applications

December 20, 2019
Written by

Using Twilio SendGrid to Send Emails from Python Django Applications

Deciding how to add email sending capabilities to a web application is always difficult. Do you go through the trouble of setting up and maintaining your own email server, or do you opt for a third-party email service? While the answer is dependent on a number of variables such as volume of emails, your hosting platform and your budget, the tendency is often to favor the simplicity offered by a dedicated email service.

In this short tutorial you’ll learn how to configure a Python application based on the Django web framework to send emails using the Twilio SendGrid service.

Tutorial Requirements

To follow this tutorial you need the following items:

  • Python 3 — If your operating system does not provide a Python 3 interpreter, you can go to python.org to download an installer.
  • A Twilio SendGrid account — If you are new to Twilio Sendgrid you can create a free account, which allows you to send 100 emails per day forever.

SendGrid Configuration

Before you can send email through SendGrid, you have to create an API key that you will use to authenticate with the service. Log in to your SendGrid account, then click on the left sidebar, select Settings and then API Keys. Finally click the “Create API Key”.

Create API Key screenshot

You need to give your API key a friendly name. For this tutorial I chose the name Django. I selected “Full Access” for permissions, which gives the key the ability to perform all the necessary email sending functions. If you prefer to create a key that has very specific permissions, then select “Restricted Access” and configure your access as needed.

When you click the “Create & View” button you will be presented with your key. This key will never be shown again, so you need to click on it to copy it to the clipboard, and then paste it in a secure document so that you can use it later. If you lose your key, you will need to generate a brand new one. Once you have saved your key, you can click the “Done” button.

Creating a Python Environment

Now we are ready to see how to send an email in the context of a Django application. We’ll begin by making a new directory on your computer called twilio-sendgrid-tests or similar, then creating a new Python virtual environment in it.

For Mac and Unix users, the commands are:

mkdir twilio-sendgrid-tests
cd twilio-sendgrid-tests
python3 -m venv venv
source venv/bin/activate

For Windows users, open a Command Prompt or PowerShell window and use the following commands:

md twilio-sendgrid-tests
cd twilio-sendgrid-tests
python -m venv venv
venv\Scripts\activate

If the Python virtual environment was created and activated successfully your prompt should have been modified with a (venv) prefix.

Now you can install django and python-dotenv in your virtual environment:

(venv) $ pip install django python-dotenv

Creating a Django Application

Let’s create a starter Django application and then set our current directory to it. I’m going to call it emails, but you can use any name you like for it:

(venv) $ django-admin startproject emails
(venv) $ cd emails

The good news is that Twilio SendGrid offers an SMTP interface for sending emails, which Django fully supports. To configure Django to send emails through SendGrid, add the following variables at the bottom of your settings.py file. In my case, this file is located in emails/settings.py, but your location will be different if you used a different name for your Django application.

# Twilio SendGrid
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = os.environ.get('SENDGRID_API_KEY')

You can see above that to use SendGrid’s SMTP interface you must have the following settings:

  • The mail server should be smtp.sendgrid.net.
  • The mail port should be 587 (port 25 is also supported, if you prefer)
  • TLS must be enabled
  • Authentication is required. For the username you must use apikey (this is the same for all SendGrid accounts). The password is the SendGrid API key that you created in the previous section.

Since it is a bad practice to include secrets in your source code, we import the SendGrid API key from an environment variable called SENDGRID_API_KEY. To avoid having to set this environment variable, we can store it in a .env file. Create a file named .env (note the leading dot) in the top-level of your Django application and define the variable in it:

SENDGRID_API_KEY='<your-sendgrid-api-key>'

Django knows nothing of this .env file, so it needs to be told to import environment variables from it when the application starts. This can be done at the top of that same settings.py file:

from dotenv import load_dotenv
load_dotenv()

Sending an Email

Now you are going to send yourself a test email. Start a Python shell as follows:

(venv) $ python manage.py shell

Note that we started the Python shell with the manage.py shell command, as this will ensure that the Django application is created and the settings we added above are imported.

Once in the shell, we can use the send_mail() function from Django to send a test email:

from django.core.mail import send_mail
send_mail('Example Subject', 'Example message', 'from@example.com', ['to@example.com'])

The arguments in the send_mail() function call above are the email subject, the body, the sender, and finally a list of recipients. Try it in your own shell session by replacing the sender and recipient with some of your own email addresses.

If everything goes well, an email should arrive at your inbox a few seconds later.

Received email screenshot

Now that you have confirmed that the application sends simple emails, you are ready to code your Django application using the send_mail() function as above or even with the lower-level EmailMessage class. All the email features provided by the Django framework are now enabled to work through Twilio SendGrid!

If Your Emails Aren’t Delivered

My hope is that using the send_email() function above you are successful in sending emails. There is a chance, however, that your emails will fail to be delivered. Since SendGrid sends emails asynchronously, most delivery errors occur after the sender completes their side of the transaction, so your application will not have any indication that there has been an error. If this happens, then it is likely that the email was rejected by the recipient’s email server.

If you experience this when you try to send an email as shown in the previous section, you can use the Twilio SendGrid console to help you debug what happened. From the SendGrid dashboard, click on Activity, and then on the “Show All Activity” button in the middle of the page. This will show you a list of all the emails that you attempted to send, indicating if they were successfully delivered or not.

Email activity page screenshot

You can see in the picture above that an email that I accidentally sent to an example.com address failed to be delivered. For any emails that were not delivered, you can click on the email to see detailed information, including any error responses sent by the recipient’s email server.

Conclusion

Twilio SendGrid is an extremely simple service that integrates nicely into the standard Django email sending workflow. I hope you decide to give Twilio SendGrid a try!

Additional Resources

The following links will help you expand your knowledge of Django's email support and Twilio SendGrid:

  • Sending Email (Django official documentation): This is the best resource if you want to learn about all the email features provided by Django, such as sending HTML formatted emails or including file attachments.
  • TwilioQuest: This fun and educational game includes several missions designed around the different services and APIs. Play the SendGrid mission to familiarize yourself with the capabilities of this service.

Miguel Grinberg is a Python Developer for Technical Content at Twilio. Reach out to him at mgrinberg [at] twilio.com if you have a cool Python project you’d like to share on the Twilio blog!