handling of failed email sends to domain managers

This commit is contained in:
David Kennedy 2025-01-29 15:02:46 -05:00
parent bc7bc4d6e1
commit 6634e9bad8
No known key found for this signature in database
GPG key ID: 6528A5386E66B96B
5 changed files with 36 additions and 22 deletions

View file

@ -1410,7 +1410,7 @@ class BaseInvitationAdmin(ListHeaderAdmin):
# store current messages from request so that they are preserved throughout the method # store current messages from request so that they are preserved throughout the method
storage = get_messages(request) storage = get_messages(request)
# Check if there are any error or warning messages in the `messages` framework # Check if there are any error or warning messages in the `messages` framework
has_errors = any(message.level_tag in ["error", "warning"] for message in storage) has_errors = any(message.level_tag in ["error"] for message in storage)
if has_errors: if has_errors:
# Re-render the change form if there are errors or warnings # Re-render the change form if there are errors or warnings
@ -1552,13 +1552,14 @@ class DomainInvitationAdmin(BaseInvitationAdmin):
portfolio_invitation.save() portfolio_invitation.save()
messages.success(request, f"{requested_email} has been invited to the organization: {domain_org}") messages.success(request, f"{requested_email} has been invited to the organization: {domain_org}")
send_domain_invitation_email( if not send_domain_invitation_email(
email=requested_email, email=requested_email,
requestor=requestor, requestor=requestor,
domains=domain, domains=domain,
is_member_of_different_org=member_of_a_different_org, is_member_of_different_org=member_of_a_different_org,
requested_user=requested_user, requested_user=requested_user,
) ):
messages.warning(request, "Could not send email confirmation to existing domain managers.")
if requested_user is not None: if requested_user is not None:
# Domain Invitation creation for an existing User # Domain Invitation creation for an existing User
obj.retrieve() obj.retrieve()

View file

@ -27,6 +27,9 @@ def send_domain_invitation_email(
is_member_of_different_org (bool): if an email belongs to a different org is_member_of_different_org (bool): if an email belongs to a different org
requested_user (User | None): The recipient if the email belongs to a user in the registrar requested_user (User | None): The recipient if the email belongs to a user in the registrar
Returns:
Boolean indicating if all messages were sent successfully.
Raises: Raises:
MissingEmailError: If the requestor has no email associated with their account. MissingEmailError: If the requestor has no email associated with their account.
AlreadyDomainManagerError: If the email corresponds to an existing domain manager. AlreadyDomainManagerError: If the email corresponds to an existing domain manager.
@ -41,22 +44,28 @@ def send_domain_invitation_email(
send_invitation_email(email, requestor_email, domains, requested_user) send_invitation_email(email, requestor_email, domains, requested_user)
all_manager_emails_sent = True
# send emails to domain managers # send emails to domain managers
for domain in domains: for domain in domains:
send_emails_to_domain_managers( if not send_emails_to_domain_managers(
email=email, email=email,
requestor_email=requestor_email, requestor_email=requestor_email,
domain=domain, domain=domain,
requested_user=requested_user, requested_user=requested_user,
) ):
all_manager_emails_sent = False
return all_manager_emails_sent
def send_emails_to_domain_managers(email: str, requestor_email, domain: Domain, requested_user=None): def send_emails_to_domain_managers(email: str, requestor_email, domain: Domain, requested_user=None):
""" """
Notifies all domain managers of the provided domain of a change Notifies all domain managers of the provided domain of a change
Raises:
EmailSendingError Returns:
Boolean indicating if all messages were sent successfully.
""" """
all_emails_sent = True
# Get each domain manager from list # Get each domain manager from list
user_domain_roles = UserDomainRole.objects.filter(domain=domain) user_domain_roles = UserDomainRole.objects.filter(domain=domain)
for user_domain_role in user_domain_roles: for user_domain_role in user_domain_roles:
@ -76,9 +85,9 @@ def send_emails_to_domain_managers(email: str, requestor_email, domain: Domain,
}, },
) )
except EmailSendingError as err: except EmailSendingError as err:
raise EmailSendingError( logger.warning(f"Could not send email manager notification to {user.email} for domain: {domain.name}")
f"Could not send email manager notification to {user.email} for domain: {domain.name}" all_emails_sent = False
) from err return all_emails_sent
def normalize_domains(domains: Domain | list[Domain]) -> list[Domain]: def normalize_domains(domains: Domain | list[Domain]) -> list[Domain]:

View file

@ -1244,24 +1244,26 @@ class DomainAddUserView(DomainFormBaseView):
def _handle_new_user_invitation(self, email, requestor, member_of_different_org): def _handle_new_user_invitation(self, email, requestor, member_of_different_org):
"""Handle invitation for a new user who does not exist in the system.""" """Handle invitation for a new user who does not exist in the system."""
send_domain_invitation_email( if not send_domain_invitation_email(
email=email, email=email,
requestor=requestor, requestor=requestor,
domains=self.object, domains=self.object,
is_member_of_different_org=member_of_different_org, is_member_of_different_org=member_of_different_org,
) ):
messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
DomainInvitation.objects.get_or_create(email=email, domain=self.object) DomainInvitation.objects.get_or_create(email=email, domain=self.object)
messages.success(self.request, f"{email} has been invited to the domain: {self.object}") messages.success(self.request, f"{email} has been invited to the domain: {self.object}")
def _handle_existing_user(self, email, requestor, requested_user, member_of_different_org): def _handle_existing_user(self, email, requestor, requested_user, member_of_different_org):
"""Handle adding an existing user to the domain.""" """Handle adding an existing user to the domain."""
send_domain_invitation_email( if not send_domain_invitation_email(
email=email, email=email,
requestor=requestor, requestor=requestor,
domains=self.object, domains=self.object,
is_member_of_different_org=member_of_different_org, is_member_of_different_org=member_of_different_org,
requested_user=requested_user, requested_user=requested_user,
) ):
messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
UserDomainRole.objects.create( UserDomainRole.objects.create(
user=requested_user, user=requested_user,
domain=self.object, domain=self.object,

View file

@ -299,13 +299,14 @@ class PortfolioMemberDomainsEditView(PortfolioMemberDomainsEditPermissionView, V
# get added_domains from ids to pass to send email method and bulk create # get added_domains from ids to pass to send email method and bulk create
added_domains = Domain.objects.filter(id__in=added_domain_ids) added_domains = Domain.objects.filter(id__in=added_domain_ids)
member_of_a_different_org, _ = get_org_membership(portfolio, member.email, member) member_of_a_different_org, _ = get_org_membership(portfolio, member.email, member)
send_domain_invitation_email( if not send_domain_invitation_email(
email=member.email, email=member.email,
requestor=requestor, requestor=requestor,
domains=added_domains, domains=added_domains,
is_member_of_different_org=member_of_a_different_org, is_member_of_different_org=member_of_a_different_org,
requested_user=member, requested_user=member,
) ):
messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
# Bulk create UserDomainRole instances for added domains # Bulk create UserDomainRole instances for added domains
UserDomainRole.objects.bulk_create( UserDomainRole.objects.bulk_create(
[ [
@ -517,12 +518,13 @@ class PortfolioInvitedMemberDomainsEditView(PortfolioMemberDomainsEditPermission
# get added_domains from ids to pass to send email method and bulk create # get added_domains from ids to pass to send email method and bulk create
added_domains = Domain.objects.filter(id__in=added_domain_ids) added_domains = Domain.objects.filter(id__in=added_domain_ids)
member_of_a_different_org, _ = get_org_membership(portfolio, email, None) member_of_a_different_org, _ = get_org_membership(portfolio, email, None)
send_domain_invitation_email( if not send_domain_invitation_email(
email=email, email=email,
requestor=requestor, requestor=requestor,
domains=added_domains, domains=added_domains,
is_member_of_different_org=member_of_a_different_org, is_member_of_different_org=member_of_a_different_org,
) ):
messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
# Update existing invitations from CANCELED to INVITED # Update existing invitations from CANCELED to INVITED
existing_invitations = DomainInvitation.objects.filter(domain__in=added_domains, email=email) existing_invitations = DomainInvitation.objects.filter(domain__in=added_domains, email=email)

View file

@ -70,11 +70,11 @@ def handle_invitation_exceptions(request, exception, email):
messages.error(request, str(exception)) messages.error(request, str(exception))
logger.warning(str(exception), exc_info=True) logger.warning(str(exception), exc_info=True)
elif isinstance(exception, AlreadyDomainManagerError): elif isinstance(exception, AlreadyDomainManagerError):
messages.warning(request, str(exception)) messages.error(request, str(exception))
elif isinstance(exception, AlreadyDomainInvitedError): elif isinstance(exception, AlreadyDomainInvitedError):
messages.warning(request, str(exception)) messages.error(request, str(exception))
elif isinstance(exception, IntegrityError): elif isinstance(exception, IntegrityError):
messages.warning(request, f"{email} is already a manager for this domain") messages.error(request, f"{email} is already a manager for this domain")
else: else:
logger.warning("Could not send email invitation (Other Exception)", exc_info=True) logger.warning("Could not send email invitation (Other Exception)", exc_info=True)
messages.warning(request, "Could not send email invitation.") messages.error(request, "Could not send email invitation.")