Add Email Functionality to a Django User Registration

Skolo Online Learning
Nerd For Tech
Published in
6 min readFeb 15, 2021

User registration and authentication is a crucial pat of any web application, to complete the process system emails are required to aid communication with the client. In this article we are going to add email functionality to a Django user registration process.

When a user creates an account on your web application, you might want to send them an email when:

  • They successfully create an account
  • They request to reset a password
  • Some significant change happens on their profile
  • Send then communication messages
  • 2 Factor authentication, a second code every time they log in for increased security
  • Any other reason you need communication on
Add email functionality to Django user registration process

HTML Emails and Templates

We are going to be sending HTML email types in addition to the standard plain-text email types. Read more about sending emails from Django on the Django documentation page: https://docs.djangoproject.com/en/3.1/topics/email/

We are assuming you already have a Django project and user registration process designed — check out our previous articles on this: https://skolo-online.medium.com/python-django-user-registration-login-logout-custom-styling-c2f2901e162a

Get an email HTML template

Visit: https://github.com/mailchimp/email-blueprints/tree/master/templates to get an email template you can use based on your requirements.

Email templates work in a similar way to page HTML templates in Django. You can pass data to the HTML using a context object, and access that data in double curly braces:

Inside your HTML template

<h1>{{object.title}}</h1>
<h2>{{object.subtitle}}</h2>

Data that you will send to the template in JSON format:

{
"object": { "title": "this is a title", "subtitle": "this is a subtitle" }
}

Get an email hosting account and add config to settings file

Send Django Emails

The next step is to get an email hosting account or you could use an existing one, you will need: (1) the mail server, (2) mail username and (3) mail password to access the account.

Once you have these details — add them to your settings.py file at the bottom of the file like so:

. . . . . .  
#Email settings details
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'mail.careers-portal.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = 'no-reply@careers-portal.com'
EMAIL_HOST_PASSWORD = '************'
. . . . . . .

Building the sendMail function

Creating the email data:

email = {
"title": "Thank your for registering with Careers Portal",
"shortDescription": "Welcome to Careers Portal, South Africa's Leading Job
Search Engine. These are the next steps.",
"subtitle": "Careers Portal - Start your job search process today",
"message": "You have successfully registered with Careers Portal. You can
now login in to your profile and start creating a profile. We have
thousands of jobs just waiting for you to apply. If you experience any
issues feel free to contact our support at support@careers-portal.co.za.>
}
subject = '[Careers Portal] Welcome to Careers Portal'
to_email = 'anyemail@gmail.com"

This is all the data we will need for now, we then need to create the email function as seen below. The function takes in the data as specified above.

def sendEmail(email, subject, to_email):    from_email = settings.EMAIL_HOST_USER    text_content = """
{}
{} {} regards,
Careers Portal Support
""". format(email['shortDescription'], email['subtitle'], email['message'])
html_c = get_template('basic-email.html')
d = { 'email': email }
html_content = html_c.render(d)
msg = EmailMultiAlternatives(subject, text_content, from_email, to_email)
msg.attach_alternative(html_content, 'text/html')
msg.send()

Now that we know what the function should look like, let us apply this function in an existing view function — inside of our python Django project. For this we will work with a ‘forgot-email’ function.

This function will power the process behind, enabling a user to reset their password. We will just reset to a new password, and send the user the new password via email.

The following is required:

  1. A HTML file with a form a user can use to request the password reset
  2. A form to be served in the HTML file above
  3. A view function to process this request
  4. An update to the URLS file — to include a new url for ‘forgot-password’

Create the HTML file that will serve the request

You can use any template for this, and inside of the template you will have a form. This form will have just one field — an email field. This is all we need from the user — their email, so we can search the database and pull up their profile if it exists:

<form class="login-form" method="POST">{% csrf_token %}<div class="row"><div class="col-12 text-center"><p>Let us find your account first, enter the email address associated with the account below:</p></div><div class="col-lg-12"><div class="form-group position-relative"><label>Enter Email <span class="text-danger">*</span></label>{{form.email}}</div>{% if form.email.errors %}{% for error in form.email.errors %}<div class="alert alert-danger"><strong>{{ error|escape }}</strong></div>{% endfor %}{% endif %}</div><div class="col-lg-12 mb-0"><button class="btn btn-primary w-100" type="submit">Recover Password</button></div><div class="col-12 text-center"><p class="mb-0 mt-3"><small class="text-dark mr-2">Create a new account ?</small> <a href="{% url 'register' %}" class="text-dark font-weight-bold">Register</a></p></div></div></form>

Forgot email Form

Inside of your forms.py file — we need to add a new form at the bottom of the file. This is the form that will be rendered inside of the HTML file above. Ensure you have these imports — the forms, and User class.

from django import formsfrom django.contrib.auth.models import User...
.
.
.
.
....
class ForgotForm(forms.ModelForm):email = forms.EmailField(max_length=100,required = True,help_text='Enter Email Address',widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Email'}),)class Meta:model = Userfields = ['email']

Creating the forgot view

Inside the views.py file — add the following lines of code to process the view:

from .functions import WelcomeEmail, sendEmail, ForgotEmail
from uuid import uuid4
from django.conf import settings
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from django.contrib import messages
...
.
.
.
.
...
def forgot(request):if request.method == 'POST':form = ForgotForm(request.POST)if form.is_valid():user_email = request.POST['email'].lower().replace(' ', '')u = User.objects.get(email=user_email)if u is not None:new_pass = str(uuid4()).split('-')[4]forgot = ForgotEmail(new_pass)
#Send the Forgot Email . . .to_email = u.emaile_mail = forgot.email()sendEmail(e_mail, forgot.subject, [to_email])u.set_password(new_pass)u.save()messages.success(request, 'Your password has been reset, check your email for more details')return redirect('login')else:messages.error(request, 'We could not find a user with matching email')return redirect('home_page')else:messages.error(request, 'Error Processing Your Request')context = {'form': form}return render(request, 'forgot.html', context)if request.method == 'GET':form = ForgotForm()context = {'form': form}return render(request, 'forgot.html', context)return render(request, 'forgot.html', {})

What we are doing in this function, within the POST option is the following:

(1) We declare the form variable, with the request.Post argument

form  = ForgotForm(request.POST)

We check if the form is valid before we continue, then we use the submitted email to check if a user exists with that email. If a user exists, we continue. We create a password using uuid4 (*Make sure you install this and import it at the top of the file).

After creating the new password, we send the email with the new password to the client, then we update the password on the system. Finally we redirect the user to the login page.

You can see here that we are importing a forgotEmail class and calling the function from somewhere else. We wrote these functions in a separate file.

forgot = ForgotEmail(new_pass)
sendEmail(e_mail, forgot.subject, [to_email])

Create a new file called functions.py and paste the code below. Then make sure you are importing the file at the top of the view.py file.

Inside the functions.py

from django.conf import settingsfrom django.core.mail import EmailMultiAlternativesfrom django.template.loader import get_templateclass ForgotEmail():def __init__(self, new_pass):self.new_pass = new_pass
subject = '[Careers Portal] Forgot your password'def email(self):return {"title": "Your password has been reset","shortDescription": "You have requested a new password","subtitle": "Please find your new password attached for Careers Portal","message": "Your new password is: {}. If you did not request this new password, please contact support@careers-portal.co.za immediately. Othewise, kindly login to your profile with your new password. If you have any challenges, send an email to admin@careers-portal.co.za."}
def sendEmail(email, subject, to_email):from_email = settings.EMAIL_HOST_USERtext_content = """{}{}{}regards,Careers Portal Support""". format(email['shortDescription'], email['subtitle'], email['message'])html_c = get_template('basic-email.html')d = { 'email': email }html_content = html_c.render(d)msg = EmailMultiAlternatives(subject, text_content, from_email, to_email)msg.attach_alternative(html_content, 'text/html')msg.send()

Full Video Tutorial — Add Email Functionality to a Django User Registration

--

--

Skolo Online Learning
Nerd For Tech

Founder of Tati Digital, passionate about digital transformation and ushering businesses in to the digital age and 4th industrial revolution.