Skip to content

Accept at-signs inside quoted email local parts - #515

Closed
prnvh wants to merge 1 commit into
python-validators:masterfrom
prnvh:fix/quoted-email-at-signs
Closed

prnvh wants to merge 1 commit into
python-validators:masterfrom
prnvh:fix/quoted-email-at-signs

Conversation

@prnvh

@prnvh prnvh commented Oct 15, 2026

Copy link
Copy Markdown

The email validator rejects valid quoted local parts containing @, such as "test@test"@example.com, because its early guard requires exactly one at-sign in the entire address.

RFC 5321 section 4.1.2 permits @ inside a quoted local part. The function already splits at the final at-sign and validates the complete local part and domain separately, so the guard only needs to require that a separator is present.

This change:

  • Allows at-signs inside quoted local parts, including multiple at-signs.
  • Moves the existing "test@test"@example.com fixture from invalid to valid cases.
  • Adds regression tests for quoted at-signs and malformed addresses, including unquoted extra separators, unmatched quotes, missing domains and invalid domains.

Standard reference: https://www.rfc-editor.org/rfc/rfc5321#section-4.1.2

Validation on Python 3.12.14:

  • Before the fix, the email regression suite has four failures and 40 passes.
  • With the fix, pytest . -q: 1,182 passed.
  • tox -e py312: passed, including a fresh source-distribution build and 1,182 tests.
  • ruff check . and ruff format --check .: passed.
  • pyright --pythonpath .venv/Scripts/python.exe .: zero errors or warnings.
  • bandit -c pyproject.toml -r src/validators: no issues identified.

@nandgator

Copy link
Copy Markdown
Collaborator

Thanks for the careful write-up and tests. You're right that RFC 5321 allows @ inside a quoted local part, but I'm going to keep the one-@ rule, so I'm closing this.

The rule is deliberate. With this change, "a@evil.com"@good.com validates, and any code that splits the address at the first @ reads the domain as evil.com"@good.com. That mismatch between parsers is the attack class in PortSwigger's Splitting the email atom research, which used it to bypass domain-based access controls. Most callers validate an address and then hand it to other code, so a validator that accepts it is the risky side of that mismatch. Real mailboxes with a quoted @ are vanishingly rare, so the strictness costs little.

@nandgator nandgator closed this Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants