How to Send Email With Django (Beginner’s Tutorial)

Editorial Note: We may earn a commission when you visit links on our website.
How to send an email with Django

Do you want to learn how to send email with Django? When building web applications, one feature that’s often requested is email functionality.

Whether you’re looking to implement a simple email alert for user registrations or contact form notification emails, you’ll need a notification system for your Django web app.

In this post, I’ll explain how Django’s email system works. Then, proceed to show you different ways to send emails with Django.

Understanding Django’s Email System

Django provides a robust email-sending framework through its django.core.mail module. This module includes functions and classes for sending basic, HTML, and mass emails.

The module requires a backend to function properly. This means you’ll need to configure the email backend you’d like to use for your project.

Django email system overview

Django supports many out-of-the-box email backends. The SMTP Backend is the most popular and works well for most applications.

In addition to the default backend Django supports, you can build a custom email backend for your project. I won’t be covering how to implement a custom email backend in Django since it’s beyond the scope of this tutorial.

Instead, I’ll show you how to use the built-in SMTP Email Backend to send emails on your Django application.

How to Send Email With Django

Prerequisites

Before we dive in, make sure you have:

  • Django installed in your project (I’m using Django 5.0, but this guide works with Django 3.x and above)
  • Basic knowledge of Django and Python
  • A working Django project (if you need to create one, check Django’s official documentation)
  • An email service provider (I’ll use SendLayer, but the steps are similar regardless of the email provider you choose)

If you’d like to use SendLayer, you can get started with a free account that lets you send up to 200 emails.

  • 200 Free Emails
  • Easy Setup
  • 5 Star Support

After creating your free account, you’ll need to authorize your sending domain. This step is essential to improve email deliverability and verify your account.

Configuring Your Email Backend

As I mentioned earlier, this guide assumes you’re familiar with Django and have a working Django project. I’ll use the default Django email backend for this guide. To proceed, open your project’s settings.py file and add the email configuration below.

# Django email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.sendlayer.net'  # Replace with your SMTP server
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-sendlayer-username'
EMAIL_HOST_PASSWORD = 'your-sendlayer-password' 

I’m using SendLayer SMTP server as the email host. But you can use any other SMTP server you’d like.

Django email settings configuration

If you’d like to use SendLayer as well, you’ll need to retrieve your SMTP credentials from your SendLayer account. Please see our tutorial to learn how to retrieve your SMTP credentials.

Once you’ve done that, be sure to replace your-sendlayer-username and your-sendlayer-password with your actual SMTP credentials.

It’s not advisable to store sensitive details like usernames and passwords in your codebase. I recommend using environment variables to secure sensitive details. For this, create a .env file in your project’s root directory and add your SMTP credentials.

// .env file
EMAIL_HOST_USER = 'your-sendlayer-username'
EMAIL_HOST_PASSWORD = 'your-sendlayer-password'

After that, you’ll need to install a third-party library using the command below:

pip install decouple

Next, return to your settings.py file and import the config module from decouple.

from decouple import config

You can use the config module to reference the email host username and password specified in the .env file:

EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')

Method 1: Send Plain Email Using send_mail() Function

send_mail() is a built-in function that lets you send simple emails with minimal customizations. It is particularly useful for welcome emails, password reset emails, notification emails from contact forms, etc.

To use this function, you’ll need to specify 4 required parameters:

  • subject: The email subject line
  • message: The body text of the email
  • from_email: The sender’s email address
  • recipient_list: A list of recipient email address(es)

There are other optional parameters you can add to the send_mail() function before sending your email.

  • fail_silently: A boolean parameter that determines error handling.
    • False: Raises exceptions if there’s an error
    • True: Suppresses errors during sending
  • connection: An optional email backend to use to send your email. This will be used instead of the default email backend in your settings.py file.
  • html_message: Optionally specify an HTML content type. If specified, it will be used as an alternative to the plain text message.

Here is an example email using the send mail function:

from django.core.mail import send_mail

send_mail(
    subject='Welcome to Our App',
    message='Thank you for signing up!',
    from_email='[email protected]',
    recipient_list=['[email protected]'],
    fail_silently=False,
)

Be sure to replace the from_email and recipient_list with the sender and recipient’s email addresses.

Pro Tip: If you’re using SendLayer SMTP server, the from email address should be from the sending domain you authorized. So if you verified example.com, your from email address include @example.com.

Send Email to Multiple Recipients

You can send the email to multiple recipients. To do so, add the recipient email addresses to the recipient_list parameter. You’ll need to separate each email address with a comma.

from django.core.mail import send_mail

send_mail(
    subject='Welcome to Our App',
    message='Thank you for signing up!',
    from_email='[email protected]',
    recipient_list=['[email protected]', '[email protected]', '[email protected]'],
    fail_silently=False,
)

Method 2: Send Email With EmailMessage Class

The EmailMessage class is a built-in module in Django that works similarly to the send_mail() function. In addition to sending basic emails, this class lets you customize your emails further.

EmailMessage vs send_mail function to send email in Django

For instance, you can include attachment files, add CC and BCC email addresses, and use a custom HTML template for your emails.

The EmailMessage class accepts 4 required parameters similar to the send_mail() function: subject, body, from_email, and recipient_email.

It also accepts additional optional parameters you can include in the email message. Here are a few optional parameters the EmailMessage class supports:

  • bcc: A list or tuple of addresses used in the “Bcc” header when sending the email.
  • connection: An email backend instance. Use this parameter if you are sending the EmailMessage via send() and you want to use the same connection for multiple messages.
  • attachments: A list of attachments to put on the message. These can be either MIMEBase instances or (filename, content, mimetype) triples.
  • headers: A dictionary of extra headers to put on the message. The keys are the header names, and the values are the header values.
  • cc: A list or tuple of recipient addresses used in the “Cc” header when sending the email.
  • reply_to: A list or tuple of recipient addresses used in the “Reply-To” header when sending the email.

Here is a basic example of how to use the EmailMessage class:

from django.core.mail import EmailMessage

email = EmailMessage(
    "Email Subject",
    "Body of email goes here",
    "[email protected]",
    ["[email protected]", ],
    ["[email protected]"],
    reply_to=["[email protected]"],
    headers={"Message-ID": "foo"},
)

In the snippet above, I’ve initialized the EmailMessage class and specified the required and optional parameters. After that, we’ll need to call the send() method on the EmailMessage instance we just created above.

email.send()

Calling the send() method will trigger the connection to the mail server.

Sending Emails With Attachments

The EmailMessage also accepts other methods like the attach() and attach_file(). These methods allow you to include attachment files to your emails.

If you use the attach_file() method, you’ll simply need to enter the complete file attachment path and MIMEType as parameters. Here is an example using the same email instance we created above:

email.attach_file('path/to/file.pdf', 'application/pdf')

You’ll need to replace the attachment path with the path to the file you’d like to attach.

Note: Django handles static and attachment files differently. So you’ll need to properly reference the attachment file in your Python script. See Django’s documentation to learn how.

Here’s another variation using the attach() method:

from django.core.mail import EmailMessage
import os

def send_report_email():
    email = EmailMessage(
        subject='Your Monthly Report',
        body='Please find your monthly report attached.',
        from_email='[email protected]',
        to=['[email protected]'],
    )
    
    # Attach file from memory
    with open('path/to/report.pdf', 'rb') as f:
        email.attach('report.pdf', f.read(), 'application/pdf')
    
    email.send()

The attach() method accepts 3 parameters: file name, encoded string, and MIMEType.

We use the with open() method to access the file and convert it to an encoded string using f.read().

When you send a test email, the attachment file should also be sent if you’ve configured it properly.

Send email with Django including attachments

Sending HTML Emails

Modern emails require HTML syntax for proper formatting and styling. With the EmailMessage class, you can create HTML templates to use as the email message. Here’s how to do it:

from django.core.mail import EmailMessage
from django.template.loader import render_to_string
from django.utils.html import strip_tags

def send_welcome_email(user_email):
    subject = 'Welcome to Our Platform'
    html_message = render_to_string('emails/welcome.html', {
        'user_email': user_email,
        'site_name': 'Your Platform Name'
    })
    plain_message = strip_tags(html_message)
    
    email = EmailMessage(
        subject=subject,
        body=html_message,
        from_email='[email protected]',
        to=[user_email],
    )
    email.content_subtype = 'html'  # This tells Django to send HTML email
    email.send()

In the code above, I’ve added 2 import statements: render_to_string and strip_tags. The render_to_string module renders a template into a string, while strip_tags removes HTML tags from a string.

We use the render_to_string method to load the HTML template from 'templates/welcome.html'. After that, we pass a context dictionary with user_email and site_name.

After adding the snippet, you’ll need to create the actual HTML template. Django will look for this file in the templates folder specified above. So the HTML email template should sit there.

<!DOCTYPE html>
<html>
<head>
    <style>
        .email-container {
            max-width: 600px;
            margin: 0 auto;
            font-family: Arial, sans-serif;
        }
        .button {
            background-color: #211FA6;
            border: none;
            color: white;
            padding: 15px 32px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
            border-radius: 10px
        }
    </style>
</head>
<body>
    <div class="email-container">
        <h1>Welcome to {{ site_name }}!</h1>
        <p>Hello {{ user_email }},</p>
        <p>Thank you for joining our platform. We're excited to have you on board!</p>
        <a href="https://sendlayer.com/docs/welcome-to-sendlayer/" class="button">Get Started</a>
    </div>
</body>
</html>

This is a simple HTML template to welcome users who sign up to your app. I added a little CSS style for the Get Started button.

When you run the script, Django will use the HTML template as the message body when sending the email.

Method 3: Send Bulk Email in Django

If you have a large subscriber list and need to send a newsletter, it can be resource-consuming to use the send_mail() function. This is because Django will treat each recipient email as a new connection to the mail server.

Fortunately, Django provides a function that simplifies bulk emails, ie, send_mass_email(). When the function is called, it will treat the emails as a single connection, regardless of the number of emails you’re sending.

It requires one parameter, which is the datatuple containing all individual email messages. Here is the format for the data tuple.

(subject, body, from_email, recipient_list)

Each message must have the format specified above to use this function. Here is an example usage:

from django.core.mail import send_mass_mail

message1 = (
    subject="Welcome to SendLayer",
    body="This is a test bulk email sent through Django using SendLayer SMTP server",
    from_email="[email protected]",
    recipient_list=["[email protected]", "[email protected]"]
)

message2 = (
    subject="Welcome to SendLayer",
    body="This is a test bulk email sent through Django using SendLayer SMTP server",
    from_email="[email protected]",
    recipient_list=["[email protected]"]
)

send_mass_mail((message1, message2), fail_silently=False)

I set the fail_silently argument to False to ensure errors are logged if the email doesn’t deliver to the specified recipients.

How to Send a Test Email in Django

You can add the email function examples I shared in this guide to your views or anywhere else in your Django application. Django has built-in test scripts that enable testing features on your app.

Creating Email Function to View.py

For this example, I’ll add the email function to a views.py file.

#views.py

from django.http import HttpResponse
from django.core.mail import send_mail

# Create your views here.
def sl_send_email(request):
    try:
        send_mail(
            subject='Test Email',
            message='This is a test email from Django using SendLayer SMTP',
            from_email='[email protected]',
            recipient_list=['[email protected]'],
            fail_silently=False,
        )
        return HttpResponse("Email sent successfully!")
    except Exception as e:
        return HttpResponse(f"Failed to send email: {str(e)}")

In the snippet above, I’ve created a new function-based view (sl_send_email()) that accepts a request parameter. Within the function, we’re using the try except Python syntax to send the email.

Pro Tip: I used the send_mail() function for this example. However, it works the same when using the send_mass_mail() function or EmailMessage class in Django.

If the email gets delivered, we’ll display “Email sent successfully” on the page. Otherwise, it’ll trigger the except block and render the error message on the page.

I’ve used HttpResponse to display the page content. However, you can use the render function in Django to display an HTML template instead.

Adding a Function-Based View to URLs in Django

After creating your function-based view, you’ll need to add the function to a URL endpoint on your app. This can be accomplished in the urls.py file.

Once you’ve opened the urls.py file, import the view you just created using the command below:

#urls.py
from .views import sl_send_email

Then, add the view to the urlpatterns variable on your project.

from django.urls import path
from .views import sl_send_email


urlpatterns = [
    path('', sl_send_email, name='Send Email'), # specify path
]

Code breakdown

urlpatterns is Django’s default way of specifying the URLs for your views. It is essentially a list containing multiple path() functions.

The path function accepts 3 parameters:

  • Route: This is a string containing the absolute path to the view. For example, using "email/" will render the view in the frontend with the URL example.com/email/ on a live site or localhost:8000/email/ on a dev environment.
  • View: This is where you specify the view you’d like to display. In our example, this is the sl_send_email view. If you used a different name for your function-based view, you’ll need to update the import statement to match yours.
  • Name: This is an optional parameter that makes it easy to reference views in templates and other parts of the application.

After adding the snippet, be sure to save your changes. Then start up the development server using the command below:

python manage.py runserver

Once the server is up, navigate to the route for the function-based view you created. Doing this will trigger the send_mail() function and render the HTTP response on the page.

If the email is delivered successfully, you’ll see a success notification on the web page.

Test email delivered successfully

Viewing the terminal will also show you the status of the request. A 200 response indicates the request was successful.

Send email with Django console response

You should receive the test email in the inbox of the recipient email(s) you specified in the snippet.

Sending a test email in Django

Troubleshooting Common Errors

When testing the code snippets above, I encountered some issues. I’ve highlighted some of the common ones so you won’t have to struggle like I did.

ModuleNotFoundError: No module named 'django'

This error indicates that you haven’t installed the Django package on your machine. To fix it, simply run the command pip install django in a terminal window.

It could also occur if you activated the wrong virtual environment. You may have installed Django on a separate virtual environment and activated a different one. Simply deactivate the virtual environment and activate the one with Django installed.

Error: (500, b'5.0.0 EMAIL SENDING LIMIT REACHED.')

Most email providers have sending limits on their service. This limit varies depending on the plan you’re subscribed to. If you’ve exceeded your sending limit, you’ll likely encounter this error.

To fix this error, you’ll need to upgrade to a higher plan or switch to a different email provider with higher limits.

Error: [Errno 2] No such file or directory

This error occurs when sending emails with an attachment. It indicates the file path you’ve specified for an email attachment is invalid. To fix this error, be sure to double-check that the file path is correct in your code is correct.

FAQs – Send Email With Django

Below, we’ve answered some of the top questions we see about sending emails in Django.

What is the difference between send_mail() and EmailMessage in Django?

Both the send_mail() function and EmailMessage class are built-in Django modules that let you send emails in your Django app. Their major difference is that EmailMessage allows for more advanced sending options like including attachments or adding BCC addresses.

Can I send emails in Django without SMTP?

Yes! You can use an Email API to route emails from your Django project. In a previous tutorial, we covered how to send emails in Python through an Email API. You can use the code snippets on your Django app as well since it’s built on Python.

Can I schedule emails in Django?

There are several ways to schedule emails in Django. You can use built-in libraries like Django-Q or create a cron job with Django management commands. Additionally, third-party libraries like Celery can help you schedule emails on your app. Here’s an example snippet of how to implement the Celery scheduling.

from celery import shared_task

@shared_task
def send_scheduled_email():
    send_mail(
       'Subject',
       'Message',
       '[email protected]',
       ['[email protected]']
)

That’s it! Now you know different ways to send emails in Django.

Next, would you like to improve the customer experience for new users on your application? Check out our guide on the best welcome email examples for new customers to learn how.

  • 200 Free Emails
  • Easy Setup
  • 5 Star Support

Ready to send your emails in the fastest and most reliable way? Get started today with the most user-friendly and powerful SMTP email delivery service. SendLayer Business includes 5,000 emails a month with premium support.