Have you ever struggled with setting up email integration in your Django projects? Whether it’s configuring SMTP settings, handling security concerns, or automating contact forms, email functionality is crucial for user engagement and trust.
In this tutorial, we’ll walk through how to send emails using Django with practical, step-by-step instructions. We’ll cover how to configure Django SMTP connections, how to set up an password for your email provider, and how to send emails through the Django shell. We’ll also look at how to set up a contact form for your Django app, which will allow your customers to contact you.
Key Takeaways
- Configure SMTP Settings: Set up Django email send by configuring the settings.py file with the appropriate email backend, host, port, and security settings (e.g., TLS).
- Secure Credentials with Django Environ: Use Django Environ to manage sensitive credentials like EMAIL_HOST_USER and EMAIL_HOST_PASSWORD securely via environment variables, preventing hardcoding of credentials in the source code.
- Generate App-Specific Passwords: When using Gmail, enable 2-Step Verification and create an App Password to securely authenticate Django mail sending instead of relying on your primary password.
- Send Emails with send_mail: Use Django’s built-in send_mail function to send emails with Django from the Django shell, views, or reusable helper functions, utilizing settings for streamlined configuration.
- Implement Automated Contact Forms: Build an automated contact form using Django Forms and integrate email-sending functionality for seamless handling of user inquiries.
- Test Email Functionality: Verify email-sending logic with unit tests and use tools like MailHog or Console Email Backend for safe development testing.
- Follow Best Practices: Ensure secure and efficient email delivery by using TLS encryption, proper authentication, and modular email functions for reusability.
Most web applications use email to manage crucial operations, such as resetting passwords, account activation, receiving customer feedback, sending newsletters, and marketing campaigns. While Gmail works for testing or small projects, production websites should use dedicated email services such as AWS SES, SendGrid, or Mailgun.
However, if you compare the cost and the effort of using a dedicated email service, sending emails with your personal email can be more reasonable for small or testing projects. So we’ll take that approach here to keep things simple.
Note: It’s not a good idea to use your personal email service for your production website. You can learn more about Gmail sending restrictions, or refer to the limitations of your email provider.
Note: the full code for this tutorial is available on GitHub.
Understanding the SMTP Server and Simple Mail Transfer Protocol
SMTP (or the Simple Mail Transfer Protocol) is a set of rules for determining how emails are transferred from senders to recipients. SMTP servers use this protocol to send and relay outgoing emails. (Note that other protocols govern how emails are received.)
An SMTP server always has a unique address and a specific port for sending messages, which in most cases is 587. We’ll see how the port is relevant in Django email send.
For this example, we’ll use Gmail’s SMTP server, where:
Now, let’s see how we can send email with Django.
Creating a Django Project
Every Django project should have a virtual environment, as we don’t want to mess up the project dependencies. To create one, run the following:
Note: if you’re unfamiliar with virtual environments, make sure to check our Python virtual environments guide.
The command above creates a virtual environment with the name .venv. To activate this virtual environment, you can use the following:
.venv\Scripts\activate
.venv\Scripts\Activate.ps1
source .venv/bin/activate
Since Django is a third-party package, you have to install it with pip:
This will install the latest version of Django, which you can check with pip freeze.
To create a Django project, you call the command line utility django-admin:
django-admin startproject EmailProject
With the command above, you’re creating a Django project with the name EmailProject, but you can create the project with whatever name you want. Now, enter to the project directory and run the server:
cd EmailProject
python manage.py runserver
After running the Django server, visit http://localhost:8000 in your browser. You’ll see an auto-generated page with the latest Django release notes.
Configuring Django Email Backend for SMTP
The email backend is the mechanism to send emails with Django. By default, Django uses django.core.mail.backends.smtp.EmailBackend, which allows it to connect to an SMTP server and send emails. Depending on the environment (development or production), you can choose a different email backend to suit your needs.
You’ll need to modify the settings file before sending emails, so let’s locate that file with the below command:
Note: for simplicity’s sake, we’ll be using only UNIX (macOS or Linux) system commands.
The tree command outputs the file structure of a directory. In this case, since we’re not giving it a specific directory path, we’ll get something similar to the following if we’re in the root folder of the project:
├── EmailProject
│ ├── asgi.py
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
1 directory, 6 files
The file we’ll be constantly modifying through this tutorial is the settings.py inside the EmailProject folder. It holds all the project configuration you’ll need, and allows you to set custom variables. As the Django docs say, “A settings file is just a Python module with module-level variables”.
Let’s look at the settings required for sending an email with Django. Open the EmailProject/settings.py file and paste the following settings at the bottom of the file:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = ''
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
Let’s break down the code above by analyzing each one of these settings.
Email Backend
The EMAIL_BACKEND setting declares the backend our Django project will use to connect with the SMTP server.
This variable is pointing to the smtp.EmailBackend class that receives all the parameters needed to send an email. I strongly suggest you take a look at the class constructor directly on the Django source code. You’ll be surprised by how readable this code is.
Note: although this class is the default EMAIL_BACKEND, it’s considered a good practice to be explicit in the Django settings.
All the other email settings will be based on the constructor of this EmailBackend class.
Email host
The EMAIL_HOST setting refers to the SMTP server domain you’ll be using. This depends on your email provider. Below is a table with the SMTP server host corresponding to three common providers:
Email provider | SMTP server host |
---|---|
Gmail | smtp.gmail.com |
Outlook/Hotmail | smtp-mail.outlook.com |
Yahoo | smtp.mail.yahoo.com |
We’re leaving this setting blank for now since we’ll use a .env file later to avoid hard-coded sensitive keys or per-site configurations. You should never set credentials directly into the code. We’ll be using Django Environ to solve this problem.
Email Port
The EMAIL_PORT setting must be set to 587 because it’s the default port for most SMTP servers. This remains true for personal email providers. This port is used along with TLS encryption to ensure the security of email sending.
Email Use TLS
Transport Layer Security (TLS) is a security protocol used across the Web to encrypt the communication between web apps (Django) and servers (SMTP server).
Originally, we set the EMAIL_USE_TLS variable to True. This means Django will use Transport Layer Security to connect to the SMTP server and send emails. (It’s mandatory for personal email providers.)
Email Host User
The EMAIL_HOST_USER setting is your personal email address. Leave it blank for now, since we’ll use django-environ to set up all of these credentials.
Email Host Password
The EMAIL_HOST_PASSWORD setting is the app password you’ll get from your email account — the process we’ll be doing right after this section. Same story: leave this setting blank, as we’ll use environmental variables later.
For other providers, you can adjust the settings accordingly. For example:
Outlook Configuration:
EMAIL_HOST = 'smtp-mail.outlook.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-email@outlook.com'
EMAIL_HOST_PASSWORD = 'your-app-password'
Yahoo Configuration:
EMAIL_HOST = 'smtp.mail.yahoo.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'your-email@yahoo.com'
EMAIL_HOST_PASSWORD = 'your-app-password'
Setting Up Gmail SMTP Server with App Password
Since “Less Secure Apps” is deprecated by Google, the proper and secure way to connect to Gmail account for sending emails is to use App Passwords. App Passwords are available only if you enable 2-Step Verification for your Google account.
Why Use App Passwords?
- Secure Alternative: Instead of sharing your primary password, App Passwords provide limited access for specific applications.
- Works with SMTP: App Passwords comply with Gmail’s security requirements for SMTP access.
- Mandatory for 2-Step Verification: Once 2-Step Verification is enabled, App Passwords are the only way to allow external apps to connect.
Step 1: Enable 2-Step Verification
- Go to your Google Account: https://myaccount.google.com/.
- Navigate to Security in the left-hand menu.
- Scroll to the “How you sign in to Google” section.
- Click on “2-Step Verification” and follow the on-screen instructions:
- Use your phone number or an authenticator app to set up 2-Step Verification.
- Verify your setup with the code sent to your device.
Step 2: Generate an App Password
- Once 2-Step Verification is enabled, search “App Passwords” in the search bar.
- There, enter the name for the App password and click Create.
- Then, it will give an pop up modal with a 16-character App Password. Make sure to save it somewhere since it will only be shown once.
If you’re using other email providers, make sure to read the following guides:
Using Django Environ to Secure Email Backend Credentials
Even if you’re just sending emails in development, you shouldn’t write passwords directly into the source code. This becomes even more important when using a version control system along with GitHub to host your project. You don’t want people to access your data.
Let’s see how we can prevent this by using Django-environ.
Create a .env file inside the EmailProject directory (where the settings.py file is located) with the command below:
cd EmailProject/
ls
settings.py
touch .env
Now, open that .env file and enter the following key–value pairs:
EMAIL_HOST=smtp.gmail.com
EMAIL_HOST_USER=YourEmail@address
EMAIL_HOST_PASSWORD=YourAppPassword
RECIPIENT_ADDRESS=TheRecieverOfTheMails
Breaking down the contents of this file:
- EMAIL_HOST: Your email provider’s SMTP server address. See the email host table above for quick guidance. In this case, I’m using smtp.gmail.com, the Gmail SMTP address.
- EMAIL_HOST_USER: Your email address.
- EMAIL_HOST_PASSWORD: The app password you just generated. Have in mind it doesn’t include any spaces.
- RECIPIENT_ADDRESS: The email address in which you’ll receive the messages. This is a custom setting that we’ll create later to send all the emails to the same recipient.
To make use of these environmental variables, we’ll need to install Django-environ:
pip install django-environ
Note: make sure your virtual environment is activated.
Now, open the settings.py located in the EmailProject directory and use the code below:
import environ
env = environ.Env()
environ.Env.read_env()
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
RECIPIENT_ADDRESS = env('RECIPIENT_ADDRESS')
First, we’re importing the environ package at the top of the settings file. Remember that all imports should be at the start. Then we create an env variable which will contain all the key–value pairs available on the .env.
The env(‘KEY’) statement means we’re looking up the value of that key. Before proceeding, make sure you have set up your .env file. Otherwise, if some environmental variable isn’t set, you’ll get a Django ImproperlyConfigured error.
Note: RECIPIENT_ADDRESS is a custom setting that we’ll use to send emails to an address we can access.
Don’t forget to include the .env file in your .gitignore if you’re using Git and GitHub. You can do this just by opening it and adding the following line:
1. Sending Emails with the Django Shell
Finally, we get to the juicy part of the article! It’s time to send your first email to Django.
Open up a terminal, activate the virtual environment, and run:
This will create a shell with all the Django settings already configured for us. Inside that brand-new shell, paste the following code:
>>> from django.core.mail import send_mail
>>> from django.conf import settings
>>> send_mail(
... subject='A cool subject',
... message='A stunning message',
... from_email=settings.EMAIL_HOST_USER,
... recipient_list=[settings.RECIPIENT_ADDRESS])
1
We can also make a one-liner without specifying the arguments:
>>> send_mail('A cool subject', 'A stunning message', settings.EMAIL_HOST_USER, [settings.RECIPIENT_ADDRESS])
1
Let’s break down the code above:
- We import the Django send_mail function.
- Then we import the settings object, which contains all the global settings and the per-site settings (those inside the settings.py file).
- Finally, we pass all the needed arguments to the send_mail function. This function returns the number of emails sent, in this case, 1.
Note how we use the settings object to get the from_email (the email you’re sending emails with) and the recipient_list (the RECIPIENT_ADDRESS custom setting we defined in the .env).
Now, if I check my inbox — as I set the RECIPIENT_ADDRESS environmental variable to my email address — I’ll get the email message sent by Django.
Asynchronous Email Sending
In Django 4.x, asynchronous email sending is supported to improve performance. This is useful for high-traffic websites or when sending bulk emails.
Here’s how you can send an email asynchronously:
import asyncio
from django.core.mail import send_mail
from django.conf import settings
async def send_async_email():
await send_mail(
subject="Async Email Test",
message="This email is sent asynchronously with Django 4.x.",
from_email=settings.EMAIL_HOST_USER,
recipient_list=[settings.RECIPIENT_ADDRESS],
)
asyncio.run(send_async_email())
Asynchronous email sending is useful in scenarios like:
- Non-blocking operations where sending an email shouldn’t delay user requests.
- Sending bulk emails (use a task queue like Celery for production-scale tasks).
Note: While Django supports asynchronous email, for production-scale bulk emails, use a background task queue like Celery or Django-Q for true non-blocking operations.
In this section, we’ll build an automated contact form with Django forms and the built-in send_mail function. We’ll also create a custom function, send(), inside the contact form so it’s easier to implement it in the views.
Let’s start by creating the contact app. Enter the project root directory — where manage.py is located — and run:
python manage.py startapp contact
Then, install it in your INSTALLED_APPS variable inside the EmailProject/settings.py file:
INSTALLED_APPS = [
'django.contrib.admin',
...
'contact',
]
Before advancing with the contact app, let’s configure the urlpatterns inside of the EmailProject/urls.py file. To do this, import the django.urls.include function and include the contact URLs in the overall project. Don’t worry; we’ll configure the contact URLs later:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('contact.urls'))
]
Contact Form
Enter the contact app folder and create a forms.py file. It’s a good practice to define all of your forms inside of a forms.py file, but it isn’t mandatory. That’s why Django doesn’t include this file by default. You can create the forms file with the following commands:
cd ../contact/
touch forms.py
Open the file you just created and make the following imports:
from django import forms
from django.conf import settings
from django.core.mail import send_mail
The Django form module gives us all the needed classes and fields to create our contact form. Once again we’re importing the settings object and the send_mail function to send the emails.
Our contact form will contain several fields and use two custom methods: get_info(), which formats the user-provided information, and send(), which will send the email message. Let’s see this implemented in code:
from django import forms
from .services import send_contact_email
class ContactForm(forms.Form):
name = forms.CharField(max_length=120)
email = forms.EmailField()
inquiry = forms.CharField(max_length=70)
message = forms.CharField(widget=forms.Textarea)
def get_info(self):
"""
Method that returns formatted information
:return: subject, msg
"""
cl_data = super().clean()
name = cl_data.get('name').strip()
from_email = cl_data.get('email')
subject = cl_data.get('inquiry')
msg = f'{name} with email {from_email} said:'
msg += f'\n"{subject}"\n\n'
msg += cl_data.get('message')
return subject, msg
def send(self):
subject, msg = self.get_info()
send_mail(
subject=subject,
message=msg,
from_email=settings.EMAIL_HOST_USER,
recipient_list=[settings.RECIPIENT_ADDRESS]
)
This class is huge, so let’s break down what we do in each part. Firstly, we define four fields that will be required to send the email message:
- Name and inquiry are CharFields, which represent the name and reason of the contact message.
- Email is an EmailField that represents the email address of the person trying to contact you. Note that the email will not be sent by the user’s email address but by the email address you set to send emails in the Django project.
- The message is another CharField, except we’re using the Textarea widget. This means that, when displaying the form, it’ll render a <textarea> tag instead of a simple <input>.
Heading into the custom methods, we’re only using the get_info method to format the user’s information and return two variables: subject, which is nothing but the inquiry field, and message, which will be the actual email message sent by Django.
On the other hand, the send() method only gets the formatted info from get_info and sends the message with the send_mail function. Although this section was pretty large, you’ll see how we simplified the contact views by implementing all the sending logic to the ContactForm itself.
Contact Views
Open the contact/views.py file and add the following imports:
from django.views.generic import FormView, TemplateView
from .forms import ContactForm
from django.urls import reverse_lazy
As you can see, we’re going to use Django generic views, which saves us a ton of time when making simple tasks — for example, when setting up a form with FormView or creating a view that only renders a template with TemplateView.
Also, we’re importing the ContactForm that we built in the previous section and the reverse_lazy function used when working with class-based views. Continuing with the views, let’s write the ContactView:
class ContactView(FormView):
template_name = 'contact/contact.html'
form_class = ContactForm
success_url = reverse_lazy('contact:success')
def form_valid(self, form):
form.send()
return super().form_valid(form)
As you can see, we’re building a simple FormView using the ContactForm we created. We’re also setting up the template_name and the success_url. We’ll write the HTML template and set up the URLs later.
The form valid method let us send the email using the ContactForm.send() method only if all the fields of the form are valid. This implies that if the user enters invalid input — such as an unformatted email address — the message won’t be sent.
The above form_valid method implementation would be equivalent to the following in a function-based view:
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form.send()
return redirect('contact:success')
else:
form = ContactForm())
Ending this section, we’re going to write a ContactSucessView, which will show a success message to the user. Since we’ve already imported the TemplateView class, we only need to inherit from it and define the template_name attribute:
class ContactSuccessView(TemplateView):
template_name = 'contact/success.html'
You can check out the views.py file on the GitHub repository if you have any concerns.
Contact URLs
It’s time to create the URL patterns of the contact app. Since Django doesn’t give us the urls.py file by default, we’ll need to create it with the following command (make sure to be inside the contact app folder):
Open that file and set up the app_name and urlpatterns variables:
from django.urls import path
from .views import ContactView, ContactSuccessView
app_name = 'contact'
urlpatterns = [
path('', ContactView.as_view(), name="contact"),
path('success/', ContactSuccessView.as_view(), name="success"),
]
We use path to include the route and its correspondent view to the URL configuration of the app. When we set the app_name variable to ‘contact’, it means the URL namespacing of the app will look like this:
contact:name_of_path
contact:contact
contact:success
Note: a namespace is what we call URLs dynamically in Django templates and Views.
You can learn more about the Django URL dispatcher in the official documentation.
Writing templates
Django templates are the preferred way to display data dynamically, using HTML and special tags provided by the Django Template Language.
For this specific app, we’ll be using three templates:
- base.html: All the other templates will inherit from it. It’ll contain the HTML skeleton that all templates must have, as well as links to Bootstrap.
- contact.html: Displays the contact form.
- success.html: Displays a success message.
Let’s start by creating the contact’s app template structure (make sure you’re inside the contact app folder):
mkdir -p templates/contact/
cd templates/contact
touch base.html contact.html success.html
The commands above create the typical template structure of a reusable Django app — appname/templates/appname — and the tree template files I mentioned before. Here’s what the app file structure should now look like:
.
├── admin.py
├── apps.py
├── forms.py
├── __init__.py
├── migrations
│ └── __init__.py
├── models.py
├── templates
│ └── contact
│ ├── base.html
│ ├── contact.html
│ └── success.html
├── tests.py
├── urls.py
└── views.py
Let’s jump into the content of the base.html template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Django Email Send</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
</head>
<body>
{% block body %}
{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous">
</script>
</body>
</html>
As you can see, it’s the simple skeleton of an HTML file that includes links to Bootstrap 5. This allows us to stylize our contact app without using CSS files. The {% block name-of-block %} tag allows us to set up a placeholder that “child templates” will utilize. The use of this tag makes template inheritance an easy task.
Before heading into the forms, you’ll need to install the Django crispy forms package, which allows us to stylize them easily:
pip install django-crispy-forms
Once again, crispy_forms is a Django app, and we need to include it on the INSTALLED_APPS list:
INSTALLED_APPS = [
...
'crispy_forms',
'contact',
]
CRISPY_TEMPLATE_PACK = 'bootstrap4'
We use the template pack of Bootstrap 4, because the Bootstrap form classes are compatible between the 4th and 5th version (at the time of writing).
Now, let’s work on the contact.html template:
{% extends 'contact/base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="mx-auto my-4 text-center">
<h1>Contact Us</h1>
</div>
<div class="container">
<form action="" method="post">
{% csrf_token %}
{{ form | crispy }}
<button class="btn btn-success my-3" type="submit">Send message</button>
</form>
</div>
{% endblock %}
Note how we extended the base template and make use of the block placeholder. This is what makes Django Template Language so efficient, as it lets us save a lot of HTML copying and pasting.
Talking about the form, we’re using the method “post”, which means that our ContactView will process the data given by the user and send the email if the form is valid. The {% csrf_token %} is mandatory in every form because of security reasons. Django’s documentation has a dedicated page on CSRF tokens and the reasons to use them when working with forms.
We’ll be rendering the form with the crispy template tag, which is why we loaded the crispy tags with {% load crispy_forms_tags %}.
Finally, let’s write the success.html template:
{% extends 'contact/base.html' %}
{% block body %}
<div class="mx-auto my-4 text-center">
<h1 class="fw-bolder text-success">We sent your message</h1>
<p class="my-5">You can send another in the <a href="{% url 'contact:contact' %}">contact page</a></p>
</div>
{% endblock %}
As you can see, it’s a simple success announcement with a link to the contact form in case the user wants to send another message.
Let’s run the server again and visit http://localhost:8000 (make sure you have the .venv activated and you’re inside the project root folder):
python manage.py runserver
The image below shows what the final contact form looks like.
And this is an image of the success message.
And here’s an image of the email in the inbox.
Best Practices to Follow
1. Reusable Email Sending Function
To make your email-sending logic modular and reusable, you can move the email sending function to a helper function:
from django.core.mail import send_mail
from django.conf import settings
def send_contact_email(subject, message, recipient):
send_mail(
subject=subject,
message=message,
from_email=settings.EMAIL_HOST_USER,
recipient_list=[recipient],
fail_silently=False,
)
You can now call this function wherever you need to send emails, including your contact form.
2. Unit Testing
You can use django.test to test send email Django functionalities.
from django.test import TestCase
from django.core.mail import send_mail
class EmailTest(TestCase):
def test_email_sending(self):
response = send_mail(
subject='Test Subject',
message='Test Message',
from_email='from@example.com',
recipient_list=['to@example.com'],
)
self.assertEqual(response, 1)
3. Sending Rich HTML Emails
HTML emails provide better design and presentation. Use Django’s template engine to create rich email content:
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.conf import settings
def send_html_email():
subject = 'HTML Email Example'
from_email = settings.EMAIL_HOST_USER
recipient = ['recipient@example.com']
html_content = render_to_string('email_template.html', {'key': 'value'})
msg = EmailMultiAlternatives(subject, body='', from_email=from_email, to=recipient)
msg.attach_alternative(html_content, "text/html")
msg.send()
4. Integrating Third-Party Email Services
For production-ready applications, consider using third-party services such as SendGrid, Mailgun, or AWS SES. These services offer advanced features like email analytics, delivery tracking, and spam filtering.
EMAIL_BACKEND = 'sendgrid_backend.SendgridBackend'
SENDGRID_API_KEY = 'your-api-key'
SENDGRID_SANDBOX_MODE_IN_DEBUG = False
5. Email Verification in User Registration
Send email verification links during user registration to prevent spam accounts.
from django.core.mail import send_mail
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from django.template.loader import render_to_string
def send_verification_email(user, request):
token = account_activation_token.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
link = request.build_absolute_uri(f'/activate/{uid}/{token}/')
message = render_to_string('activation_email.html', {'link': link})
send_mail('Verify your email', message, 'from@example.com', [user.email])
Wrapping up
Congrats! You’ve learned how to send emails with Django and how to build a Django contact form as well.
There are many ways to send emails with Django. In this tutorial, you’ve made it with your personal email address, but I’d like you to explore other tools and integrate them into your projects.
In this tutorial, we’ve covered the following:
- How to set up Django settings to serve emails
- How to use a personal email account to send emails in a small project
- How to use .env files to use sensitive data in a Django project
- How to build an automated contact form
For more on Django, check out “Build a Photo-sharing App with Django”.
FAQs on Django Send Email with SMTP Server
Can I Send an Email from Django?
Yes, Django provides a built-in email-sending framework that makes it simple to send emails. By configuring the SMTP settings in your settings.py file, you can send emails using the send_mail function or EmailMessage class.
How to Send Email in Django?
To configure Django for sending emails:
- Set the SMTP details in your settings.py file:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.gmail.com' EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = 'your_email@example.com' EMAIL_HOST_PASSWORD = 'your_app_password'
- Use a secure Password instead of your main email password if you’re using Gmail or similar providers.
- For production, consider using third-party services like SendGrid, Mailgun, or Amazon SES for better scalability.
How to Send Outlook Mail in Django?
To send Outlook mail in Django, you can use Django’s email sending functionality with the SMTP settings for Outlook. In your Django project’s settings.py file, configure the SMTP settings for Outlook. These settings will enable Django to connect to the Outlook SMTP server to send emails.
How to Receive Emails in Django?
In your Django project’s settings.py, configure your incoming email server settings. You typically need the IMAP (Internet Message Access Protocol) server details for your email provider, along with authentication credentials. Next, use the imaplib library to connect to your email server and retrieve emails. You can do this in your Django views or custom management commands. Once you have fetched an email, you can process it, extract information, and perform any necessary actions within your Django application. This could involve parsing the email content, storing relevant data in your database, or triggering specific actions based on the email’s content or sender.
How Do I Test Email Sending in Django Without Sending Real Emails?
During development, you can use an optional email backend to test emails without connecting to a real SMTP server. For example: Console Email Backend: Prints email messages to the terminal instead of sending them.
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
For more advanced testing, use tools like MailHog or Mailtrap, which act as fake SMTP servers for capturing and displaying test emails.
How Do I Manage Sensitive Email Credentials Securely?
Use Django Environ to load sensitive credentials (like email host, username, and password) from a .env file:
- Install Django Environ:
pip install django-environ
- Create a .env file:
EMAIL_HOST=smtp.gmail.com EMAIL_HOST_USER=your_email@example.com EMAIL_HOST_PASSWORD=your_app_password
- Load the .env file in settings.py:
import environ env = environ.Env() environ.Env.read_env() EMAIL_HOST = env('EMAIL_HOST') EMAIL_HOST_USER = env('EMAIL_HOST_USER') EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')