Sending Emails in Django

Automate sending emails to users heyylateef | Mar 02 2022

Wouldn't it be great if you can automatically send emails to users on your website? How about sending emails for free? With leveraging our free Gmail account, you can send emails from our Django website! In this tutorial, we'll learn how to send emails using Gmail and Django. As a test, we'll be sending an email to ourselves from our site.


1. Project Setup

Lets setup our normal Django project. In your terminal, enter the following command:

$ django-admin startproject sendemail
$cd sendmail
$ python manage.py startapp emailapp


2. Edit your settings.py and urls.py files

We need to configure our settings before we continue. Inside of sendemail/settings.pyplug in the newly created app into INSTALLED_APPS:

# sendemail/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'emailapp',
]



At the bottom of the settings file, we'll setup our Django project to utilize Gmail email backend. (We'll update the user and password fields later in this tutorial). Enter the following:

# sendemail/settings.py
#Email settings, preconfigured for Gmail
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = "smtp.gmail.com"
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = "your-gmail@gmail.com"
EMAIL_HOST_PASSWORD = "your-password"


Open sendemail/urls.py. Lets configure our project's url patterns. Enter the following:

# sendemail/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('', include('emailapp.urls')),
]



3. Creating our views

Our main functions are going to render and handle a contact form submit, and execute Django's 'sendmail" method. Copy and paste the following in your views.py:

# sendemail/emailapp/views.py
from django.shortcuts import render
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.contrib import messages
from .forms import ContactForm
from django.conf import settings

def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
name = form.cleaned_data.get('name')
message = form.cleaned_data.get('message')
email_inquiry(name=name, email=email, message=message, subject="Lab Tutorials")
messages.success(request, message="Email was sent successfully!")
return render(request, 'emailapp/contact.html', {'form':form,})
else:
messages.error(request, "Error processesing emails, please try again")
return render(request, 'emailapp/contact.html', {'form':form,})
else:
form = ContactForm()
if 'submitted' in request.GET:
submitted = True
return render(request, 'emailapp/contact.html', {'form':form,})

def email_inquiry(name, email, message, subject):
msg_plain = render_to_string('emailapp/email_inquiry.txt', {'contactName':name, 'contactEmail':email, 'contactMessage':message,})
msg_html = render_to_string('emailapp/email_inquiry.html', {'contactName':name, 'contactEmail':email, 'contactMessage':message,})
send_mail(subject=subject,message=msg_plain,from_email=settings.EMAIL_HOST_USER, recipient_list=[settings.EMAIL_HOST_USER], html_message=msg_html)

4. Setting up our form

Inside your app, create a file named forms.py. We would want to have a separate file for configuring our form. Paste the following in the file:

# sendemail/emailapp/forms.py
from django import forms
from django.forms import ModelForm


class ContactForm(forms.Form):
name = forms.CharField(required=True, widget=forms.TextInput(attrs={'class': 'form-control'}))
email = forms.EmailField(label="Your email address", required=True, widget=forms.EmailInput(attrs={"class": "form-control"}))
message = forms.CharField(label="Type your message...", required=True, widget=forms.Textarea(attrs={'class': 'form-control', 'rows':'5'}))


5. Setup our app's url patterns

Create a new file within our app named urls.py. Paste the following in the file:

# sendemail/emailapp/urls.py
from django.urls import path
from django.conf import settings
from . import views
from django.conf.urls.static import static

urlpatterns = [
path('', views.contact, name='contact'),

]


6. Templates

Inside your app's folder, create another folder: templates/emailapp. Inside this new folder, create 5 files:

  1. base.html
  2. contact.html
  3. email_base.html
  4. email_inquiry.html
  5. email_inquiry.txt

Copy and paste the following for each file:

base.html

{# HTML5 declaration #}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{% load static %}
<!-- Bootstrap 5 CDN -->
<!-- Latest compiled and minified CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">

<!-- Latest compiled JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>

<title>{% block title %}Follow me @heyylateef{% endblock title %}</title>
<header>
{# Navigation Menu #}
</header>
</head>
<body>
{# The Document Body #}
<div class = "container">
{% if messages %}
{% for message in messages %}
{% if message.tags == 'success'%}
<div class="alert alert-success alert-dismissible">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'info'%}
<div class="alert alert-info alert-dismissible">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'warning'%}
<div class="alert alert-warning alert-dismissible">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'error'%}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
<strong>{{message}}</strong>
</div>
{% endif %}
{% endfor %}
{% endif %}
</div>
<div class="container">
{% block content %}
if you see this, something is wrong!
{% endblock content %}
</div>
{# The Footer #}
<div class="footer-basic">
</div>



{% block javascript %}
{% endblock javascript %}
</body>
</html>


contact.html

{% extends 'emailapp/base.html' %}
{% load static %}


{% block content %}

<section class="page-section" id="about">
<div class="container pt-5">
<div class="row justify-content-center">
<div class="col-lg-8 text-center">
<h2 class="mt-0">Contact Form!</h2>
<hr class="divider light my-4" />
<div class="col-lg-8 text-left">
</div>
</div>
</div>
</div>
<div class="container pb-5">
{% if submitted %}
<p class="success">
Your request was submitted successfully.
</p>
{% else %}
<form action="" method="post" novalidate>
{{form.as_table}}
<div class="col pt-3">
<input type="submit" class="btn btn-success" name="Submit">
</div>
{% csrf_token %}
</form>
{% endif %}
</section>

{% endblock %}

email_base.html

{# HTML5 declaration #}
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<!-- Font Awesome (free icons) -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">

<title>{% block title %}Lateef Lab{% endblock title %}</title>
</head>
<body>
<style>
</style>
<header>
{# Navigation Menu #}
</header>
{# The Document Body #}
<div class = "container mt-5">
{% if messages %}
{% for message in messages %}
{% if message.tags == 'success'%}
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'info'%}
<div class="alert alert-info alert-dismissible">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'warning'%}
<div class="alert alert-warning alert-dismissible">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{message}}</strong>
</div>
{% elif message.tags == 'error'%}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{message}}</strong>
</div>
{% endif %}
{% endfor %}
{% endif %}
</div>

<div class="container-fluid p-0">
{% block content %}
<!--if you see this, something is wrong!-->
{% endblock content %}
</div>
{# The Footer #}
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>

<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

email_inquiry.html

{% extends "emailapp/email_base.html" %}
{% block content %}
<table class="body-wrap" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; width: 100%; background-color: #f6f6f6; margin: 0;">
<tbody>
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<div class="content" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; max-width: 600px; display: block; margin: 0 auto; padding: 20px;">
<tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<table width="100%" cellpadding="0" cellspacing="0" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<tbody><tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
Here is a review of your inquiry:
</td>
</tr>
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
Name: {{contactName}}
</td>
</tr>
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
Email: {{contactEmail}}
</td>
</tr>
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
{{contactMessage}}
</td>
</tr>
<tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
<td class="content-block" style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0; padding: 0 0 20px;" valign="top">
<b>Lateef Lab</b>
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</div>
</tr>
</tbody>
</table>
{% endblock content %}

email_inquiry.txt


Name: {{contactName}}


Email: {{contactEmail}}

{% if contactDate %}
Date: {{contactDate}}
{% endif %}


{{contactMessage}}
© 2022 Lateef Lab



7. Setup Gmail App Password

On your computer, go to gmail.com and login. Once logged in, on the top right corner of the window, click on your Gmail profile picture and click "Mange your Google Account"



Next, look at the left hand navigation menu. Click "Security", then "App passwords". Note: you will need to set up 2 step verification on your Gmail to have the ability to create app passwords.



Sign in again



In the 2-Step Verification page, scroll to the bottom and click on "App Passwords".


In the App Password window, click on the dropdown menu and select "Other". Then create a new for your new app password. Click "Generate".



Now, here is your app password! Copy and paste the app password in your settings.py file as the value of the EMAIL_HOST_PASSWORD variable. (Note: please keep this password safe, you should read this password as an environment variable)




8. Updating settings.py

Go back to your settings.py file, update the following variables with your gmail account and app password as strings:

EMAIL_HOST_USER = "your-gmail@gmail.com"
EMAIL_HOST_PASSWORD = "ilzqfprjffmfovvi"


9. Lets test our app!

Lets (finally) test our app! We'll run migrations and run it locally. In your terminal, enter the following commands:

$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver

Go to localhost:8000. You'll see en empty form, go ahead and fill it out and submit it!



If your form was valid, you should notice the web page will reload and display a success message at the top of the screen.



At last, lets check our Gmail. You should see a similarly rendered email in your inbox (from yourself).



Thats it! You've learned how to use Gmail with Django to send emails from your site (and for free). Check out the GitHub repo!

About The Lab

Like the content posted on this site? Need help with another web project? Want to give some feedback? Feel free to contact me via email or social media!

Know more!
DigitalOcean Referral Badge