From 9a94f4b905e99727efdb61ba35af94496ee03752 Mon Sep 17 00:00:00 2001 From: Kumi Date: Wed, 20 Nov 2024 10:15:43 +0100 Subject: [PATCH] fix: Handle email sending failures gracefully Adds exception handling for SMTPRecipientsRefused to prevent unhandled exceptions when email delivery fails. Provides user feedback on email verification failure and removes registration record if the initial verification email fails. Improves user experience by allowing system to continue even if an email address is invalid or blocked. --- .../registration/signals.py | 34 ++++++++++++------- .../registration/views.py | 25 +++++++++----- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/synapse_registration/registration/signals.py b/src/synapse_registration/registration/signals.py index 35ef56f..809a602 100644 --- a/src/synapse_registration/registration/signals.py +++ b/src/synapse_registration/registration/signals.py @@ -7,6 +7,8 @@ from .models import UserRegistration import requests +from smtplib import SMTPRecipientsRefused + @receiver(post_save, sender=UserRegistration) def handle_status_change(sender, instance, created, **kwargs): @@ -35,21 +37,17 @@ def handle_status_change(sender, instance, created, **kwargs): headers={"Authorization": f"Bearer {settings.SYNAPSE_ADMIN_TOKEN}"}, ) - send_mail( - "Registration Approved", - f"Congratulations, {instance.username}! Your registration at {settings.MATRIX_DOMAIN} has been approved.", - settings.DEFAULT_FROM_EMAIL, - [instance.email], - ) + try: + send_mail( + "Registration Approved", + f"Congratulations, {instance.username}! Your registration at {settings.MATRIX_DOMAIN} has been approved.", + settings.DEFAULT_FROM_EMAIL, + [instance.email], + ) + except SMTPRecipientsRefused: + pass elif status == UserRegistration.STATUS_DENIED: - send_mail( - "Registration Denied", - f"Sorry, your registration request at {settings.MATRIX_DOMAIN} has been denied.", - settings.DEFAULT_FROM_EMAIL, - [instance.email], - ) - response = requests.put( f"{settings.SYNAPSE_SERVER}/_synapse/admin/v2/users/@{instance.username}:{settings.MATRIX_DOMAIN}", json={"deactivated": True}, @@ -63,3 +61,13 @@ def handle_status_change(sender, instance, created, **kwargs): settings.DEFAULT_FROM_EMAIL, [settings.ADMIN_EMAIL], ) + + try: + send_mail( + "Registration Denied", + f"Sorry, your registration request at {settings.MATRIX_DOMAIN} has been denied.", + settings.DEFAULT_FROM_EMAIL, + [instance.email], + ) + except SMTPRecipientsRefused: + pass \ No newline at end of file diff --git a/src/synapse_registration/registration/views.py b/src/synapse_registration/registration/views.py index 21f4034..54f302d 100644 --- a/src/synapse_registration/registration/views.py +++ b/src/synapse_registration/registration/views.py @@ -11,6 +11,7 @@ import requests from secrets import token_urlsafe from datetime import datetime, timedelta +from smtplib import SMTPRecipientsRefused class LandingPageView(TemplateView): @@ -76,22 +77,30 @@ class EmailInputView(FormView): token = token_urlsafe(32) - UserRegistration.objects.create( + registration = UserRegistration.objects.create( username=self.request.session["username"], email=email, token=token, ip_address=ip_address, ) + verification_link = self.request.build_absolute_uri( reverse_lazy("verify_email", args=[token]) ) - send_mail( - "Verify your email", - f"Click the link to verify your email: {verification_link}", - settings.DEFAULT_FROM_EMAIL, - [email], - ) - return render(self.request, "registration/email_sent.html") + + try: + send_mail( + "Verify your email", + f"Click the link to verify your email: {verification_link}", + settings.DEFAULT_FROM_EMAIL, + [email], + ) + return render(self.request, "registration/email_sent.html") + + except SMTPRecipientsRefused: + form.add_error("email", "Your email address is invalid, not accepting mail, or blocked by our mail server.") + registration.delete() + return self.form_invalid(form) class VerifyEmailView(View):