diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 5d103eef6..1891de91e 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -271,7 +271,7 @@ impl MimeMessage { &mut from, &mut list_post, &mut chat_disposition_notification_to, - &mail.headers, + &mail, ); headers.retain(|k, _| { !is_hidden(k) || { @@ -299,7 +299,7 @@ impl MimeMessage { &mut from, &mut list_post, &mut chat_disposition_notification_to, - &part.headers, + part, ); (part, part.ctype.mimetype.parse::()?) } else { @@ -536,7 +536,7 @@ impl MimeMessage { &mut inner_from, &mut list_post, &mut chat_disposition_notification_to, - &mail.headers, + mail, ); if !signatures.is_empty() { @@ -1632,6 +1632,11 @@ impl MimeMessage { } } + /// Merges headers from the email `part` into `headers` respecting header protection. + /// Should only be called with nonempty `headers` if `part` is a root of the Cryptographic + /// Payload as defined in "Header Protection for + /// Cryptographically Protected Email", otherwise this may unnecessarily discard headers from + /// outer parts. #[allow(clippy::too_many_arguments)] fn merge_headers( context: &Context, @@ -1642,10 +1647,14 @@ impl MimeMessage { from: &mut Option, list_post: &mut Option, chat_disposition_notification_to: &mut Option, - fields: &[mailparse::MailHeader<'_>], + part: &mailparse::ParsedMail, ) { + let fields = &part.headers; + // See . + let has_header_protection = part.ctype.params.contains_key("hp"); + headers.retain(|k, _| { - !is_protected(k) || { + !(has_header_protection || is_protected(k)) || { headers_removed.insert(k.to_string()); false } @@ -2096,7 +2105,8 @@ pub(crate) fn parse_message_id(ids: &str) -> Result { } /// Returns whether the outer header value must be ignored if the message contains a signed (and -/// optionally encrypted) part. +/// optionally encrypted) part. This is independent from the modern Header Protection defined in +/// . /// /// NB: There are known cases when Subject and List-ID only appear in the outer headers of /// signed-only messages. Such messages are shown as unencrypted anyway.