Your question
Email addresses with reserved TLDs (.local, .internal, etc.) are rejected even though domains with these TLDs are accepted. This prevents setting a catchAllAddress like [email protected] on a domain m.internal.
Steps to Reproduce
- Create domain m.internal - succeeds
- Set catchAllAddress: “[email protected]” - fails with “Invalid email address”
Related Code
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on
Let me look at the relevant source code to understand this issue properly.
You’ve identified a real inconsistency in the source code. Looking at the code directly:
sanitize_domain calls is_valid_domain(), which explicitly allows reserved TLDs ("test", "localhost", "local", "internal") – so m.internal passes.
sanitize_email does not call is_valid_domain(). Its final check is hardcoded to only use the PSL (Public Suffix List): psl::domain(...).is_some_and(|d| d.suffix().typ().is_some()) – reserved TLDs are not in the PSL, so [email protected] fails.
This is a bug: sanitize_email should mirror the reserved-TLD logic from is_valid_domain() so that an email address on a locally-valid domain (one that sanitize_domain would accept) is also accepted. The fix would be to replace the final PSL-only check in sanitize_email with the same is_valid_domain() call used by sanitize_domain.
There is no configuration workaround for this – it’s a code-level inconsistency. A human team member will need to review and patch sanitize_email in crates/utils/src/lib.rs.
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong. If you found it useful, mention @helpbot in any reply to ask follow-up questions and the bot will respond again.
A fix will be included in v0.16.6.