Skip to content

Commit bc08faa

Browse files
committed
Add one-off error messages for full-width-at and small-commercial-at which are not accepted for the @-sign
1 parent a1c90ab commit bc08faa

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

email_validator/syntax.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,28 @@ def split_string_at_unquoted_special(text: str, specials: Tuple[str, ...]) -> Tu
8383
else:
8484
left_part += c
8585

86+
# No special symbol found. The special symbols always
87+
# include an at-sign, so this always indicates a missing
88+
# at-sign. The other symbol is optional.
8689
if len(left_part) == len(text):
90+
# The full-width at-sign might occur in CJK contexts.
91+
# We can't accept it because we only accept addresess
92+
# that are actually valid. But if this is common we
93+
# may want to consider accepting and normalizing full-
94+
# width characters for the other special symbols (and
95+
# full-width dot is already accepted in internationalized
96+
# domains) with a new option.
97+
# See https://news.ycombinator.com/item?id=42235268.
98+
if "@" in text:
99+
raise EmailSyntaxError("The email address has the \"full-width\" at-sign (@) character instead of a regular at-sign.")
100+
101+
# Check another near-homoglyph for good measure because
102+
# homoglyphs in place of required characters could be
103+
# very confusing. We may want to consider checking for
104+
# homoglyphs anywhere we look for a special symbol.
105+
if "﹫" in text:
106+
raise EmailSyntaxError('The email address has the "small commercial at" character instead of a regular at-sign.')
107+
87108
raise EmailSyntaxError("An email address must have an @-sign.")
88109

89110
# The right part is whatever is left.

tests/test_syntax.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,16 @@ def test_email_valid(email_input: str, output: ValidatedEmail) -> None:
304304
normalized='\u1E69@nfc.tld',
305305
),
306306
),
307+
(
308+
'@@fullwidth.at',
309+
MakeValidatedEmail(
310+
local_part='@',
311+
smtputf8=True,
312+
ascii_domain='fullwidth.at',
313+
domain='fullwidth.at',
314+
normalized='@@fullwidth.at',
315+
),
316+
),
307317
],
308318
)
309319
def test_email_valid_intl_local_part(email_input: str, output: ValidatedEmail) -> None:
@@ -363,6 +373,8 @@ def test_domain_literal() -> None:
363373
'email_input,error_msg',
364374
[
365375
('hello.world', 'An email address must have an @-sign.'),
376+
('hello@world', 'The email address has the "full-width" at-sign (@) character instead of a regular at-sign.'),
377+
('hello﹫world', 'The email address has the "small commercial at" character instead of a regular at-sign.'),
366378
('my@localhost', 'The part after the @-sign is not valid. It should have a period.'),
367379
('my@.leadingdot.com', 'An email address cannot have a period immediately after the @-sign.'),
368380
('my@.leadingfwdot.com', 'An email address cannot have a period immediately after the @-sign.'),

0 commit comments

Comments
 (0)