From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 567031FF183 for ; Wed, 16 Jul 2025 11:13:02 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 32C91B14D; Wed, 16 Jul 2025 11:14:08 +0200 (CEST) From: Lukas Wagner To: pve-devel@lists.proxmox.com Date: Wed, 16 Jul 2025 11:13:26 +0200 Message-Id: <20250716091326.144240-1-l.wagner@proxmox.com> X-Mailer: git-send-email 2.39.5 MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.019 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_MSPIKE_H2 0.001 Average reputation (+2) SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH proxmox stable-bookworm] fix #6188: notify: smtp: quote sender's display name if needed X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" 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 --- 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 { + // 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