Skip to content

Commit 37ddfb2

Browse files
committed
Reject IPv6 domain literals with a zone index
ipaddress.IPv6Address accepts '%scope' since Python 3.9, but RFC 5321's IPv6-addr has no zone index, so 'me@[IPv6:fe80::1%eth0]' was accepted.
1 parent c0cc1bc commit 37ddfb2

2 files changed

Lines changed: 14 additions & 0 deletions

File tree

‎email_validator/syntax.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ def validate_email_domain_literal(domain_literal: str) -> DomainLiteralValidatio
791791
except ValueError as e:
792792
raise EmailSyntaxError(f"The IPv6 address in brackets after the @-sign is not valid ({e}).") from e
793793

794+
# Python accepts a zone index ("%eth0") but RFC 5321 4.1.3 does not.
795+
if addr.scope_id is not None:
796+
raise EmailSyntaxError("The IPv6 address in brackets after the @-sign is not valid (It has a zone index).")
797+
794798
# Return the IPv6Address object and construct a normalized
795799
# domain literal.
796800
return {

‎tests/test_syntax.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,16 @@ def test_domain_literal() -> None:
407407
assert validated.domain == "[IPv6:::1]"
408408
assert repr(validated.domain_address) == "IPv6Address('::1')"
409409

410+
# Check that an IPv4 address in an IPv6 address is accepted.
411+
validated = validate_email("me@[IPv6:::ffff:1.2.3.4]", allow_domain_literal=True)
412+
assert validated.domain == "[IPv6:::ffff:1.2.3.4]"
413+
414+
# Check that IPv6 zone indexes are rejected.
415+
for email_input in ("me@[IPv6:fe80::1%eth0]", "me@[IPv6:::1%]]"):
416+
with pytest.raises(EmailSyntaxError) as exc_info:
417+
validate_email(email_input, allow_domain_literal=True)
418+
assert str(exc_info.value) == "The IPv6 address in brackets after the @-sign is not valid (It has a zone index)."
419+
410420

411421
@pytest.mark.parametrize(
412422
'email_input,error_msg',

0 commit comments

Comments
 (0)