From 03c55362ef14805474941b4c3f011b54c62d9cc9 Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Sun, 5 Jul 2026 09:58:54 +0200 Subject: [PATCH] Fix IDN: `sanitize_email` rejects valid Punycode domains --- CHANGELOG.md | 1 + crates/utils/src/lib.rs | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0777c1a5..5e6369c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - Prometheus: event counters are exported with incorrect metric names. - Registry: Changing the type of an existing account from `user` to `group` panics. - Masked emails: Return `UnknownRecipient` only for disabled or expired masked emails. +- IDN: `sanitize_email` rejects valid Punycode domains. ## [0.16.11] - 2026-06-25 diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 76ea7cd0..d657e9e5 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -285,10 +285,16 @@ pub fn sanitize_email(email: &str) -> Option { for ch in chars { match ch { - '.' | '-' | '_' => { + '.' => { if !last_ch.is_alphanumeric() { return None; } + result.push('.'); + } + '-' | '_' => { + if last_ch == NIL_CHAR || last_ch == '.' { + return None; + } result.push(ch); } ' ' | '\x09'..='\x0d' => continue, @@ -477,6 +483,18 @@ mod tests { ); } + #[test] + fn a_label_email_domains_are_accepted_and_idempotent() { + assert_eq!( + sanitize_email("user@xn--fsqu00a.com").as_deref(), + Some("user@xn--fsqu00a.com") + ); + assert_eq!( + sanitize_email("User@例子.com").as_deref(), + sanitize_email("user@xn--fsqu00a.com").as_deref() + ); + } + #[test] fn to_ascii_domain_borrows_ascii_owns_idn() { assert!(matches!(