---
title: "Trust an email domain only after strict · Agent Wranglers"
url: https://agentwranglers.se/playbook/application-security/authentication-and-sessions/strict-email-parsing
id: APS-15
level: Required
applies: accounts
risk: takeover
updated: 2026-10-27
build: a2a6bdfed830
tokens: 1140
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Trust an email domain only after strict parsing

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: APS-15
- Level: Required
- Chapter: [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md)
- Rule: Before an email domain grants anything, such as joining an organisation or routing single sign-on, check the address against one plain `local@domain` shape. Refuse quotes, comments, encoded words, `%` and more than one `@`.
- Check: A test sends `"a@example.com"@evil.example`, `=?utf-8?q?a=40example.com?=@evil.example`, `a@example.com(@evil.example)`, `a%example.com@evil.example` and `a@evil.example@example.com` to sign-up and to invitations. Each is refused, and no account joins the organisation that claims example.com.
- Risk: An account or system taken over
- Applies when: The project has user accounts.
- How: Parsers and mail servers disagree about unusual addresses. An address such as `"jo@example.com"@evil.example` or one holding an encoded word like `=?utf-8?q?...?=` can read as example.com to the app. The mail server still delivers it to the attacker, who then confirms the address and joins the organisation. RFC 2047 says an encoded word must not appear in any part of an address. Allow only the characters and lengths you need, and convert an international domain to its ASCII form before the check. Store and send to exactly the string you checked. Then confirm it as [Prove the email address before trusting it](https://agentwranglers.se/playbook/accounts/sign-up/email-verification.md) says, and let only [a proven domain](https://agentwranglers.se/playbook/accounts/organisations-and-teams/verified-domains.md) grant access. Compare addresses as [Compare email addresses and usernames in one canonical form](https://agentwranglers.se/playbook/accounts/sign-up/identifier-normalisation.md) says.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
const MAX_ADDRESS_LENGTH = 254;
const PLAIN_ADDRESS = /^[a-z0-9._+-]{1,64}@[a-z0-9-]{1,63}(?:\.[a-z0-9-]{1,63})+$/i;

export function trustedEmailDomain(address) {
  if (address.length > MAX_ADDRESS_LENGTH || !PLAIN_ADDRESS.test(address)) return null;
  return address.split('@')[1].toLowerCase();
}
```

### Python example

```python
import re

MAX_ADDRESS_LENGTH = 254
PLAIN_ADDRESS = re.compile(r"[a-z0-9._+-]{1,64}@[a-z0-9-]{1,63}(?:\.[a-z0-9-]{1,63})+", re.IGNORECASE)

def trusted_email_domain(address: str) -> str | None:
    if len(address) > MAX_ADDRESS_LENGTH or not PLAIN_ADDRESS.fullmatch(address):
        return None
    return address.split("@")[1].lower()
```

## Sources

- [RFC 2047 MIME message header extensions, section 5](https://www.rfc-editor.org/rfc/rfc2047#section-5)

## Related rules

- ACC-2 [Prove the email address before trusting it](https://agentwranglers.se/playbook/accounts/sign-up/email-verification.md) in Accounts and identity
- ACC-43 [Prove a domain before trusting it](https://agentwranglers.se/playbook/accounts/organisations-and-teams/verified-domains.md) in Accounts and identity
- ACC-4 [Compare email addresses and usernames in one canonical form](https://agentwranglers.se/playbook/accounts/sign-up/identifier-normalisation.md) in Accounts and identity

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/application-security/authentication-and-sessions/strict-email-parsing">Agent Wranglers application security playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Make tokens from a secure random source](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/secure-random-tokens.md)
- Next: [Lock down session cookies](https://agentwranglers.se/playbook/application-security/authentication-and-sessions/session-cookies.md)
- [Authentication and sessions](https://agentwranglers.se/playbook/application-security/authentication-and-sessions.md)
