pythondjangoauthenticationweb-applicationsemail-verification

Email verification in Django


I am having a web-app in Django. I tried using the tokengenerator for password reset to create a verification mail, it's not activating the email.

Coming to the problem:

  1. While the user provides email, it should check whether the email is present in the DB. (DB will be updated with user emails)
  2. After verifying whether the email is present in the DB, the user is prompted to create a password.
  3. After creating a password user can log in to the respective page.

Is there any solution? I tried and followed:

https://medium.com/@frfahim/django-registration-with-confirmation-email-bb5da011e4ef

The above post helped me to send the email, but the user is not activated after verifying the email. The post doesn't meet my requirement, though I tried to check whether email verification is possible.

Is there any third-party module for Django or any solution for the requirements I have mentioned?


Solution

  • I figured out a solution , but for the second requirement user has to input the password at the time of account creation . The main goal was to verify the user supplied email.

    Models

    class Yourmodel(models.Model):
        first_name = models.CharField(max_length=200)
        second_name = models.CharField(max_length=200)
        email = models.EmailField(max_length=100)
    

    Tokens

    from django.contrib.auth.tokens import PasswordResetTokenGenerator
    from django.utils import six
    class TokenGenerator(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 = TokenGenerator()
    

    Views

    from django.contrib.auth import get_user_model
    from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
    from django.contrib.sites.shortcuts import get_current_site
    from .tokens import account_activation_token
    from django.core.mail import send_mail
    from django.utils.encoding import force_bytes
    from django.template.loader import render_to_string
    
    def signup(request):
        User = get_user_model()
        if request.method == 'POST':
            form = SignupForm(request.POST)
            if form.is_valid():
                email = form.cleaned_data.get('email')
                if Yourmodel.objects.filter(email__iexact=email).count() == 1:
                    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('email_template.html', {
                                'user': user,
                                'domain': current_site.domain,
                                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                                'token': account_activation_token.make_token(user),
                            })
                    to_email = form.cleaned_data.get('email')
                    send_mail(mail_subject, message, 'youremail', [to_email])
                    return HttpResponse('Please confirm your email address to complete the registration')
         else:
            form = SignupForm()
        return render(request, 'regform.html', {'form': form})
    
    def activate(request, uidb64, token):
        User = get_user_model()
        try:
            uid = force_text(urlsafe_base64_decode(uidb64))
            user = User.objects.get(pk=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!')
    
    

    Forms

    from django.contrib.auth.forms import UserCreationForm
    
    
    class SignupForm(UserCreationForm):
        class Meta:
            model = User
            fields = ('username', 'email', 'password1', 'password2')
    

    Email Template

    {% autoescape off %}
    Hi ,
    Please click on the link to confirm your registration,
    http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
    {% endautoescape %}
    

    regform.html

    {% csrf_token %}
    {% for field in form %}
    <label >{{ field.label_tag }}</label>
    {{ field }}
    {% endfor %}
    

    If you don't want to compare with email address in your model you can skip, this will send the email to the email address which was supplied at the time registration without further validation.

    email = form.cleaned_data.get('email')
    if Yourmodel.objects.filter(email__iexact=email).count() == 1: