Repository: cisagov/manage.get.gov

Issue:
Update error message new generic error messages
### Issue description

The registry can produce a connection error (no error code) or various errors that essentially mean a user entered bad data of some kind. All user events that can result in EPP errors should display plain language error messages. The content for the error messages is defined in [this word doc ](https://docs.google.com/document/d/12qxl6evZw16dT-TB9iu3YLjKdwwL5KqIYQJV4uncAXg/edit#heading=h.30j0zll)

### Acceptance criteria

- [ ] client hold/revert client hold/ delete buttons  on django admin display connection error should a connection error occur
- [ ] in the Manage Domain section, the following pages: security email and DNSSEC should show the connection if a connection error occurs. Note name servers is already implemented to do this and should be a good example for the other two pages.
- [ ]  in the Manage Domain section, the follow pages:security email, DNSSEC, and Nameservers  should show their corresponding generic error message if any other EPP error (or ContactError for security email page) is thrown. 

### Additional context

_No response_

### Links to other issues

Relates to #433 



Discussion:

Resolving patch:
diff --git a/src/registrar/utility/errors.py b/src/registrar/utility/errors.py
--- a/src/registrar/utility/errors.py
+++ b/src/registrar/utility/errors.py
@@ -69,6 +69,7 @@ class NameserverErrorCodes(IntEnum):
         - 5 UNABLE_TO_UPDATE_DOMAIN unable to update the domain
         - 6 MISSING_HOST host is missing for a nameserver
         - 7 INVALID_HOST host is invalid for a nameserver
+        - 8 BAD_DATA bad data input for nameserver
     """
 
     MISSING_IP = 1
@@ -78,6 +79,7 @@ class NameserverErrorCodes(IntEnum):
     UNABLE_TO_UPDATE_DOMAIN = 5
     MISSING_HOST = 6
     INVALID_HOST = 7
+    BAD_DATA = 8
 
 
 class NameserverError(Exception):
@@ -96,6 +98,10 @@ class NameserverError(Exception):
         ),
         NameserverErrorCodes.MISSING_HOST: ("Name server must be provided to enter IP address."),
         NameserverErrorCodes.INVALID_HOST: ("Enter a name server in the required format, like ns1.example.com"),
+        NameserverErrorCodes.BAD_DATA: (
+            "There’s something wrong with the name server information you provided. "
+            "If you need help email us at help@get.gov."
+        ),
     }
 
     def __init__(self, *args, code=None, nameserver=None, ip=None, **kwargs):
@@ -112,3 +118,65 @@ def __init__(self, *args, code=None, nameserver=None, ip=None, **kwargs):
 
     def __str__(self):
         return f"{self.message}"
+
+
+class DsDataErrorCodes(IntEnum):
+    """Used in the DsDataError class for
+    error mapping.
+    Overview of ds data error codes:
+        - 1 BAD_DATA  bad data input in ds data
+    """
+
+    BAD_DATA = 1
+
+
+class DsDataError(Exception):
+    """
+    DsDataError class used to raise exceptions on
+    the ds data getter
+    """
+
+    _error_mapping = {
+        DsDataErrorCodes.BAD_DATA: (
+            "There’s something wrong with the DS data you provided. If you need help email us at help@get.gov."
+        )
+    }
+
+    def __init__(self, *args, code=None, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.code = code
+        if self.code in self._error_mapping:
+            self.message = self._error_mapping.get(self.code)
+
+    def __str__(self):
+        return f"{self.message}"
+
+
+class SecurityEmailErrorCodes(IntEnum):
+    """Used in the SecurityEmailError class for
+    error mapping.
+    Overview of security email error codes:
+        - 1 BAD_DATA  bad data input in security email
+    """
+
+    BAD_DATA = 1
+
+
+class SecurityEmailError(Exception):
+    """
+    SecurityEmailError class used to raise exceptions on
+    the security email form
+    """
+
+    _error_mapping = {
+        SecurityEmailErrorCodes.BAD_DATA: ("Enter an email address in the required format, like name@example.com.")
+    }
+
+    def __init__(self, *args, code=None, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.code = code
+        if self.code in self._error_mapping:
+            self.message = self._error_mapping.get(self.code)
+
+    def __str__(self):
+        return f"{self.message}"
diff --git a/src/registrar/views/domain.py b/src/registrar/views/domain.py
--- a/src/registrar/views/domain.py
+++ b/src/registrar/views/domain.py
@@ -28,6 +28,10 @@
     GenericErrorCodes,
     NameserverError,
     NameserverErrorCodes as nsErrorCodes,
+    DsDataError,
+    DsDataErrorCodes,
+    SecurityEmailError,
+    SecurityEmailErrorCodes,
 )
 from registrar.models.utility.contact_error import ContactError
 
@@ -315,7 +319,7 @@ def form_valid(self, formset):
                 )
                 logger.error(f"Registry connection error: {Err}")
             else:
-                messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
+                messages.error(self.request, NameserverError(code=nsErrorCodes.BAD_DATA))
                 logger.error(f"Registry error: {Err}")
         else:
             messages.success(
@@ -491,7 +495,7 @@ def form_valid(self, formset, **kwargs):
                 )
                 logger.error(f"Registry connection error: {err}")
             else:
-                messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
+                messages.error(self.request, DsDataError(code=DsDataErrorCodes.BAD_DATA))
                 logger.error(f"Registry error: {err}")
             return self.form_invalid(formset)
         else:
@@ -581,10 +585,10 @@ def form_valid(self, form):
                 )
                 logger.error(f"Registry connection error: {Err}")
             else:
-                messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
+                messages.error(self.request, SecurityEmailError(code=SecurityEmailErrorCodes.BAD_DATA))
                 logger.error(f"Registry error: {Err}")
         except ContactError as Err:
-            messages.error(self.request, GenericError(code=GenericErrorCodes.GENERIC_ERROR))
+            messages.error(self.request, SecurityEmailError(code=SecurityEmailErrorCodes.BAD_DATA))
             logger.error(f"Generic registry error: {Err}")
         else:
             messages.success(self.request, "The security email for this domain has been updated.")


Test patch:
diff --git a/src/registrar/tests/test_views.py b/src/registrar/tests/test_views.py
--- a/src/registrar/tests/test_views.py
+++ b/src/registrar/tests/test_views.py
@@ -13,6 +13,10 @@
 from registrar.utility.errors import (
     NameserverError,
     NameserverErrorCodes,
+    SecurityEmailError,
+    SecurityEmailErrorCodes,
+    GenericError,
+    GenericErrorCodes,
 )
 
 from registrar.models import (
@@ -1734,13 +1738,13 @@ def test_security_email_form_messages(self):
             (
                 "RegistryError",
                 form_data_registry_error,
-                """
-We’re experiencing a system connection error. Please wait a few minutes
-and try again. If you continue to receive this error after a few tries,
-contact help@get.gov
-                """,
+                str(GenericError(code=GenericErrorCodes.CANNOT_CONTACT_REGISTRY)),
+            ),
+            (
+                "ContactError",
+                form_data_contact_error,
+                str(SecurityEmailError(code=SecurityEmailErrorCodes.BAD_DATA)),
             ),
-            ("ContactError", form_data_contact_error, "Value entered was wrong."),
             (
                 "RegistrySuccess",
                 form_data_success,