diff --git a/verify_email/email_handler.py b/verify_email/email_handler.py index b3fae6f..9dece48 100644 --- a/verify_email/email_handler.py +++ b/verify_email/email_handler.py @@ -20,37 +20,45 @@ def __init__(self): # Private : def __send_email(self, msg, useremail): - subject = self.settings.get('subject') + subject = self.settings.get("subject") send_mail( - subject, strip_tags(msg), - from_email=self.settings.get('from_alias'), - recipient_list=[useremail], html_message=msg + subject, + strip_tags(msg), + from_email=self.settings.get("from_alias"), + recipient_list=[useremail], + html_message=msg, ) # Public : def send_verification_link(self, request, inactive_user=None, form=None): - + if form: inactive_user = form.save(commit=False) - + inactive_user.is_active = False inactive_user.save() try: - - useremail = form.cleaned_data.get(self.settings.get('email_field_name')) if form else inactive_user.email + + useremail = ( + form.cleaned_data.get(self.settings.get("email_field_name")) + if form + else inactive_user.email + ) if not useremail: raise KeyError( 'No key named "email" in your form. Your field should be named as email in form OR set a variable' ' "EMAIL_FIELD_NAME" with the name of current field in settings.py if you want to use current name ' - 'as email field.' + "as email field." ) - verification_url = self.token_manager.generate_link(request, inactive_user, useremail) + verification_url = self.token_manager.generate_link( + request, inactive_user, useremail + ) msg = render_to_string( - self.settings.get('html_message_template', raise_exception=True), - {"link": verification_url, "inactive_user": inactive_user}, - request=request + self.settings.get("html_message_template", raise_exception=True), + {"link": verification_url, "inactive_user": inactive_user}, + request=request, ) self.__send_email(msg, useremail) @@ -67,35 +75,46 @@ def resend_verification_link(self, request, email, **kwargs): - UserAlreadyActive (by) get_user_by_token() - MaxRetryExceeded (by) request_new_link() - InvalidTokenOrEmail - + These exception should be handled in caller function. """ - inactive_user = kwargs.get('user') - user_encoded_token = kwargs.get('token') - encoded = kwargs.get('encoded', True) + inactive_user = kwargs.get("user") + user_encoded_token = kwargs.get("token") + encoded = kwargs.get("encoded", True) if encoded: - decoded_encrypted_user_token = self.token_manager.perform_decoding(user_encoded_token) + decoded_encrypted_user_token = self.token_manager.perform_decoding( + user_encoded_token + ) email = self.token_manager.perform_decoding(email) - inactive_user = self.token_manager.get_user_by_token(email, decoded_encrypted_user_token) + inactive_user = self.token_manager.get_user_by_token( + email, decoded_encrypted_user_token + ) if not inactive_user or not email: - raise InvalidTokenOrEmail(f'Either token or email is invalid. user: {inactive_user}, email: {email}') + raise InvalidTokenOrEmail( + f"Either token or email is invalid. user: {inactive_user}, email: {email}" + ) # At this point, we have decoded email(if it was encoded), and inactive_user, and we can request new link link = self.token_manager.request_new_link(request, inactive_user, email) msg = render_to_string( - self.settings.get('html_message_template', raise_exception=True), - {"link": link}, request=request + self.settings.get("html_message_template", raise_exception=True), + {"link": link}, + request=request, ) self.__send_email(msg, email) return True - # These is supposed to be called outside of this module -def send_verification_email(request, form): - return _VerifyEmail().send_verification_link(request, form) +def send_verification_email(request, form=None, user=None): + if form is not None: + return _VerifyEmail().send_verification_link(request, form) + elif user is not None: + return _VerifyEmail().send_verification_link(request, user) + else: + raise ValueError("Either form or user must be provided") # These is supposed to be called outside of this module diff --git a/verify_email/views.py b/verify_email/views.py index 07873db..e0c6f59 100644 --- a/verify_email/views.py +++ b/verify_email/views.py @@ -23,16 +23,16 @@ pkg_configs = GetFieldFromSettings() -login_page = pkg_configs.get('login_page') +login_page = pkg_configs.get("login_page") -success_msg = pkg_configs.get('verification_success_msg') -failed_msg = pkg_configs.get('verification_failed_msg') +success_msg = pkg_configs.get("verification_success_msg") +failed_msg = pkg_configs.get("verification_failed_msg") -failed_template = pkg_configs.get('verification_failed_template') -success_template = pkg_configs.get('verification_success_template') -link_expired_template = pkg_configs.get('link_expired_template') -request_new_email_template = pkg_configs.get('request_new_email_template') -new_email_sent_template = pkg_configs.get('new_email_sent_template') +failed_template = pkg_configs.get("verification_failed_template") +success_template = pkg_configs.get("verification_success_template") +link_expired_template = pkg_configs.get("link_expired_template") +request_new_email_template = pkg_configs.get("request_new_email_template") +new_email_sent_template = pkg_configs.get("new_email_sent_template") def verify_user_and_activate(request, useremail, usertoken): @@ -42,7 +42,7 @@ def verify_user_and_activate(request, useremail, usertoken): verify the user's email and token and redirect'em accordingly. """ - if request.method == 'GET': + if request.method == "GET": try: verified = verify_user(useremail, usertoken) if verified is True: @@ -53,63 +53,69 @@ def verify_user_and_activate(request, useremail, usertoken): request, template_name=success_template, context={ - 'msg': success_msg, - 'status': 'Verification Successful!', - 'link': reverse(login_page) - } + "msg": success_msg, + "status": "Verification Successful!", + "link": ( + login_page + if login_page and login_page.startswith("/") + else reverse(login_page) if login_page else "" + ), + }, ) else: # we dont know what went wrong... raise ValueError except (ValueError, TypeError) as error: - logger.error(f'[ERROR]: Something went wrong while verifying user, exception: {error}') + logger.error( + f"[ERROR]: Something went wrong while verifying user, exception: {error}" + ) return render( request, template_name=failed_template, context={ - 'msg': failed_msg, - 'minor_msg': 'There is something wrong with this link...', - 'status': 'Verification Failed!', - } + "msg": failed_msg, + "minor_msg": "There is something wrong with this link...", + "status": "Verification Failed!", + }, ) except SignatureExpired: return render( request, template_name=link_expired_template, context={ - 'msg': 'The link has lived its life :( Request a new one!', - 'status': 'Expired!', - 'encoded_email': useremail, - 'encoded_token': usertoken - } + "msg": "The link has lived its life :( Request a new one!", + "status": "Expired!", + "encoded_email": useremail, + "encoded_token": usertoken, + }, ) except BadSignature: return render( request, template_name=failed_template, context={ - 'msg': 'This link was modified before verification.', - 'minor_msg': 'Cannot request another verification link with faulty link.', - 'status': 'Faulty Link Detected!', - } + "msg": "This link was modified before verification.", + "minor_msg": "Cannot request another verification link with faulty link.", + "status": "Faulty Link Detected!", + }, ) except MaxRetriesExceeded: return render( request, template_name=failed_template, context={ - 'msg': 'You have exceeded the maximum verification requests! Contact admin.', - 'status': 'Maxed out!', - } + "msg": "You have exceeded the maximum verification requests! Contact admin.", + "status": "Maxed out!", + }, ) except InvalidToken: return render( request, template_name=failed_template, context={ - 'msg': 'This link is invalid or been used already, we cannot verify using this link.', - 'status': 'Invalid Link', - } + "msg": "This link is invalid or been used already, we cannot verify using this link.", + "status": "Invalid Link", + }, ) except UserNotFound: raise Http404("404 User not found") @@ -119,36 +125,38 @@ def request_new_link(request, useremail=None, usertoken=None): try: if useremail is None or usertoken is None: # request came from re-request email page - if request.method == 'POST': + if request.method == "POST": form = RequestNewVerificationEmail(request.POST) # do not inflate data if form.is_valid(): form_data: dict = form.cleaned_data - email = form_data['email'] + email = form_data["email"] inactive_user = get_user_model().objects.get(email=email) if inactive_user.is_active: - raise UserAlreadyActive('User is already active') + raise UserAlreadyActive("User is already active") else: # resend email - status = resend_verification_email(request, email, user=inactive_user, encoded=False) + status = resend_verification_email( + request, email, user=inactive_user, encoded=False + ) if status: return render( request, template_name=new_email_sent_template, context={ - 'msg': "You have requested another verification email!", - 'minor_msg': 'Your verification link has been sent', - 'status': 'Email Sent!', - } + "msg": "You have requested another verification email!", + "minor_msg": "Your verification link has been sent", + "status": "Email Sent!", + }, ) else: - logger.error('something went wrong during sending email') + logger.error("something went wrong during sending email") else: form = RequestNewVerificationEmail() return render( request, template_name=request_new_email_template, - context={'form': form} + context={"form": form}, ) else: # request came from previously sent link @@ -159,53 +167,55 @@ def request_new_link(request, useremail=None, usertoken=None): request, template_name=new_email_sent_template, context={ - 'msg': "You have requested another verification email!", - 'minor_msg': 'Your verification link has been sent', - 'status': 'Email Sent!', - } + "msg": "You have requested another verification email!", + "minor_msg": "Your verification link has been sent", + "status": "Email Sent!", + }, ) else: - messages.info(request, 'Something went wrong during sending email :(') - logger.error('something went wrong during sending email') + messages.info(request, "Something went wrong during sending email :(") + logger.error("something went wrong during sending email") except ObjectDoesNotExist as error: - messages.warning(request, 'User not found associated with given email!') - logger.error(f'[ERROR]: User not found. exception: {error}') + messages.warning(request, "User not found associated with given email!") + logger.error(f"[ERROR]: User not found. exception: {error}") return HttpResponse(b"User Not Found", status=404) except MultipleObjectsReturned as error: - logger.error(f'[ERROR]: Multiple users found. exception: {error}') + logger.error(f"[ERROR]: Multiple users found. exception: {error}") return HttpResponse(b"Internal server error!", status=500) except KeyError as error: - logger.error(f'[ERROR]: Key error for email in your form: {error}') + logger.error(f"[ERROR]: Key error for email in your form: {error}") return HttpResponse(b"Internal server error!", status=500) except MaxRetriesExceeded as error: - logger.error(f'[ERROR]: Maximum retries for link has been reached. exception: {error}') + logger.error( + f"[ERROR]: Maximum retries for link has been reached. exception: {error}" + ) return render( request, template_name=failed_template, context={ - 'msg': 'You have exceeded the maximum verification requests! Contact admin.', - 'status': 'Maxed out!', - } + "msg": "You have exceeded the maximum verification requests! Contact admin.", + "status": "Maxed out!", + }, ) except InvalidToken: return render( request, template_name=failed_template, context={ - 'msg': 'This link is invalid or been used already, we cannot verify using this link.', - 'status': 'Invalid Link', - } + "msg": "This link is invalid or been used already, we cannot verify using this link.", + "status": "Invalid Link", + }, ) except UserAlreadyActive: return render( request, template_name=failed_template, context={ - 'msg': "This user's account is already active", - 'status': 'Already Verified!', - } + "msg": "This user's account is already active", + "status": "Already Verified!", + }, )