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, I'll show you different ways to send emails with Django.
Table of contents
- Understanding Django's email system
- How to send email with Django
- Configuring your email backend
- How to send a test email
- Troubleshooting common errors
- Frequently asked questions
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 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 backends Django supports, you can build a custom email backend for your project. However, I'll show you how to use the built-in SMTP Email Backend to send emails in 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.
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
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's SMTP server as the email host, but you can use any other SMTP server you'd like.
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.
Securing your 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. Create a .env file in your project's root directory:
EMAIL_HOST_USER='your-sendlayer-username'
EMAIL_HOST_PASSWORD='your-sendlayer-password'
Start by installing the python-decouple library:
pip install python-decouple
Once the installation completes, import and use it in your settings.py:
from decouple import config
# other code snippet...
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's particularly useful for welcome emails, password reset emails, and notification emails from contact forms.
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:-
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 instead of the defaulthtml_message: Optionally specify an HTML content type
Here's 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='paulie@example.com',
recipient_list=['user@example.com'],
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's SMTP server, the from email address should be from the sending domain you authorized. So if you verified example.com, your from email address should include
@example.com.
Send email to multiple recipients
You can send emails to multiple recipients by adding their email addresses to the recipient_list parameter, separated by commas:
from django.core.mail import send_mail
send_mail(
subject='Welcome to Our App',
message='Thank you for signing up!',
from_email='paulie@example.com',
recipient_list=['user1@example.com', 'user2@example.com', 'user3@example.com'],
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.
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 send_mail(): subject, body, from_email, and recipient_email.
It also accepts additional optional parameters:
bcc: A list or tuple of addresses used in the "Bcc" header
connection: An email backend instance for using the same connection for multiple messages
attachments: A list of attachments (MIMEBase instances or filename/content/mimetype triples)
headers: A dictionary of extra headers
cc: A list or tuple of recipient addresses for the "Cc" header
reply_to: A list or tuple of recipient addresses for the "Reply-To" header
Here's 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",
"from@example.com",
["recipient@example.com"],
["bcc@example.com"],
reply_to=["paulie@example.com"],
headers={"Message-ID": "foo"},
)
email.send()
In the snippet above, I've initialized the EmailMessage class and specified the required and optional parameters. Calling the send() method will trigger the connection to the mail server.
Sending emails with attachments
The EmailMessage class accepts methods like attach() and attach_file() that 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:
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
def send_report_email():
email = EmailMessage(
subject='Your Monthly Report',
body='Please find your monthly report attached.',
from_email='paulie@example.com',
to=['recipient@example.com'],
)
# 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 be included if you've configured it properly.
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:
from django.core.mail import EmailMessage
from django.template.loader import render_to_string
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'
})
email = EmailMessage(
subject=subject,
body=html_message,
from_email='noreply@yourplatform.com',
to=[user_email],
)
email.content_subtype = 'html' # This tells Django to send HTML email
email.send()
In the code above, I've imported render_to_string, which renders a template into a string. We use this method to load the HTML template from 'templates/welcome.html'.
After adding the snippet, you'll need to create the actual HTML template:
<!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. 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: send_mass_mail(). 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's the format:
(subject, body, from_email, recipient_list)
Each message must have the format specified above. Here's an example usage:
from django.core.mail import send_mass_mail
message1 = (
"Welcome to SendLayer",
"This is a test bulk email sent through Django using SendLayer SMTP server",
"paulie@example.com",
["user1@example.com", "other@example.com"]
)
message2 = (
"Welcome to SendLayer",
"This is a test bulk email sent through Django using SendLayer SMTP server",
"paulie@example.com",
["user@example.com"]
)
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. For this example, I'll add the email function to a views.py file.
Creating email function in views.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
def sl_send_email(request):
try:
send_mail(
subject='Test Email',
message='This is a test email from Django using SendLayer SMTP',
from_email='paulie@example.com',
recipient_list=['david@example.com'],
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 thesend_mass_mail()function orEmailMessageclass 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.
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.
Import the view you just created:
# urls.py
from .views import sl_send_email
Then, add the view to the urlpatterns variable:
from django.urls import path
from .views import sl_send_email
urlpatterns = [
path('', sl_send_email, name='Send Email'),
]
urlpatterns is Django's default way of specifying the URLs for your views. It's essentially a list containing multiple path() functions.
The path function accepts 3 parameters:
-
Route: A string containing the absolute path to the view. For example, using
"email/"will render the view at example.com/email/ on a live site orlocalhost:8000/email/on a dev environment. -
View: Where you specify the view you'd like to display. In our example, this is the
sl_send_emailview. - Name: An optional parameter that makes it easy to reference views in templates and other parts of the application. After adding the snippet, save your changes and start the development server:
python manage.py runserver
Once the server is up, navigate to the route for the function-based view you created. 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.
Viewing the terminal will also show you the status of the request. A 200 response indicates the request was successful.
You should receive the test email in the inbox of the recipient email(s) you specified.
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, run:
pip install django
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, double-check that the file path in your code is correct.
Frequently asked questions
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 in your Django app as well since it's built on Python.
Wrapping Up
In this comprehensive tutorial, we've explored multiple ways to send emails in Django.
Have questions or want to share your implementation? Drop a comment below. I'd love to hear how you're handling email in your Django projects!
Ready to implement this in your application? Start your free trial at SendLayer and send your first email in minutes.







Top comments (0)