mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-02 16:02:15 +02:00
For failed email logger messages to be errors and have a standardized output
This commit is contained in:
parent
973b392923
commit
508bd30434
8 changed files with 175 additions and 78 deletions
|
@ -9,7 +9,7 @@ from django.core.management import BaseCommand
|
|||
from django.conf import settings
|
||||
from registrar.utility import csv_export
|
||||
from io import StringIO
|
||||
from ...utility.email import send_templated_email
|
||||
from ...utility.email import send_templated_email, EmailSendingError
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -46,9 +46,11 @@ class Command(BaseCommand):
|
|||
|
||||
logger.info("Generating report...")
|
||||
try:
|
||||
self.email_current_metadata_report(zip_filename, email_to)
|
||||
success = self.email_current_metadata_report(zip_filename, email_to)
|
||||
if not success:
|
||||
# TODO - #1317: Notify operations when auto report generation fails
|
||||
raise EmailSendingError("Report was generated but failed to send via email.")
|
||||
except Exception as err:
|
||||
# TODO - #1317: Notify operations when auto report generation fails
|
||||
raise err
|
||||
else:
|
||||
logger.info(f"Success! Created {zip_filename} and successfully sent out an email!")
|
||||
|
@ -78,13 +80,24 @@ class Command(BaseCommand):
|
|||
encrypted_zip_in_bytes = self.get_encrypted_zip(zip_filename, reports, password)
|
||||
|
||||
# Send the metadata file that is zipped
|
||||
send_templated_email(
|
||||
template_name="emails/metadata_body.txt",
|
||||
subject_template_name="emails/metadata_subject.txt",
|
||||
to_addresses=email_to,
|
||||
context={"current_date_str": datetime.now().strftime("%Y-%m-%d")},
|
||||
attachment_file=encrypted_zip_in_bytes,
|
||||
)
|
||||
try:
|
||||
send_templated_email(
|
||||
template_name="emails/metadata_body.txt",
|
||||
subject_template_name="emails/metadata_subject.txt",
|
||||
to_addresses=email_to,
|
||||
context={"current_date_str": datetime.now().strftime("%Y-%m-%d")},
|
||||
attachment_file=encrypted_zip_in_bytes,
|
||||
)
|
||||
return True
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send metadata email:\n"
|
||||
f" Subject: metadata_subject.txt\n"
|
||||
f" To: {email_to}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
return False
|
||||
|
||||
def get_encrypted_zip(self, zip_filename, reports, password):
|
||||
"""Helper function for encrypting the attachment file"""
|
||||
|
|
|
@ -136,9 +136,12 @@ class Command(BaseCommand):
|
|||
)
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
f"email did not send successfully to {email_data['email']} "
|
||||
f"for {[domain for domain in email_data['domains']]}"
|
||||
f": {err}"
|
||||
"Failed to send transition domain invitation email:\n"
|
||||
f" Subjec template: transition_domain_invitation_subject.txt\n"
|
||||
f" To: {email_data['email']}\n"
|
||||
f" Domains: {', '.join(email_data['domains'])}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
# if email failed to send, set error in domains_with_errors for each
|
||||
# domain in the email so that transition domain email_sent is not set
|
||||
|
|
|
@ -97,9 +97,17 @@ class Command(BaseCommand):
|
|||
context=context,
|
||||
)
|
||||
logger.info(f"Sent email for domain {domain.name} to managers and CC’d org admins")
|
||||
except EmailSendingError as e:
|
||||
except EmailSendingError as err:
|
||||
if not dryrun:
|
||||
logger.warning(f"Failed to send email for domain {domain.name}. Reason: {e}")
|
||||
logger.error(
|
||||
"Failed to send expiring soon email(s):\n"
|
||||
f" Subject template: {subject_template}\n"
|
||||
f" To: {', '.join(domain_manager_emails)}\n"
|
||||
f" CC: {', '.join(portfolio_admin_emails)}\n"
|
||||
f" Domain: {domain.name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
|
||||
if all_emails_sent:
|
||||
|
|
|
@ -1032,8 +1032,17 @@ class DomainRequest(TimeStampedModel):
|
|||
wrap_email=wrap_email,
|
||||
)
|
||||
logger.info(f"The {new_status} email sent to: {recipient.email}")
|
||||
except EmailSendingError:
|
||||
logger.warning("Failed to send confirmation email", exc_info=True)
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send status update to creator email:\n"
|
||||
f" Type: {new_status}\n"
|
||||
f" Subject template: {email_template_subject}\n"
|
||||
f" To: {recipient.email}\n"
|
||||
f" CC: {', '.join(cc_addresses)}\n"
|
||||
f" BCC: {bcc_address}"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
def investigator_exists_and_is_staff(self):
|
||||
"""Checks if the current investigator is in a valid state for a state transition"""
|
||||
|
|
|
@ -940,18 +940,22 @@ class TestSendPortfolioMemberPermissionUpdateEmail(unittest.TestCase):
|
|||
permissions.user.email = "user@example.com"
|
||||
permissions.portfolio.organization_name = "Test Portfolio"
|
||||
|
||||
mock_get_requestor_email.return_value = "requestor@example.com"
|
||||
mock_get_requestor_email.return_value = MagicMock(name="mock.email")
|
||||
|
||||
# Call function
|
||||
result = send_portfolio_member_permission_update_email(requestor, permissions)
|
||||
|
||||
# Assertions
|
||||
mock_logger.warning.assert_called_once_with(
|
||||
"Could not send email organization member update notification to %s for portfolio: %s",
|
||||
permissions.user.email,
|
||||
permissions.portfolio.organization_name,
|
||||
exc_info=True,
|
||||
expected_message = (
|
||||
"Failed to send organization member update notification email:\n"
|
||||
f" Requestor Email: {mock_get_requestor_email.return_value}\n"
|
||||
f" Subject template: portfolio_update_subject.txt\n"
|
||||
f" To: {permissions.user.email}\n"
|
||||
f" Portfolio: {permissions.portfolio}\n"
|
||||
f" Error: Email failed"
|
||||
)
|
||||
|
||||
mock_logger.error.assert_called_once_with(expected_message, exc_info=True)
|
||||
self.assertFalse(result)
|
||||
|
||||
@patch("registrar.utility.email_invitations._get_requestor_email", side_effect=Exception("Unexpected error"))
|
||||
|
@ -1013,18 +1017,22 @@ class TestSendPortfolioMemberPermissionRemoveEmail(unittest.TestCase):
|
|||
permissions.user.email = "user@example.com"
|
||||
permissions.portfolio.organization_name = "Test Portfolio"
|
||||
|
||||
mock_get_requestor_email.return_value = "requestor@example.com"
|
||||
mock_get_requestor_email.return_value = MagicMock(name="mock.email")
|
||||
|
||||
# Call function
|
||||
result = send_portfolio_member_permission_remove_email(requestor, permissions)
|
||||
|
||||
# Assertions
|
||||
mock_logger.warning.assert_called_once_with(
|
||||
"Could not send email organization member removal notification to %s for portfolio: %s",
|
||||
permissions.user.email,
|
||||
permissions.portfolio.organization_name,
|
||||
exc_info=True,
|
||||
expected_message = (
|
||||
"Failed to send portfolio member removal email:\n"
|
||||
f" Requestor Email: {mock_get_requestor_email.return_value}\n"
|
||||
f" Subject template: portfolio_removal_subject.txt\n"
|
||||
f" To: {permissions.user.email}\n"
|
||||
f" Portfolio: {permissions.portfolio}\n"
|
||||
f" Error: Email failed"
|
||||
)
|
||||
|
||||
mock_logger.error.assert_called_once_with(expected_message, exc_info=True)
|
||||
self.assertFalse(result)
|
||||
|
||||
@patch("registrar.utility.email_invitations._get_requestor_email", side_effect=Exception("Unexpected error"))
|
||||
|
@ -1092,10 +1100,12 @@ class TestSendPortfolioInvitationRemoveEmail(unittest.TestCase):
|
|||
result = send_portfolio_invitation_remove_email(requestor, invitation)
|
||||
|
||||
# Assertions
|
||||
mock_logger.warning.assert_called_once_with(
|
||||
"Could not send email organization member removal notification to %s for portfolio: %s",
|
||||
invitation.email,
|
||||
invitation.portfolio.organization_name,
|
||||
mock_logger.error.assert_called_once_with(
|
||||
"Failed to send portfolio invitation removal email:\n"
|
||||
f" Subject template: portfolio_removal_subject.txt\n"
|
||||
f" To: {invitation.email}\n"
|
||||
f" Portfolio: {invitation.portfolio.organization_name}\n"
|
||||
f" Error: Email failed",
|
||||
exc_info=True,
|
||||
)
|
||||
self.assertFalse(result)
|
||||
|
|
|
@ -98,6 +98,15 @@ def _send_domain_invitation_email(email, requestor_email, domains, requested_use
|
|||
)
|
||||
except EmailSendingError as err:
|
||||
domain_names = ", ".join([domain.name for domain in domains])
|
||||
logger.error(
|
||||
"Failed to send domain invitation email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: domain_invitation_subject.txt\n"
|
||||
f" To: {email}\n"
|
||||
f" Domains: {domain_names}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
raise EmailSendingError(f"Could not send email invitation to {email} for domains: {domain_names}") from err
|
||||
|
||||
|
||||
|
@ -173,9 +182,15 @@ def _send_domain_invitation_update_emails_to_domain_managers(
|
|||
"date": date.today(),
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
f"Could not send email manager notification to {user.email} for domain: {domain.name}", exc_info=True
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send domain manager update notification email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject: domain_manager_notification_subject.txt\n"
|
||||
f" To: {user.email}\n"
|
||||
f" Domain: {domain.name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
return all_emails_sent
|
||||
|
@ -220,11 +235,15 @@ def send_domain_manager_removal_emails_to_domain_managers(
|
|||
"date": date.today(),
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send notification email to %s for domain %s",
|
||||
user.email,
|
||||
domain.name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send domain manager deleted notification email:\n"
|
||||
f" User that did the removing: {removed_by_user}\n"
|
||||
f" Domain manager removed: {manager_removed_email}\n"
|
||||
f" Subject template: domain_manager_deleted_notification_subject.txt\n"
|
||||
f" To: {user.email}\n"
|
||||
f" Domain: {domain.name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
|
@ -265,6 +284,15 @@ def send_portfolio_invitation_email(email: str, requestor, portfolio, is_admin_i
|
|||
},
|
||||
)
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio invitation email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: portfolio_invitation_subject.txt\n"
|
||||
f" To: {email}\n"
|
||||
f" Portfolio: {portfolio}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
raise EmailSendingError(
|
||||
f"Could not sent email invitation to {email} for portfolio {portfolio}. Portfolio invitation not saved."
|
||||
) from err
|
||||
|
@ -319,11 +347,14 @@ def send_portfolio_update_emails_to_portfolio_admins(editor, portfolio, updated_
|
|||
"updated_info": updated_page,
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization admin notification to %s " "for portfolio: %s",
|
||||
user.email,
|
||||
portfolio,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio org update notification email:\n"
|
||||
f" Requested User: {user}\n"
|
||||
f" Subject template: portfolio_org_update_notification_subject.txt\n"
|
||||
f" To: {user.email}\n"
|
||||
f" Portfolio: {portfolio}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
|
@ -362,11 +393,14 @@ def send_portfolio_member_permission_update_email(requestor, permissions: UserPo
|
|||
"date": date.today(),
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization member update notification to %s " "for portfolio: %s",
|
||||
permissions.user.email,
|
||||
permissions.portfolio.organization_name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send organization member update notification email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: portfolio_update_subject.txt\n"
|
||||
f" To: {permissions.user.email}\n"
|
||||
f" Portfolio: {permissions.portfolio}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
return False
|
||||
|
@ -403,11 +437,14 @@ def send_portfolio_member_permission_remove_email(requestor, permissions: UserPo
|
|||
"requestor_email": requestor_email,
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization member removal notification to %s " "for portfolio: %s",
|
||||
permissions.user.email,
|
||||
permissions.portfolio.organization_name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio member removal email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: portfolio_removal_subject.txt\n"
|
||||
f" To: {permissions.user.email}\n"
|
||||
f" Portfolio: {permissions.portfolio}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
return False
|
||||
|
@ -444,11 +481,13 @@ def send_portfolio_invitation_remove_email(requestor, invitation: PortfolioInvit
|
|||
"requestor_email": requestor_email,
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization member removal notification to %s " "for portfolio: %s",
|
||||
invitation.email,
|
||||
invitation.portfolio.organization_name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio invitation removal email:\n"
|
||||
f" Subject template: portfolio_removal_subject.txt\n"
|
||||
f" To: {invitation.email}\n"
|
||||
f" Portfolio: {invitation.portfolio.organization_name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
return False
|
||||
|
@ -497,11 +536,15 @@ def _send_portfolio_admin_addition_emails_to_portfolio_admins(email: str, reques
|
|||
"date": date.today(),
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization admin notification to %s " "for portfolio: %s",
|
||||
user.email,
|
||||
portfolio.organization_name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio admin addition notification email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: portfolio_admin_addition_notification_subject.txt\n"
|
||||
f" To: {user.email}\n"
|
||||
f" Portfolio: {portfolio}\n"
|
||||
f" Portfolio Admin: {user}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
|
@ -550,11 +593,14 @@ def _send_portfolio_admin_removal_emails_to_portfolio_admins(email: str, request
|
|||
"date": date.today(),
|
||||
},
|
||||
)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send email organization admin notification to %s " "for portfolio: %s",
|
||||
user.email,
|
||||
portfolio.organization_name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send portfolio admin removal notification email:\n"
|
||||
f" Requestor Email: {requestor_email}\n"
|
||||
f" Subject template: portfolio_admin_removal_notification_subject.txt\n"
|
||||
f" To: {user.email}\n"
|
||||
f" Portfolio: {portfolio.organization_name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
all_emails_sent = False
|
||||
|
|
|
@ -375,11 +375,13 @@ class DomainFormBaseView(DomainBaseView, FormMixin):
|
|||
context["recipient"] = manager
|
||||
try:
|
||||
send_templated_email(template, subject_template, to_addresses=[manager.email], context=context)
|
||||
except EmailSendingError:
|
||||
logger.warning(
|
||||
"Could not send notification email to %s for domain %s",
|
||||
manager.email,
|
||||
domain.name,
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send notification email:\n"
|
||||
f" Subject template: {subject_template}\n"
|
||||
f" To: {manager.email}\n"
|
||||
f" Domain: {domain.name}\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
|
|
|
@ -1018,8 +1018,14 @@ class Review(DomainRequestWizard):
|
|||
context=context,
|
||||
)
|
||||
logger.info("A submission confirmation email was sent to ombdotgov@omb.eop.gov")
|
||||
except EmailSendingError:
|
||||
logger.warning("Failed to send confirmation email", exc_info=True)
|
||||
except EmailSendingError as err:
|
||||
logger.error(
|
||||
"Failed to send OMB submission confirmation email:\n"
|
||||
f" Subject template: omb_submission_confirmation_subject.txt\n"
|
||||
f" To: ombdotgov@omb.eop.gov\n"
|
||||
f" Error: {err}",
|
||||
exc_info=True,
|
||||
)
|
||||
|
||||
|
||||
class Finished(DomainRequestWizard):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue