How To Send Emails With Django (Contact Form Example)

Viktor Nagornyy
Powered by Django
Published in
5 min readMay 16, 2023

--

Send emails in Django

When you’re building a product powered by Django, you need to be able to send emails to communicate important information with your users.

For example, if you use Django Allauth for user management and social authentication , you need Django to send system emails to your users — sign up, lost password, email verification, and more. Plus, you need a contact form for visitors and users to contact you. That’s what we’ll build today.

We will use the Django Anymail package to send emails via an API. Anymail integrates several transactional email service providers (ESPs) into Django, allowing you to switch between ESPs with just a setting change. Here, we will focus on using Postmark due to its high deliverability and rich features. I use this for all my mission-critical emails to ensure users get them.

If you’re starting to build a Django app, consider the Pegasus SaaS boilerplate. This is what I use to start Django projects. It includes Django Anymail (and many other packages) already integrated and custom HTML email templates to match the UI. Instead of wasting time building everything from scratch, Pegasus can help you hit the ground running so you can build and launch your app within days.

Before we begin

This article assumes you already have Python and Django installed using pipenv. If you need help installing Django, here are two resources:

Step 1: Installing Django Anymail

To install Django Anymail, use the following pipenv command:

pipenv install django-anymail[postmark]

If you want to use another ESP, change [postmark] to the one you want.

Step 2: Configure Django Anymail with Postmark

To set up Django Anymail with Postmark, you must add anymail to your INSTALLED_APPS in your Django settings and configure the Anymail email backend. I like to use Django Environ to manage settings, so we’ll use that.

In your Django settings.py, add the following:

import environ

env = environ.Env()

INSTALLED_APPS = [
... # other apps
"anymail",
]

ANYMAIL = {
"POSTMARK_SERVER_TOKEN": env('POSTMARK_SERVER_TOKEN'),
}

EMAIL_BACKEND = "anymail.backends.postmark.EmailBackend"
DEFAULT_FROM_EMAIL = env('DEFAULT_FROM_EMAIL') # default from email

Replace 'POSTMARK_SERVER_TOKEN' with your actual Postmark server API token, and 'DEFAULT_FROM_EMAIL' with the email you'd like to send from by default. The email domain must be verified in Postmark; otherwise, emails will be rejected. Both these values should be placed in your .env file as per Django-environ setup.

Please note, if you enable debugging DEBUG=True , then Django DEFAULT_FROM_EMAIL will be webmaster@localhost and this will cause your ESP to reject emails. Disable debugging to use the correct email. If your Django isn’t sending emails, this is why.

Step 3: Sending an email

With Django Anymail and Postmark set up, you can send an email using Django’s standard send_mail function. Here's an example:

from django.core.mail import send_mail

send_mail(
'Hello from Django', # subject
'This is a test email.', # message
None, # from email (uses DEFAULT_FROM_EMAIL if None)
['recipient@example.com'], # recipient list
)

Contact Us Form Example

Let’s integrate the email-sending functionality with a simple “Contact Us” form. The form will include “Name,” “Email,” “Subject,” and “Message” fields.

First, create the form in your Django app’s forms.py file:

from django import forms

class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)

Then, you need to handle this form in your app’s view file views.py:

from django.core.mail import send_mail
from django.shortcuts import render

from .forms import ContactForm

def contact_us(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
send_mail(
form.cleaned_data['subject'], # subject
f"Message from {form.cleaned_data['name']} <{form.cleaned_data['email']}>\n\n"
f"{form.cleaned_data['message']}", # message
None, # from email
['your-email@example.com'], # replace with your email
)
return render(request, 'contact_us_success.html')
else:
form = ContactForm()

return render(request, 'contact_us.html', {'form': form})

Finally, you need to create the Django template contact_us.html for the form, which you can include inside your base.html.

Let’s start with the form template first:

{% extends "base.html" %}

{% block content %}
<h1>Contact Us</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Send</button>
</form>
{% endblock content %}

In the contact_us.html, {% extends "base.html" %} tells Django that this template "extends" the base.html template. The {% block content %} in contact_us.html corresponds to the same-named block in the base.html file. When Django renders this page, it will replace the {% block content %} in base.html with the content defined inside {% block content %} in contact_us.html.

Now, here’s a sample base.html to complete our example:

<!DOCTYPE html>
<html>
<head>
<title>My Django Site</title>
<!-- Add CSS and JavaScript files here -->
</head>
<body>
<header>
<!-- Navigation goes here -->
</header>

<main>
{% block content %}
{% endblock content %}
</main>

<footer>
<!-- Footer content goes here -->
</footer>
</body>
</html>

In the above base.html, the {% block content %}{% endblock content %} is a placeholder where child templates can insert their content. This is where the form will be shown.

That’s it! You have now successfully integrated Django with Anymail and Postmark to send emails and created a contact us form that sends an email upon submission.

This is a lot of work for every single project. That’s why I prefer to use Pegasus to jumpstart every Django project.

New To Django?

If you’re new to Django, as I was, you may be looking for good resources to learn how to use Django to build apps. The best resources that helped me learn Django with easy-to-follow instructions and code are the three ebooks written by William S. Vincent (he keeps them up-to-date):

Django for Beginners laid a solid foundation for me to pick up all other Django (and Python) concepts. Start with that ebook. That’s what I did.

If you want to be notified of new stories related to Django, follow Powered by Django here on Medium, or you can follow me to learn more about digital marketing in addition to Django.

This article includes affiliate links.

--

--

Viktor Nagornyy
Powered by Django

📈 Marketing consultant. 14 years helping biz generate leads & sales. Open source advocate. Sign up for my marketing coaching newsletter ➡️ inboundmethod.com/m