diff --git a/src/registrar/admin.py b/src/registrar/admin.py
index c17af86a8..b6706fad4 100644
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1885,7 +1885,7 @@ def save_model(self, request, obj, form, change):
if requested_user is not None:
portfolio_invitation.retrieve()
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 become a member of {domain_org}")
if not send_domain_invitation_email(
email=requested_email,
@@ -1894,7 +1894,7 @@ def save_model(self, request, obj, form, change):
is_member_of_different_org=member_of_a_different_org,
requested_user=requested_user,
):
- messages.warning(request, "Could not send email confirmation to existing domain managers.")
+ messages.warning(request, "Could not send email notification to existing domain managers.")
if requested_user is not None:
# Domain Invitation creation for an existing User
obj.retrieve()
diff --git a/src/registrar/tests/test_admin.py b/src/registrar/tests/test_admin.py
index 4538de71e..ddacdf5e4 100644
--- a/src/registrar/tests/test_admin.py
+++ b/src/registrar/tests/test_admin.py
@@ -399,7 +399,7 @@ def test_add_domain_invitation_success_when_user_not_portfolio_member(
# Assert success message
mock_messages_success.assert_has_calls(
[
- call(request, "test@example.com has been invited to the organization: new portfolio"),
+ call(request, "test@example.com has been invited to become a member of new portfolio"),
call(request, "test@example.com has been invited to the domain: example.com"),
]
)
@@ -656,7 +656,7 @@ def test_add_domain_invitation_when_user_not_portfolio_member_raises_exception_s
# Assert success message
mock_messages_success.assert_called_once_with(
- request, "test@example.com has been invited to the organization: new portfolio"
+ request, "test@example.com has been invited to become a member of new portfolio"
)
# Assert error message
@@ -784,7 +784,7 @@ def test_add_domain_invitation_success_when_email_not_portfolio_member(
# Assert success message
mock_messages_success.assert_has_calls(
[
- call(request, "nonexistent@example.com has been invited to the organization: new portfolio"),
+ call(request, "nonexistent@example.com has been invited to become a member of new portfolio"),
call(request, "nonexistent@example.com has been invited to the domain: example.com"),
]
)
@@ -1018,7 +1018,7 @@ def test_add_domain_invitation_when_user_not_portfolio_email_raises_exception_se
# Assert success message
mock_messages_success.assert_called_once_with(
- request, "nonexistent@example.com has been invited to the organization: new portfolio"
+ request, "nonexistent@example.com has been invited to become a member of new portfolio"
)
# Assert error message
@@ -1503,7 +1503,7 @@ def test_save_exception_email_sending_error(self, mock_messages_error, mock_send
self.client.force_login(self.superuser)
# Mock the email sending function to raise EmailSendingError
- mock_send_email.side_effect = EmailSendingError("Email service unavailable")
+ mock_send_email.side_effect = EmailSendingError("Email service unavailable.")
# Create an instance of the admin class
admin_instance = PortfolioInvitationAdmin(PortfolioInvitation, admin_site=None)
@@ -1521,9 +1521,16 @@ def test_save_exception_email_sending_error(self, mock_messages_error, mock_send
# Call the save_model method
admin_instance.save_model(request, portfolio_invitation, None, None)
+ msg = (
+ "Email service unavailable. Try again, and if the problem persists, "
+ 'contact us.'
+ )
# Assert that messages.error was called with the correct message
- mock_messages_error.assert_called_once_with(request, "Email service unavailable")
+ mock_messages_error.assert_called_once_with(
+ request,
+ msg,
+ )
@less_console_noise_decorator
@patch("registrar.admin.send_portfolio_invitation_email")
@@ -1585,8 +1592,17 @@ def test_save_exception_generic_error(self, mock_messages_error, mock_send_email
# Call the save_model method
admin_instance.save_model(request, portfolio_invitation, None, None)
+ msg = (
+ "An unexpected error occurred: james.gordon@gotham.gov could not be added to this domain. "
+ 'Try again, and if the problem persists, contact us.'
+ )
+
# Assert that messages.error was called with the correct message
- mock_messages_error.assert_called_once_with(request, "Could not send email invitation.")
+ mock_messages_error.assert_called_once_with(
+ request,
+ msg,
+ )
@less_console_noise_decorator
@patch("registrar.admin.send_portfolio_admin_addition_emails")
diff --git a/src/registrar/tests/test_email_invitations.py b/src/registrar/tests/test_email_invitations.py
index 99515648a..bdbad0de3 100644
--- a/src/registrar/tests/test_email_invitations.py
+++ b/src/registrar/tests/test_email_invitations.py
@@ -525,7 +525,10 @@ def test_send_portfolio_invitation_email_failure(self, mock_send_templated_email
with self.assertRaises(EmailSendingError) as context:
send_portfolio_invitation_email(self.email, self.requestor, self.portfolio, is_admin_invitation)
- self.assertIn("Could not sent email invitation to", str(context.exception))
+ self.assertIn(
+ "An unexpected error occurred: invitee@example.com could not be added to this domain.",
+ str(context.exception),
+ )
@less_console_noise_decorator
@patch(
diff --git a/src/registrar/tests/test_views_domain.py b/src/registrar/tests/test_views_domain.py
index 0e9c70d1a..44fb65023 100644
--- a/src/registrar/tests/test_views_domain.py
+++ b/src/registrar/tests/test_views_domain.py
@@ -981,7 +981,7 @@ def test_domain_user_add_form_fails_to_send_to_some_managers(
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
success_page = success_result.follow()
- self.assertContains(success_page, "Could not send email confirmation to existing domain managers.")
+ self.assertContains(success_page, "Could not send email notification to existing domain managers.")
@GenericTestHelper.switch_to_enterprise_mode_wrapper
@boto3_mocking.patching
diff --git a/src/registrar/utility/email_invitations.py b/src/registrar/utility/email_invitations.py
index b6b775c10..a140703cc 100644
--- a/src/registrar/utility/email_invitations.py
+++ b/src/registrar/utility/email_invitations.py
@@ -103,7 +103,7 @@ def _send_domain_invitation_email(email, requestor_email, domains, requested_use
f" Error: {err}",
exc_info=True,
)
- raise EmailSendingError(f"Could not send email invitation to {email} for domains: {domain_names}") from err
+ raise EmailSendingError(f"An unexpected error occurred: {email} could not be added to this domain.") from err
def send_domain_invitation_email(
@@ -335,9 +335,7 @@ def send_portfolio_invitation_email(email: str, requestor, portfolio, is_admin_i
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
+ raise EmailSendingError(f"An unexpected error occurred: {email} could not be added to this domain.") from err
all_admin_emails_sent = True
# send emails to portfolio admins
diff --git a/src/registrar/utility/errors.py b/src/registrar/utility/errors.py
index 9446d84f7..d31719961 100644
--- a/src/registrar/utility/errors.py
+++ b/src/registrar/utility/errors.py
@@ -54,12 +54,6 @@ def __init__(self, email=None, domain=None, portfolio=None):
# Default message if no additional info is provided
message = "Can't send invitation email. No email is associated with your user account."
- # Customize message based on provided arguments
- if email and domain:
- message = f"Can't send email to '{email}' on domain '{domain}'. No email exists for the requestor."
- elif email and portfolio:
- message = f"Can't send email to '{email}' for portfolio '{portfolio}'. No email exists for the requestor."
-
super().__init__(message)
@@ -71,9 +65,9 @@ class OutsideOrgMemberError(InvitationError):
def __init__(self, email=None):
# Default message if no additional info is provided
- message = "Can not invite member of a .gov organization to a different organization."
+ message = "Can not invite member to this organization."
if email:
- message = f"{email} is already a member of another .gov organization."
+ message = f"{email} is not a member of this organization."
super().__init__(message)
diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py
index 71e9ae89c..70be1beca 100644
--- a/src/registrar/views/domain.py
+++ b/src/registrar/views/domain.py
@@ -1324,7 +1324,7 @@ def form_valid(self, form):
if requested_user is not None:
portfolio_invitation.retrieve()
portfolio_invitation.save()
- messages.success(self.request, f"{requested_email} has been invited to the organization: {domain_org}")
+ messages.success(self.request, f"{requested_email} has been invited to become a member of {domain_org}")
if requested_user is None:
self._handle_new_user_invitation(requested_email, requestor, member_of_a_different_org)
@@ -1343,9 +1343,9 @@ def _handle_new_user_invitation(self, email, requestor, member_of_different_org)
domains=self.object,
is_member_of_different_org=member_of_different_org,
):
- messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
+ messages.warning(self.request, "Could not send email notification to existing domain managers.")
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 this domain.")
def _handle_existing_user(self, email, requestor, requested_user, member_of_different_org):
"""Handle adding an existing user to the domain."""
@@ -1356,7 +1356,7 @@ def _handle_existing_user(self, email, requestor, requested_user, member_of_diff
is_member_of_different_org=member_of_different_org,
requested_user=requested_user,
):
- messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
+ messages.warning(self.request, "Could not send email notification to existing domain managers.")
UserDomainRole.objects.create(
user=requested_user,
domain=self.object,
diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py
index abc2c2194..15eab4bd9 100644
--- a/src/registrar/views/portfolios.py
+++ b/src/registrar/views/portfolios.py
@@ -446,7 +446,7 @@ def _process_added_domains(self, added_domain_ids, member, requestor, portfolio)
is_member_of_different_org=member_of_a_different_org,
requested_user=member,
):
- messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
+ messages.warning(self.request, "Could not send email notification to existing domain managers.")
# Bulk create UserDomainRole instances for added domains
UserDomainRole.objects.bulk_create(
[
@@ -777,7 +777,7 @@ def _process_added_domains(self, added_domain_ids, email, requestor, portfolio):
domains=added_domains,
is_member_of_different_org=member_of_a_different_org,
):
- messages.warning(self.request, "Could not send email confirmation to existing domain managers.")
+ messages.warning(self.request, "Could not send email notification to existing domain managers.")
# Update existing invitations from CANCELED to INVITED
existing_invitations = DomainInvitation.objects.filter(domain__in=added_domains, email=email)
@@ -1179,7 +1179,7 @@ def _handle_exceptions(self, exception, portfolio, email):
elif isinstance(exception, MissingEmailError):
messages.error(self.request, str(exception))
logger.error(
- f"Can't send email to '{email}' for portfolio '{portfolio}'. No email exists for the requestor.",
+ "Can't send invitation email. No email is associated with your account.",
exc_info=True,
)
else:
diff --git a/src/registrar/views/utility/invitation_helper.py b/src/registrar/views/utility/invitation_helper.py
index 18c427940..390467a8c 100644
--- a/src/registrar/views/utility/invitation_helper.py
+++ b/src/registrar/views/utility/invitation_helper.py
@@ -9,6 +9,7 @@
MissingEmailError,
OutsideOrgMemberError,
)
+from django.utils.html import format_html
logger = logging.getLogger(__name__)
@@ -61,7 +62,7 @@ def handle_invitation_exceptions(request, exception, email):
"""Handle exceptions raised during the process."""
if isinstance(exception, EmailSendingError):
logger.warning(exception, exc_info=True)
- messages.error(request, str(exception))
+ messages.error(request, with_contact_link(str(exception)))
elif isinstance(exception, MissingEmailError):
messages.error(request, str(exception))
logger.error(exception, exc_info=True)
@@ -72,7 +73,17 @@ def handle_invitation_exceptions(request, exception, email):
elif isinstance(exception, AlreadyDomainInvitedError):
messages.error(request, str(exception))
elif isinstance(exception, IntegrityError):
- messages.error(request, f"{email} is already a manager for this domain")
+ messages.error(request, f"An unexpected error occurred: {email} could not be added to this domain.")
else:
logger.warning("Could not send email invitation (Other Exception)", exc_info=True)
- messages.error(request, "Could not send email invitation.")
+ messages.error(
+ request, with_contact_link(f"An unexpected error occurred: {email} could not be added to this domain.")
+ )
+
+
+def with_contact_link(error_message: str, contact_url: str = "https://get.gov/contact") -> str:
+ return format_html(
+ '{} Try again, and if the problem persists, contact us.',
+ error_message,
+ contact_url,
+ )