Skip to content

Commit d4ac7ed

Browse files
committed
use re lib to validate emails
1 parent ea71902 commit d4ac7ed

2 files changed

Lines changed: 15 additions & 15 deletions

File tree

server/mergin/auth/forms.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Copyright (C) Lutra Consulting Limited
22
#
33
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-MerginMaps-Commercial
4+
45
import re
56
import safe
67
from flask_wtf import FlaskForm
@@ -17,7 +18,6 @@
1718

1819
from .models import MAX_USERNAME_LENGTH, User
1920
from ..app import UpdateForm, CustomStringField
20-
from .utils import get_email_domain
2121

2222

2323
def username_validation(form, field):
@@ -51,25 +51,20 @@ class ExtendedEmail(Email):
5151
3, multiple @ symbols,
5252
4, leading, trailing, or consecutive dots in the local part,
5353
5, invalid domain part - missing top level domain (user@example), consecutive dots,
54-
Custom check for
55-
- additional invalid characters disallows |'—
56-
- non-ASCII characters in the domain part
57-
because they make our email sending service to fail
54+
The extended validation checks email addresses using the regex provided by Brevo,
55+
so that we stay consistent with their validation rules and avoid API failures.
5856
"""
5957

6058
def __call__(self, form, field):
6159
super().__call__(form, field)
6260

63-
if re.search(r"[|'—]", field.data):
64-
raise ValidationError(
65-
f"Email address '{field.data}' contains an invalid character."
66-
)
61+
email = field.data.strip()
6762

68-
domain = get_email_domain(field.data)
69-
if not domain.isascii():
70-
raise ValidationError(
71-
f"Email address '{field.data}' contains non-ASCII characters in the domain part."
72-
)
63+
pattern = r"^[\x60#&*\/=?^{!}~'+\w-]+(\.[\x60#&*\/=?^{!}~'+\w-]+)*\.?@([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*\.)[a-zA-Z0-9-]*[a-zA-Z0-9]{2,}$"
64+
email_regexp = re.compile(pattern, re.IGNORECASE)
65+
66+
if not email_regexp.match(email):
67+
raise ValidationError(f"Email address '{email}' is invalid.")
7368

7469

7570
class PasswordValidator:

server/mergin/tests/test_auth.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ def test_logout(client):
125125
400,
126126
), # tests with upper case, but email already exists
127127
(" mergin@mergin.com ", "#pwd123", 400), # invalid password
128-
("verylonglonglonglonglonglonglongemail@example.com", "#pwd1234", 201),
128+
(
129+
"verylonglonglonglonglonglonglongemail@lutra-consulting.co.uk",
130+
"#pwd1234",
131+
201,
132+
), # long local part, second-level domain, dash in domain
129133
("us.er@mergin.com", "#pwd1234", 201), # dot is allowed
130134
("us er@mergin.com", "#pwd1234", 400), # space is disallowed
131135
("test@gmaiñ.com", "#pwd1234", 400), # non-ASCII character in the domain
@@ -946,6 +950,7 @@ def test_server_usage(client):
946950
(" user", True), # starting with space (will be stripped)
947951
("us.er", True), # dot in the middle
948952
(".user", False), # starting with dot
953+
("us-er", True), # hyphen
949954
]
950955

951956

0 commit comments

Comments
 (0)