From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 337C41FF170 for ; Thu, 26 Jun 2025 14:54:34 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 47DEC39421; Thu, 26 Jun 2025 14:55:09 +0200 (CEST) From: Lukas Wagner To: pbs-devel@lists.proxmox.com Date: Thu, 26 Jun 2025 14:54:29 +0200 Message-Id: <20250626125429.347246-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.020 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_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [smtp.rs, ietf.org] Subject: [pbs-devel] [PATCH proxmox] fix #6188: notify: smtp: quote sender's display name if needed X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox Backup Server development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pbs-devel-bounces@lists.proxmox.com Sender: "pbs-devel" RFC5322 requires to quote the display name if certain special characters are used (see diff). Signed-off-by: Lukas Wagner --- Notes: The sendmail endpoint does not seem to need this, apparently sendmail does the quoting automatically. proxmox-notify/src/endpoints/smtp.rs | 56 ++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/proxmox-notify/src/endpoints/smtp.rs b/proxmox-notify/src/endpoints/smtp.rs index b684d8ca..d4fed237 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)?); @@ -377,14 +380,61 @@ fn build_forwarded_message( Ok(message) } -#[cfg(all(test, feature = "mail-forwarder"))] +/// 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 lettre::message::header::Date; 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\"" + ); + } + + #[cfg(feature = "mail-forwarder")] #[test] fn test_forward_message_from_raw() { + use lettre::message::header::Date; + let input = "testdata/test1.msg"; let reference = "testdata/test_forward_message_from_raw.ref"; -- 2.39.5 _______________________________________________ pbs-devel mailing list pbs-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel