RFC5322 requires to quote the display name if certain special characters are used (see diff).
(backported from commit 7262fae25c7cd25df9443158e3542ad58e7c0ebe on master) Signed-off-by: Lukas Wagner <l.wag...@proxmox.com> --- proxmox-notify/src/endpoints/smtp.rs | 55 +++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/proxmox-notify/src/endpoints/smtp.rs b/proxmox-notify/src/endpoints/smtp.rs index b88e6c95..ada57693 100644 --- a/proxmox-notify/src/endpoints/smtp.rs +++ b/proxmox-notify/src/endpoints/smtp.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::time::Duration; use lettre::message::header::{HeaderName, HeaderValue}; @@ -213,8 +214,10 @@ impl Endpoint for SmtpEndpoint { .clone() .unwrap_or_else(|| context().default_sendmail_author()); + let quoted_author = quote_name_if_needed(&author); + let mut email_builder = - Message::builder().from(parse_address(&format!("{author} <{mail_from}>"))?); + Message::builder().from(parse_address(&format!("{quoted_author} <{mail_from}>"))?); for recipient in recipients { email_builder = email_builder.to(parse_address(&recipient)?); @@ -371,3 +374,53 @@ impl Endpoint for SmtpEndpoint { self.config.disable.unwrap_or_default() } } + +/// Quote mail name if required by RFC5322. +fn quote_name_if_needed(name: &str) -> Cow<str> { + // See https://datatracker.ietf.org/doc/html/rfc5322#section-3.2.3 + let needs_quotes = name.chars().any(|c| { + matches!( + c, + '(' | ')' | '<' | '>' | '@' | ',' | ';' | ':' | '\\' | '"' | '[' | ']' | '=' + ) + }); + + if needs_quotes { + // Quoted strings may contain all printable chars except \ and ", they need to be + // escaped. Non-ASCII UTF-8 characters are later encoded by lettre, we do not + // need to care about them here. + let mut result = name.replace(r#"\"#, r#"\\"#); + result = result.replace(r#"""#, r#"\""#); + Cow::Owned(format!("\"{result}\"")) + } else { + Cow::Borrowed(name) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_quote_mail_name() { + assert_eq!( + "e_name_if_needed("Firstname Lastname"), + "Firstname Lastname" + ); + + assert_eq!( + "e_name_if_needed("Firstname \"Nickname\" Lastname"), + "\"Firstname \\\"Nickname\\\" Lastname\"" + ); + + assert_eq!( + "e_name_if_needed("Proxmox VE (somehost)"), + "\"Proxmox VE (somehost)\"" + ); + + assert_eq!( + "e_name_if_needed("Firstname \\ Lastname"), + "\"Firstname \\\\ Lastname\"" + ); + } +} -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel