You want to receive emails of events associated with a Django project and send email to end users.
Set up a default connection to an email server defining
settings.py. If required you can also define
settings.py. You can also set up a direct Django connection to an email service provider like Google Gmail/Google Apps, Amazon Simple Email Service (SES) and SparkPost.
Once you define a connection to an email server you can use one of Django's email shortcut methods to send emails:
mail_managers. To access all functionalites to send email in Django, such as adding attachments, headers, CC and BCC you can use the
There are two main aspects associated with setting up email in a Django project. The first is setting up the connection to an email server and the second is the composition of emails.
Django supports connections to any email server and also offers various options to simulate email server connections. Email simulation is particularly powerful during development and testing where sending out real emails is unnecessary. The set up for an email server in Django is done in
settings.py. Depending on the email server connection, you may need to set up several variables in
settings.py. Table 1 illustrates the various email server options for Django.
|Django email backend||Configuration||Notes|
|For development (|
|Console Email||Sends all email output to the console where Django is running.|
|File Email||Sends all email output to a flat file specified in |
|In memory Email||Sends all email output to an in memory attribute available at |
|Nullify Email||Does nothing with all email output.|
|Python Email Server Simulator|
also needed is the Python command line email server:
|Sends all email output to a Python email server set up via command line. This is similar to the Console Email option, because the Python email server outputs content to the console.|
|For production (|
|SMTP Email Server (Standard)|
|Sends all email output to a SMTP email server.|
|SMTP Email Server (*Secure-TLS)|
|Sends all email output to a secure SMTP (TLS) email server.|
|SMTP Email Server (*Secure-SSL)|
|Sends all email output to a secure SMTP (SSL) email server.|
1If the SMTP email server is running on a network or a different port than the default, adjust |
2In today's email spam infested Internet, nearly all SMTP email servers require authentication to send email. If your SMTP server doesn't require authentication you can ommit
*The terms SSL and TLS are often used interchangeably or in conjunction with each other (TLS/SSL). There are differences though in terms of their underlying protocol. From a Django set up prespecitive, you only need to ensure what type of secure email server you connect to, as they operate differently and on different ports.
Whichever email connection you set up from table 1 in
settings.py is considered a Django project's default and will be used when doing any email related task -- if you don't specify otherwise when defining an email task.
The previous section provided the most generic approach to set up a default connection to an email server in Django. However, with the complexities involved in running email servers in today's world -- namely spam filtering and security issues -- it can be easier and more practical to use a third party service to relay email from a Django project to the outside world. Although you can use the previous section's configurations to connect to any third party email service, there can be certain subtleties to set up configurations to third party email services. In this section I'll provide the Django configuration details for what I consider three of the most popular third party email services.
|You can set up Django local email delivery and configure Exim, Postfix or Sendmail to deliver email to third party providers.|
This section describes how to set up Django to connect directly with third party email providers. Another alternative is to set up Django to deliver email to a locally running email server (i.e. on 127.0.0.1) such as Exim, Postfix or Sendmail, which can then be set up to relay email to a third party email service.
I personally would not recommend this alternative as it adds another component to set up, maintain and worry about. Not to mention this is beyond the scope of Django, as it involves setting up different email servers with third party email services.
Google offers the ability to send out email through Gmail or Google Apps, the last of which is a Gmail version for custom domains (e.g.
coffeehouse.com ). Once you have a Gmail or Google Apps account, you'll need to set up the account's username/password credentials in
settings.py. You will not be able to use Google's email services without hard-coding your account credentials somewhere in your app. If you are weary of hard-coding the username/password credentials in
settings.py, I suggest you create a separate account for this purpose to limit vulnerabilities, look into using multiple environments or configuration files for Django to keep the username/password in a different file or set up a local email server with the credentials as described in the previous sidebar.
Listing 1 illustrates the configuration needed to set up Django to send email via Gmail or Google Apps account.
As you can see in listing 1, the configuration parameters are pretty similar to those described in table 1. This is all you need to set up a default email connection to Gmail or Google Apps in Django.
|Beware of sending too much email with Google|
Because Google's email service is free, it's not designed for relaying too many email messages. If your Django app sends out a couple of email messages every hour you probably won't have a problem, but if your app sends out email messages every second or hundreds of email messages in the span of a few minutes, the account will likely be blocked.
If the account is blocked, you will either need to wait a few hours or manually log into the account (i.e. via a browser) for it to be unblocked. If the account is constantly blocked due to the email volume you send out, you should try another email service provider.
|Google will overwrite the |
Django allows you to set an email's
This means if you send an email message in Django with
SES is another email service offered by AWS which is run by Amazon.com. Unlike Google's email service, SES is a paid service with an average cost of 0.0001 cents per email (10 cents per 1000 emails). The easiest way to set up Django with SES is through the Python library
boto and a custom Django email backend called
Listing 2 illustrates the pip requirements to install
boto which is a library to integrate multiple AWS services using Python and
django-ses which is an open-source project specifically designed to run SES with Django. NOTE: If you are unfamiliar with pip, read the recipe Install Django which explains why pip is a good option to manage Python packages in Django projects.
Once you install the Python packages in listing 2 using pip, you can proceed to configure SES in
settings.py. Listing 3 illustrates the necessary variables to set up Django to use SES.
As you can see in listing 3, the variable
EMAIL_BACKEND is set to the custom class
django_ses.SESBackend which provides all the necessary hooks to connect to SES.
To connect to SES you'll also need to provide the variables
AWS_SECRET_ACCESS_KEY which are access credentials related to your AWS account. See How Do I Get Security Credentials ? for more information on getting these values from an AWS account.
This is all you need to set up a default email connection to Amazon Simple Email Service (SES). There's no need to set up any other variable in
settings.py, such a
EMAIL_HOST_USER, everything is taken care of by the custom email backend.
SparkPost is another third party email service used by large companies like Twitter, Oracle and PayPal. Pricing wise SparkPost is a mix between the two previous services, it's a free service for the first 100,000 emails per month, but after this volume it's a paid service with an average cost of .0002 cents per email (20 cents per next 1000 emails per month) and lower per email rates once you send 1 million emails a month..
The easiest way to set up Django with SparkPost is directly in
settings.py. Listing 4 illustrates the necessary variables to set up Django to use SparkPost.
As you can see in listing 4, the configuration parameters are pretty similar to those described in table 1 for a standard email connection. Just notice that in addition to the
EMAIL_HOST_USER value being
SMTP_Injection -- a SparkPost requirement -- you'll also need to assign a SparkPost API key to the
EMAIL_HOST_PASSWORD. See Create API Keys for more information on how to create and get SparkPost API keys.
Now that you understand various ways to set up an email connection in a Django project, lets explore the actual composition of emails.
There can be many options and steps involved in sending an email. To simplify this process, Django offers four shortcut methods that you can leverage anywhere in an application (e.g. to receive an email notification when a web form is processed or when a critical error occurs). Table 2 illustrates the various email shortcut methods.
|Shortcut method and description||Shortcut method with all arguments*||Argument descriptions and notes|
|Email is sent with a |
|Email is sent with a |
*Method arguments without a default value (e.g. |
If you start to get emails with error messages once a project goes into production (i.e.
To disable this behavior you will either need to clear all values from
Although the previous email shortcut methods can be used under most circumstances, they do not support things like attachments, CC, BCC or other email headers. If you want total control for sending email messages in Django the previous shortcut methods won't work.
Used 'under-the-hood' by the previous Django shortcut methods and offering the utmost flexibility for sending email in Django is the Django
EmailMessage class. The various parameters and methods supported by the
EmailMessage class are described in Table 3
EmailMessageclass parameters and methods
|Parameter and/or method||Description|
|The subject line of the email.|
|The body text as a plain text message.|
|The sender's address. Both email@example.com and Webmaster |
|A list or tuple of recipient addresses.|
|A list or tuple of addresses used as the email BCC header when sending the email.|
|An email backend instance. Use this parameter if you want to use the same connection for multiple messages. If omitted, a new connection is created when send() is called.|
|A list of attachments to put on the message. These can be either email.MIMEBase.MIMEBase instances, or (filename, content, mimetype) triples.|
|A dictionary of extra headers to put on the message. The keys are the header name, values are the header values. It's up to the caller to ensure header names and values are in the correct format for an email message. The corresponding attribute is extra_headers.|
|A list or tuple of recipient addresses used in the the email CC header when sending the email.|
|Sends the message. If a connection was specified when the email was constructed, that connection will be used. Otherwise, an instance of the default backend will be instantiated and used. If the keyword argument |
|Useful when extending the |
|Useful when extending the |
|Creates a new file attachment and adds it to the message. There are two ways to call attach(). You can pass it a single argument that is an |
|Creates a new attachment using a file from the filesystem. It can be called with the path of the file to attach (e.g.|
With a clear idea of the functionalities provided by the
EmailMessage classs in table 3, lets take a look at some typical cases where you would use the
EmailMessage class to send email.
Listing 5 provides a basic email example that uses options like CC, BCC and the
Reply-To header which aren't support via the Django email shortcuts from the last section.
As you can see in listing 5, we create an
EmailMessage instance specifying the different class parameters. Once this is done, we simply call the
send() method to send the email. It's as simple as that. Because no connection values are provided in the
EmailMessage instance, Django uses the default backend connection defined in
One drawback of the
send() method is that it opens a connection to the email server every time it's called. This can be inefficient if you send hundreds or thousands of emails at once. In the spirit of the
send_mass_mail() shortcut method from the last section, it's also possible to open a single connection to the email server and send multiple emails with
EmailMessage. Listing 6 shows how to use a single connection and send multiple emails with
In listing 6 we first create a connection to the email server using
mail.get_connection() and then open the connection with the
open() method. Next, we create the
EmailMessage instances. Once the email instances are prepared, we call the connection's
send_messages() method with an argument list corresponding to each of the
EmailMessage instances. Finally, once the emails are sent we call the connection's
close() method to drop the connection to the email server.
Another common email scenario is to send HTML emails. Django provides the
EmailMultiAlternatives class for this purpose which is a subclass of the
EmailMessage class. By being a subclass, it means you can leverage the same functionalities as
EmailMessage (e.g. CC, BCC), but you don't need to do a lot of work as the subclass
EmailMultiAlternatives is specifically designed to handle a multiple types of messages. Listing 7 illustrates how to use the
EmailMultiAlternatives, a subclass of the
In listing 7 we first define all the email fields, which include the text and HTML version of the email. Note that having a text and HTML version of the email content is common practice as there is no guarantee end users will allow or can read an email's HTML version, so a text version is provided as a backup. Next, we define an instance of the
EmailMultiAlternatives class, notice the parameters are inline with those of the
Next, in listing 7 you can see we call the
attach_alternative method which is specific to the
EmailMultiAlternatives class. The first argument to this method is the HTML content and the second is the content type that corresponds to
text/html. Finally, we call the
send() method -- part of the
EmailMessage class, but which is also automatically part of to
EmailMultiAlternatives since it's a subclass -- to send the actual email.
In controlled environments (e.g. corporate email) where it can be guaranteed that all end users are capable of viewing HTML email, it can be practical to just send an HTML version of an email and bypass the text version altogether. Under these circumstances, you can actually use the
EmailMesssage class directly with a minor tweak. Listing 8 illustrates how to just send HTML email with the
Listing 8 looks like a standard
EmailMessage process definition, however line four is what makes listing 8 different. If the HTML content were sent without line four, end users would receive a verbatim version of the HTML content (i.e. without the HTML brackets rendered). This is because by default the
EmailMessage class specifies the content type as text. In order to switch the default content type of the
EmailMessage instance, in line four a call is made to set the
html. With this change the email content type is set to HTML and end users are capable of viewing the content rendered as HTML.
|Beware of just sending HTML email versions to the public at large|
Although sending an HTML email version is quicker than sending a text and HTML email version, this can be problematic if you can't determine where end users read their email. There are certain users that for security reasons disable the ability to view HTML emails, as well as certain email products that can't or aren't very good at rendering HTML emails. So if you just send an HTML email version, there can be a subset of end users that won't be able to see the email content.
For this reason if you send email to end users where you can't control their environment (i.e. email reader), it is best you send a text and HTML email version -- as illustrated in listing 7 -- than sending an HTML email version illustrated in listing 8.
Another common practice when sending emails is to attach files. Listing 9 illustrates how to attach a PDF to an email.
As you can see in listing 9, after creating an
EmailMessage instance we just open the PDF file using Python's standard
open() method. Next, we use the
attach() method from the
EmailMessage which takes three arguments: the file name, the file contents and the file content type or MIME type. Finally, we simply call the
send() method to send the email.