Do you like my work and want to support me?
- Python >= 3.8
- Django >= 3.1
You can install by:
pip3 install django-email-verification
and import by:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
...
'django_email_verification', # you have to add this
]
You have to add these parameters to the settings, you have to include all of them except the last one:
def verified_callback(user):
user.is_active = True
EMAIL_VERIFIED_CALLBACK = verified_callback
EMAIL_FROM_ADDRESS = '[email protected]'
EMAIL_MAIL_SUBJECT = 'Confirm your email'
EMAIL_MAIL_HTML = 'mail_body.html'
EMAIL_MAIL_PLAIN = 'mail_body.txt'
EMAIL_TOKEN_LIFE = 60 * 60
EMAIL_PAGE_TEMPLATE = 'confirm_template.html'
EMAIL_PAGE_DOMAIN = 'http://mydomain.com/'
EMAIL_MULTI_USER = True # optional (defaults to False)
# For Django Email Backend
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'mYC00lP4ssw0rd' # os.environ['password_key'] suggested
EMAIL_USE_TLS = True
In detail:
EMAIL_VERIFIED_CALLBACK
: the function that will be called when the user successfully verifies the email. Takes the user object as argument.EMAIL_FROM_ADDRESS
: this can be the same asEMAIL_HOST_USER
or an alias address if required.EMAIL_MAIL_
:SUBJECT
: the mail default subject.HTML
: the mail body template in form of html.PLAIN
: the mail body template in form of .txt file.
EMAIL_TOKEN_LIFE
: the lifespan of the email link (in seconds).EMAIL_PAGE_TEMPLATE
: the template of the success/error view.EMAIL_PAGE_DOMAIN
: the domain of the confirmation link (usually your site's domain).EMAIL_MULTI_USER
: (optional) ifTrue
an error won't be thrown if multiple users with the same email are present ( just one will be activated)
For the Django Email Backend fields look at the official documentation.
The EMAIL_VERIFIED_CALLBACK
can be a function on the AUTH_USER_MODEL
, for example:
EMAIL_VERIFIED_CALLBACK = get_user_model().verified_callback
The function will receive no arguments.
The EMAIL_MAIL_SUBJECT
should look like this ({{ link }}
(str
), {{ expiry }}
(datetime
) and user
(Model
) are
passed during the rendering):
EMAIL_MAIL_SUBJECT = 'Confirm your email {{ user.username }}'
The EMAIL_MAIL_HTML
should look like this ({{ link }}
(str
), {{ expiry }}
(datetime
) and user
(Model
) are
passed during the rendering):
<h1>You are almost there, {{ user.username }}!</h1><br>
<h2>Please click <a href="{{ link }}">here</a> to confirm your account</h2>
<h2>The token expires on {{ expiry|time:"TIME_FORMAT" }}</h2>
The EMAIL_MAIL_PLAIN
should look like this ({{ link }}
(str
), {{ expiry }}
(datetime
) and user
(Model
) are
passed during the rendering):
You are almost there, {{ user.username }}!
Please click the following link to confirm your account: {{ link }}
The token expires on {{ expiry|time:"TIME_FORMAT" }}
The EMAIL_PAGE_TEMPLATE
should look like this ({{ success }}
(bool
), {{ user }}
(Model
)
and {{ request }}
(WSGIRequest
) are passed during the rendering):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Confirmation</title>
</head>
<body>
{% if success %}
{{ user.username }}, your account is confirmed!
{% else %}
Error, invalid token!
{% endif %}
</body>
</html>
After you have created the user you can send the confirm email
from django.shortcuts import render
from django.contrib.auth import get_user_model
from django_email_verification import send_email
def my_functional_view(request):
...
user = get_user_model().objects.create(username=username, password=password, email=email)
user.is_active = False # Example
send_email(user)
return render(...)
send_email(user)
sends an email with the defined template (and the pseudo-random generated token) to the user.
IMPORTANT: You have to manually set the user to inactive before sending the email.
If you are using class based views, then it is necessary to call the superclass before calling the send_confirm
method.
from django.views.generic.edit import FormView
from django_email_verification import send_email
class MyClassView(FormView):
def form_valid(self, form):
user = form.save()
returnVal = super(MyClassView, self).form_valid(form)
send_email(user)
return returnVal
There are two ways to get the token verified:
-
The first one is the simplest: you just have to include the app urls in
urls.py
from django.contrib import admin from django.urls import path, include from django_email_verification import urls as email_urls # include the urls urlpatterns = [ path('admin/', admin.site.urls), ... path('email/', include(email_urls)), # connect them to an arbitrary path ]
When a request arrives to
https.//mydomain.com/email/<token>
the package verifies the token and:- if it corresponds to a pending token it renders the
EMAIL_PAGE_TEMPLATE
passingsuccess=True
and deletes the token - if it doesn't correspond it renders the
EMAIL_PAGE_TEMPLATE
passingsuccess=False
- if it corresponds to a pending token it renders the
-
The second one is more customizable: you can build your own view for verification, mark it as
@verify_view
, verify the token manually with the functionverify_token(token)
and execute your custom logic, here's how:### For the view from django.http import HttpResponse from django_email_verification import verify_view, verify_token @verify_view def confirm(request, token): success, user = verify_token(token) return HttpResponse(f'Account verified, {user.username}' if success else 'Invalid token') ### For the urls from django.urls import path urlpatterns = [ ... path('email/<str:token>/', confirm), # remember to set the "token" parameter in the url! ... ]
IMPORTANT: the path must NOT have the
name
attribute setThe library makes sure one and only one
@verify_view
is present and throws an error if this condition is not met.
If you want to use the console email backend provided by django, then define:
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
You can use all the django email backends and also your custom one.
You can define a custom salt to be used in token generation in your settings file. Simply define:
CUSTOM_SALT = 'xxxxxxxxxxxxxxxxxxxxxxx'
in your settings.py.
Logo by by Filippo Veggo
Usage of the Django trademarks are subject to the Django Trademark licensing Agreement."