Send Verification Email on registration on Django Web app

This article is going to cover how to register with email verification in Django.

So, Let’s start!

Assume that I have a project named user_registration and it contains an app named accounts.

At first, we need to configure our email server. So, got to user_registration/setting.py and write the following lines:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'  
MAILER_EMAIL_BACKEND = EMAIL_BACKEND
EMAIL_HOST = 'your_mail_server'
EMAIL_HOST_PASSWORD = 'your_password'
EMAIL_HOST_USER = 'your_email'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

To test the above configuration work, open up the terminal and navigate to user_registration project and run following command:

$ python manage.py shell
>>> from django.core.mail import send_mail
>>> send_mail( 'Subject here', 'Here is the message.', 'me@example.com', ['example@gmail.com'], fail_silently=False, )

It will return 1 as a status code. Then check your mail, a mail will arrive.

Now create a form in accounts/templates/accounts/signup.html and write the following code:

<!DOCTYPE html>  
<html lang="en">
<head>
<title>Signup</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="container" style="margin-top: 50px;">
<div class="row justify-content-center">
<div class="col-md-5 shadow-sm p-3 mb-5 bg-white rounded">
<h2>Signup</h2>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="first_name">First Name:</label>
<input type="text" class="form-control" id="first_name" placeholder="Enter first name"
name="first_name">
</div>
<div class="form-group">
<label for="last_name">Last Name:</label>
<input type="text" class="form-control" id="last_name" placeholder="Enter last name"
name="last_name">
</div>
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter username" name="username">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" name="email">
</div>
<div class="form-group">
<label for="pwd1">Password:</label>
<input type="password" class="form-control" id="pwd1" placeholder="Enter password" name="password1">
</div>
<div class="form-group">
<label for="pwd2">Confirm Password:</label>
<input type="password" class="form-control" id="pwd2" placeholder="Reenter password"
name="password2">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>

Now create a form in accounts/templates/accounts/acc_active_email.html and write the following code:

{% autoescape off %}  
Hi {{ user.username }},
Please click on the link to confirm your registration,
http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
If you think, it's not you, then just ignore this email.
{% endautoescape %}

Now open up accounts/urls.py and write the following path:

from django.urls import path  
from accounts import views
urlpatterns = [
path('signup/', views.signup, name="signup"),
path('activate/<uidb64>/<token>/',views.activate, name='activate'),
]

Now open up accounts/tokens.py and write the following code:

from django.contrib.auth.tokens import PasswordResetTokenGenerator  
from django.utils import six
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp) +
six.text_type(user.is_active)
)
account_activation_token = AccountActivationTokenGenerator()

Now open up accounts/forms.py and write the following code:

from django.contrib.auth.forms import UserCreationForm  
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'username')

Now open up accounts/views.py and write the following code:

from django.http import HttpResponse  
from django.shortcuts import render
from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes, force_text
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.template.loader import render_to_string
from .forms import SignUpForm
from .tokens import account_activation_token
from django.contrib.auth.models import User
from django.core.mail import EmailMessage
def signup(request):
if request.method == 'GET':
return render(request, 'accounts/signup.html')
if request.method == 'POST':
form = SignUpForm(request.POST)
# print(form.errors.as_data())
if form.is_valid():
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
mail_subject = 'Activate your account.'
message = render_to_string('accounts/acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.id)).decode(),
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data.get('email')
email = EmailMessage(
mail_subject, message, to=[to_email]
)
email.send()
return HttpResponse('Please confirm your email address to complete the registration')
else:
form = SignUpForm()
return render(request, 'accounts/signup.html', {'form': form})
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(id=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
else:
return HttpResponse('Activation link is invalid!')

When user signup, is_active set to False that means user set to inactive during signup process. By render_to_string() method which data/ value send over conext. Here, data/ value send overaccounts/acc_active_email.html and userdomainuid, and token data as context data.

Convert uid into text. Then, find user object by uid. Now check account_activation_token.check_token(user, token) to check is this match with previously creaed token. If match the user.is_active set to True.

Comments

Popular posts from this blog

Documentation is Very vital before you develop any system or app

Steps followed when creating a new software

Everything you need to know when developing an on demand service app