diff --git a/zerver/forms.py b/zerver/forms.py index 996b62e1a3..f96a0a3a90 100644 --- a/zerver/forms.py +++ b/zerver/forms.py @@ -68,6 +68,11 @@ DEACTIVATED_ACCOUNT_ERROR = gettext_lazy( ) PASSWORD_TOO_WEAK_ERROR = gettext_lazy("The password is too weak.") +# Set Form.EmailField to match the default max_length on Model.EmailField, +# can be removed when https://code.djangoproject.com/ticket/35119 is +# completed. +EMAIL_MAX_LENGTH = 254 + class OverridableValidationError(ValidationError): pass @@ -242,7 +247,7 @@ class ToSForm(forms.Form): class HomepageForm(forms.Form): - email = forms.EmailField() + email = forms.EmailField(max_length=EMAIL_MAX_LENGTH) def __init__(self, *args: Any, **kwargs: Any) -> None: self.realm = kwargs.pop("realm", None) @@ -321,7 +326,9 @@ class ImportRealmOwnerSelectionForm(forms.Form): class RealmCreationForm(RealmDetailsForm): # This form determines whether users can create a new realm. - email = forms.EmailField(validators=[email_not_system_bot, email_is_not_disposable]) + email = forms.EmailField( + validators=[email_not_system_bot, email_is_not_disposable], max_length=EMAIL_MAX_LENGTH + ) import_from = forms.ChoiceField( choices=PreregistrationRealm.IMPORT_FROM_CHOICES, required=False, @@ -539,7 +546,7 @@ def rate_limit_password_reset_form_by_email(email: str) -> None: class CreateUserForm(forms.Form): full_name = forms.CharField(max_length=100) - email = forms.EmailField() + email = forms.EmailField(max_length=EMAIL_MAX_LENGTH) class OurAuthenticationForm(AuthenticationForm): diff --git a/zerver/tests/test_signup.py b/zerver/tests/test_signup.py index e78220daed..05a406fbfb 100644 --- a/zerver/tests/test_signup.py +++ b/zerver/tests/test_signup.py @@ -1108,6 +1108,11 @@ class LoginTest(ZulipTestCase): self.assertEqual(result.status_code, 200) self.assertContains(result, "Enter a valid email address") + invalid_email = "a" * 260 + "@example.com" + result = self.client_post("/accounts/home/", {"email": invalid_email}, subdomain="zulip") + self.assertEqual(result.status_code, 200) + self.assertContains(result, "Ensure this value has at most 254 characters (it has 272).") + def test_register_deactivated_partway_through(self) -> None: """ If you try to register for a deactivated realm, you get a clear error @@ -4743,6 +4748,33 @@ class TestFindMyTeam(ZulipTestCase): result = self.client_get("/accounts/find/", {"emails": "invalid"}) self.assertEqual(result.status_code, 200) + def test_find_team_long_email_address(self) -> None: + # Emails over 320 characters are considered invalid. + data = {"emails": "a" * 320 + "@example.com"} + result = self.client_post("/accounts/find/", data) + self.assertEqual(result.status_code, 200) + self.assertIn(b"Enter a valid email", result.content) + from django.core.mail import outbox + + self.assert_length(outbox, 0) + + # Emails in the database are never over 254 characters, + # but searching for them does not cause an error. + # When https://code.djangoproject.com/ticket/35119 is + # resolved, Django's email validator will return this + # case as invalid, so this test will need to be updated. + data = {"emails": "a" * 260 + "@example.com"} + result = self.client_post("/accounts/find/", data) + self.assertEqual(result.status_code, 200) + content = result.content.decode() + self.assertIn("Emails sent! The addresses entered on", content) + self.assertIn("a@example.com", content) + from django.core.mail import outbox + + self.assert_length(outbox, 1) + message = outbox[0] + self.assertIn("Unfortunately, no Zulip Cloud accounts", message.body) + def test_find_team_zero_emails(self) -> None: data = {"emails": ""} result = self.client_post("/accounts/find/", data)