{"id":14972743,"url":"https://github.com/knownbug06/Django-Verify-Email","last_synced_at":"2026-01-09T23:04:38.636Z","repository":{"id":38889422,"uuid":"300864149","full_name":"foo290/Django-Verify-Email","owner":"foo290","description":"A two-step verification for new accounts by verifying email.","archived":false,"fork":false,"pushed_at":"2024-08-10T09:50:25.000Z","size":300,"stargazers_count":104,"open_issues_count":27,"forks_count":33,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-30T06:21:44.239Z","etag":null,"topics":["account-activation","django","django-application","django-project","djangoapp","email","email-verification","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/foo290.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-03T11:27:29.000Z","updated_at":"2024-10-22T07:25:04.000Z","dependencies_parsed_at":"2024-06-19T05:18:23.751Z","dependency_job_id":"7ee2eff9-b8b6-43cc-996d-988653e84b56","html_url":"https://github.com/foo290/Django-Verify-Email","commit_stats":{"total_commits":81,"total_committers":13,"mean_commits":6.230769230769231,"dds":0.5308641975308642,"last_synced_commit":"725e77a1e204aa1139a335083e80f620cedf2154"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo290%2FDjango-Verify-Email","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo290%2FDjango-Verify-Email/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo290%2FDjango-Verify-Email/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo290%2FDjango-Verify-Email/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foo290","download_url":"https://codeload.github.com/foo290/Django-Verify-Email/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247393569,"owners_count":20931812,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["account-activation","django","django-application","django-project","djangoapp","email","email-verification","python"],"created_at":"2024-09-24T13:47:27.922Z","updated_at":"2026-01-09T23:04:38.607Z","avatar_url":"https://github.com/foo290.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n\u003ch1 style='text-align:center'\u003eEmail-Verification for Django\u003c/h1\u003e\n\nEmail verification for new signups or new users is a two-step verification process and adds a layer for security for valid users.\n\n\u003cb\u003e verify_email \u003c/b\u003e is a django app that provides this functionality right of the bat without any complex implementation.\n\n\u003chr\u003e\n\n## Version Update (2.0.0):\n\n\u003chr\u003e\n\n\u003e This version contains breaking changes and is not compatible with the previous version 1.0.9\n\n### What's in this update\n**Features:**\n* Added feature for **re-requesting email** in case the previous email was lost or deleted by mistake\n* Added a variable `REQUEST_NEW_EMAIL_TEMPLATE` where user can specify his custom template for requesting email again. More on this \u003ca href='#resending-email-using-form'\u003ehere\u003c/a\u003e.\n* Added a Django form for requesting email with a field `email`.\n\nRead about this feature \u003ca href='#resending-email-using-form'\u003ehere\u003c/a\u003e\n\n**Bug Fixes:**\n* Fixed a bug where the user was not able to request a new email using the previous link in case if the link expires.\n \n **Others**\n * Using exceptions instead of normal string errors\n * code cleanup\n\n\u003chr\u003e\u003chr\u003e\n\n## The app takes care of :\n* Settings user's is_active status to False.\n* Generate hashed token for each user.\n* Generate a verification link and send it to the user's email.\n* Recieve a request from the verification link and verify for its validity.\n* Activating the user's account.\n\n## What you have to implement is :\n* Three steps in \u003ca href='#quickstart'\u003eQuick start\u003c/a\u003e below...\n\n\u003cb\u003eNote : \u003c/b\u003eThe app is designed to be used right of the bat, however, further customizations options are also provided in \u003ca href=\"#advance\"\u003eAdvance\u003c/a\u003e section below.\n\n\n## Installation\n\nNOTE: Don't forget to activate the virtual environment if you have one.\n\n```\npip install Django-Verify-Email\n```\n\n\u003cp id='quickstart'\u003e\n\u003ch2\u003eQuick start\u003c/h2\u003e \u003chr\u003e\n\u003c/p\u003e\n\nThe steps to getting started are very simple. Like any other app, this can be installed easily by adding \"verify_email\" in your installed apps like:\n\n\u003cb\u003eNote: \u003c/b\u003eThis documentation assumes that you already have a mail server configured for your project to send mails. \n\nif not, then your first step should be Step 0:\n\n### Step 0 :-\n\n--- Bypass this step if you already have these things set up for your project. ---\n\nIn your settings.py :\n```\nEMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'\nEMAIL_HOST = 'smtp.gmail.com'\nEMAIL_PORT = 587\nEMAIL_USE_TLS = True\nEMAIL_HOST_USER = os.environ.get('EMAIL_ID') \nEMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PW')\n\nDEFAULT_FROM_EMAIL = 'noreply\u003cno_reply@domain.com\u003e'\n```\n\n## Main steps... \u003chr\u003e\n\n### Step 1 :-\nAdd \"verify_email\" to your INSTALLED_APPS setting like this:\n```\n    INSTALLED_APPS = [\n        ...\n        \"verify_email.apps.VerifyEmailConfig\",\n    ]\n```\n\u003cp id=\"step2\"\u003e\n\u003ch3\u003eStep 2 :-\u003c/h3\u003e\n\nInclude the \"verify_email\" URLconf in your project urls.py like this:\n\n\n```\n\nurlpatterns = [\n\t...\n\tpath('verification/', include('verify_email.urls')),\t\n\n]\n```\n\u003c/p\u003e\n\n\u003cp id=\"step3\"\u003e\n\u003ch3\u003eStep 3 :-\u003c/h3\u003e\n\nApply migrations...\n\n\n```\npython manage.py migrate\n```\n\u003c/p\u003e\n\n\n\n### Step 4 :-\nFor sending email from a signup form, in your views.py import:\n\n```\n...\nfrom verify_email.email_handler import send_verification_email\n```\nNow in the function where you are validating the form:\n\n```\n...\n\ndef register_user(request):\n    ...\n    \n    if form.is_valid():\n\n        inactive_user = send_verification_email(request, form)\n```\n\n\u003cb\u003eAttention : \u003c/b\u003e\"send_verification_email()\" takes two arguments, requests and form in order to set user's active status. \n\nThe \"inactive_user\" that is returned by \"send_verification_email()\" contains a saved user object just like form.save() would do(with is_active status set as False), which you can further use to extract user information from cleaned_data dictionary, as shown below :\n\n```\ninactive_user.cleaned_data['email']\n\n# Output: test-user123@gmail.com\n```\nThe user is already being saved as inactive and you don't have to .save() it explicitly.\n\n\u003cb\u003eIf anything goes wrong in sending the verification link email, the user will not be saved, so that the user can try again.\u003c/b\u003e\n\n\n\n### At this point, you are good to go...\n Start the development server and signup with an email and you should be getting an email on the entered email with the default template for account activation. (You can provide your own HTML template. see \u003ca href='#advance'\u003eAdvance Section\u003c/a\u003e)\n\n \u003cb\u003eNote : \u003c/b\u003eThe app comes with default email templates which can be overriden. See \u003ca href='#customemailtemplate'\u003e Custom Email Templates\u003c/a\u003e\n\n# Verifying User's email : \n\n\u003ch3 style='text-align:center'\u003eNothing...\u003c/h3\u003e\u003cbr\u003e\n\nThat's right! , you don't have to implement any other code for validating users with their respective unique tokens and emails. \n\n\u003cb\u003eThe app takes care of everything in the background.\u003c/b\u003e\n\n* When the user clicks on the verification link, it comes to :\n    ```\n    path('verification/', include('verify_email')),\n    ```\n    which you defined in your project's urls.py in \u003ca href='#step2'\u003estep 2\u003c/a\u003e above.\n* This pattern is further extended in this app's urls.py where it accepts encoded email and encoded hashed tokens from the verification link.\n* It then checks for users by that email.\n* If the user exists, it then checks for a token if it is valid for that user or not.\n* If the token is valid, it activates the user's account by setting is_active attribute to True and last_login to timezone.now().\n* If the token is already been redeemed or modified, you'll be redirected to a \"verification failed\" page.\n\n#### This whole process from generating HMAC hashed token for each user to verify it for a unique user, is abstracted within the app 😃.\n\n\n\n\u003cp id=\"advance\"\u003e\n\n\u003ch1\u003eAdvance\u003c/h1\u003e\n\n\u003cp id=\"link-expiring\"\u003e\n\u003ch2\u003eExpiration of link and Resending emails :\u003c/h2\u003e\nIf you want your link to expire after a certain amount of time, you can use signed links, \u003cb\u003eAll you have to do is just set a variable in the settings.py file and BAMM! you got yourself a link that will expire after the specified time.\u003c/b\u003e\u003cbr\u003e\nIt's that simple, just setting a variable. \u003cbr\u003e\u003cbr\u003e\nIf you don't set this variable, the link will expire after being used at least once. \n\u003cbr\u003e\n\nThe link, by default, does not expire until it has been used at least once, however, you can \n**change** this behavior by specifying the time as\n\"EXPIRE_AFTER\" in settings.py. The variable can be set as :\n* By default the time is considered in seconds, so if you set \"EXPIRE_AFTER\" as an integer, that will be considered in seconds.\n* You can specify time unit for large times, max unit is days.\n* **Its very simple** just suffix the \"EXPIRE_AFTER\" variable's value with a time unit from [\"s\", \"m\", \"h\", \"d\"]. (Keep in mind, the \"m\" here is minutes, not month)\n\n**Example**\n\n* If I have to make a link expire after **one-day**, then I'd do:\n    * EXPIRE_AFTER = \"1d\"  # Will expire after one day from link generation\n\n* If I have to make a link expire after **one-hour**, then I'd do:\n    * EXPIRE_AFTER = \"1h\"  # Will expire after one hour from link generation\n    \n* If I have to make a link expire after **one-minute**, then I'd do:\n    * EXPIRE_AFTER = \"1m\"  # Will expire after 1 minute from link generation\n\n**Note:** By default, if you do not specify a unit, it'll be considered in seconds.\n\u003c/p\u003e\n\n\u003cp id=\"resending-email\"\u003e\n\u003ch2\u003eRe-Sending Email\u003c/h2\u003e \u003chr\u003e\n\u003c/p\u003e\n\nA user can request a new verification link **For a specific no. of times** in case the previous one has expired. By default, a user can request\nnew link **two times** which, obviously can be modified by you.\n\nSet a \"MAX_RETRIES\" variable in settings.py specifying the no. of times a user is allowed to request a new link.\n\nAfter that no. is exceeded, the user will be automatically redirected to an error page showing that you have maxed out.\n\n\u003cp id=\"resending-email-using-link\"\u003e\n\u003ch2\u003eRe-Sending Email using previous link\u003c/h2\u003e \n\u003c/p\u003e\nWhen the link expires, the user will be redirected to a page displaying that the link is expired and has a button to request a new email, now as long as the user hasn't exceeded max retries, the user can request a new email simply by clicking on that button.\n\n\u003cp id='resending-email-using-form'\u003e\n\u003ch2\u003eResend Email using Email Form\u003c/h2\u003e \n\u003c/p\u003e\n\nIn case when previous email/link is lost or deleted by the client, they can request a new email by specifying their email.\n\nThe path for that is `https://yourdomain/verification/user/verify-email/request-new-link/`, at this path, there will be a form that will ask for the email of the registered user.\n\nThe pathname is `request-new-link-from-email` which you can use to create a button on your front end and redirect traffic to the request email page.\nSomething like:\n\n```html\n\u003ca href=\"{% url 'request-new-link-from-email' %}\"\u003e\n```\n\nThis will redirect you to full path `/verification/user/verify-email/request-new-link/`\n\nThere are several checks done before sending an email again:\n* if the email is registered and the user's account is not been activated\n* the user hasn't exceeded max retry limit(set by you),\n\nThen a new email will be sent to the given email.\n\nThe form template is supposed to be changed unless you are okay with the default template provided with the package.\n\nTo set your own custom template for form, set a variable name `REQUEST_NEW_EMAIL_TEMPLATE` in settings.py with the path of template you want to use. Example:\n```py\nREQUEST_NEW_EMAIL_TEMPLATE = 'mytemplates/mycustomtemplate.html'\n```\nand then your template will be displayed at the path.\n\n**Making Form:** while making your custom template, keep in mind that the view will pass a variable named `form` to the provided template, this form will contain only 1 field `email`. Sample code that you can use while making your template is here:\n\n```html\n\u003cform method='POST' \u003e\n            {% csrf_token %}\n    \n            \u003cfieldset\u003e\n                {{form}}\n            \u003c/fieldset\u003e\n    \n            \u003cdiv style=\"margin-top: 50px;\"\u003e\n                \u003cbutton class=\"btn btn-outline-info\" type=\"submit\"\u003eRequest New Email\u003c/button\u003e\n            \u003c/div\u003e\n\u003c/form\u003e\n```\nYou can apply your styles or whatever you want. (this code is used in the default template)\n\n\n**NOTE:** This info is stored in the database so you have to apply migrations (\u003ca href='#step3'\u003estep 3\u003c/a\u003e) to use this feature. \n\u003c/p\u003e\n\n\u003cp id=\"customemailtemplate\"\u003e\n\n\u003ch2\u003eCustom Email Templates : \u003c/h2\u003e\n\nThe app is packed with default HTML templates to handle the web pages but if you want to provide your own template you can do it by setting an attribute in settings.py :\n\n```\nHTML_MESSAGE_TEMPLATE = \"path/to/html_template.html\"\n\nVERIFICATION_SUCCESS_TEMPLATE = \"path/to/success.html\"\n\nVERIFICATION_FAILED_TEMPLATE = \"path/to/failed.html\"\n\nREQUEST_NEW_EMAIL_TEMPLATE = \"path/to/email.html\"\n\nLINK_EXPIRED_TEMPLATE = 'path/to/expired.html'\n\nNEW_EMAIL_SENT_TEMPLATE  = 'path/to/new_email_sent.html'\n```\n```\nSUBJECT = 'subject of email'\n\n# default subject is: Email Verification Mail\n```\n\u003c/p\u003e\n\n## Inside Templates : \u003chr\u003e\n\n### Custom HTML Message Template :\n\nTwo variables are passed in context dict of \"HTML_MESSAGE_TEMPLATE\" :\n\n* ```{{request}}``` : Which is the same request passed in to send_verification_email.\n* ```{{link}}``` : Which contains verification link\n\n\u003cb\u003eIMPORTANT : \u003c/b\u003e if you are using custom html message template for email that has to be sent to user, \u003cu\u003eprovide a \u003cb\u003e{{link}}\u003c/b\u003e as a template tag to contain verification link.\u003c/u\u003e \n\n\u003cb\u003eYou Must Pass This In Your Template\u003c/b\u003e. Otherwise, the sent mail will not contain the verification link.\n\n\nFor Ex :\n\n```my_custom_email_message.html : ```\n\n```\n\u003cdiv class=\"format-font\" \u003e\n    \u003ca href=\"{{link}}\" class=\"my-button\" \u003eVerify\u003c/a\u003e  # ----\u003e The \"link\" variable is passed by the app's backend containing verification link.\n\u003c/div\u003e\n```\n\n----\u003e \"link\" is a variable, that contains a verification link, and is passed in an HTML message template during sending the email to the user.\n\n\n### Custom HTML Verification Success and Failed pages : \n\u003chr\u003e\n\n\u003cb\u003eSuccess :\u003c/b\u003e \n\nTwo variables are passed in the context dictionary of \"VERIFICATION_SUCCESS_TEMPLATE\" :\n\n* ```{{mgs}}```: Which contains the message to be displayed on successful verification.\n* ```{{link}}```: Which contains a redirect link to the login page.\n\n\u003cb\u003eIn template :\u003c/b\u003e\n\n```\n\u003ch1 style=\"text-align: center; color: white;\"\u003e\n    {{msg}}     # __--\u003e message variable\n\u003c/h1\u003e\n\n\u003ca href=\"{{link}}\" class=\"btn btn-primary\"\u003e     # __--\u003e Link of login page\n    Login\n\u003c/a\u003e\n\n```\n\n\u003cb\u003eFailed :\u003c/b\u003e\n\nOnly \"{{msg}}\" is passed for failed msg in the template.\n\n\n\u003cb\u003eIn template :\u003c/b\u003e\n\n```\n\u003ch1 style=\"text-align: center; color: white;\"\u003e\n    {{msg}}\n\u003c/h1\u003e\n```\n\n\n\n## Successful Verification :\nAfter verification is successful, you might want to redirect the user to the login page. You can do this in two ways :\n\n* 1 \u003cb\u003eRedirect from success webpage.\u003c/b\u003e\n\tThe user will be prompted to show a success page with a button on it to navigate to the Login page.\n    ```\n    LOGIN_URL = 'name of your login pattern'\n\n    Note: This variable is also used by Django.\n    ```\n* 2 \u003cb\u003eRedirect directly to the login page without stopping at the success message page.\u003c/b\u003e\n\tThe user will be directly sent to the login page, bypassing the success page.\n    ```\n    VERIFICATION_SUCCESS_TEMPLATE = None\n    ```\n\u003c/p\u003e\n\n\n\u003e There is always room for improvements and new ideas, feel free to raise PR or Issues\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknownbug06%2FDjango-Verify-Email","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fknownbug06%2FDjango-Verify-Email","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fknownbug06%2FDjango-Verify-Email/lists"}