diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 6d954328a..98cdbec1d 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -127,69 +127,74 @@ impl MimeMessage { let mail_raw; let mut gossipped_addr = Default::default(); - let (mail, signatures) = match e2ee::try_decrypt(context, &mail, message_time).await { - Ok((raw, signatures)) => { - if let Some(raw) = raw { - // Encrypted, but maybe unsigned message. Only if - // `signatures` set is non-empty, it is a valid - // autocrypt message. + let (mail, signatures, warn_empty_signature) = + match e2ee::try_decrypt(context, &mail, message_time).await { + Ok((raw, signatures)) => { + if let Some(raw) = raw { + // Encrypted, but maybe unsigned message. Only if + // `signatures` set is non-empty, it is a valid + // autocrypt message. - mail_raw = raw; - let decrypted_mail = mailparse::parse_mail(&mail_raw)?; - if std::env::var(crate::DCC_MIME_DEBUG).is_ok() { - info!(context, "decrypted message mime-body:"); - println!("{}", String::from_utf8_lossy(&mail_raw)); + mail_raw = raw; + let decrypted_mail = mailparse::parse_mail(&mail_raw)?; + if std::env::var(crate::DCC_MIME_DEBUG).is_ok() { + info!(context, "decrypted message mime-body:"); + println!("{}", String::from_utf8_lossy(&mail_raw)); + } + + // Handle any gossip headers if the mail was encrypted. See section + // "3.6 Key Gossip" of https://autocrypt.org/autocrypt-spec-1.1.0.pdf + // but only if the mail was correctly signed: + if !signatures.is_empty() { + let gossip_headers = + decrypted_mail.headers.get_all_values("Autocrypt-Gossip"); + gossipped_addr = update_gossip_peerstates( + context, + message_time, + &mail, + gossip_headers, + ) + .await?; + } + + // let known protected headers from the decrypted + // part override the unencrypted top-level + + // Signature was checked for original From, so we + // do not allow overriding it. + let mut throwaway_from = from.clone(); + + // We do not want to allow unencrypted subject in encrypted emails because the user might falsely think that the subject is safe. + // See https://github.com/deltachat/deltachat-core-rust/issues/1790. + headers.remove("subject"); + + MimeMessage::merge_headers( + context, + &mut headers, + &mut recipients, + &mut throwaway_from, + &mut chat_disposition_notification_to, + &decrypted_mail.headers, + ); + + (decrypted_mail, signatures, true) + } else { + // Message was not encrypted + (mail, signatures, false) } - - // Handle any gossip headers if the mail was encrypted. See section - // "3.6 Key Gossip" of https://autocrypt.org/autocrypt-spec-1.1.0.pdf - // but only if the mail was correctly signed: - if !signatures.is_empty() { - let gossip_headers = - decrypted_mail.headers.get_all_values("Autocrypt-Gossip"); - gossipped_addr = - update_gossip_peerstates(context, message_time, &mail, gossip_headers) - .await?; - } - - // let known protected headers from the decrypted - // part override the unencrypted top-level - - // Signature was checked for original From, so we - // do not allow overriding it. - let mut throwaway_from = from.clone(); - - // We do not want to allow unencrypted subject in encrypted emails because the user might falsely think that the subject is safe. - // See https://github.com/deltachat/deltachat-core-rust/issues/1790. - headers.remove("subject"); - - MimeMessage::merge_headers( - context, - &mut headers, - &mut recipients, - &mut throwaway_from, - &mut chat_disposition_notification_to, - &decrypted_mail.headers, - ); - - (decrypted_mail, signatures) - } else { - // Message was not encrypted - (mail, signatures) } - } - Err(err) => { - // continue with the current, still encrypted, mime tree. - // unencrypted parts will be replaced by an error message - // that is added as "the message" to the chat then. - // - // if we just return here, the header is missing - // and the caller cannot display the message - // and try to assign the message to a chat - warn!(context, "decryption failed: {}", err); - (mail, Default::default()) - } - }; + Err(err) => { + // continue with the current, still encrypted, mime tree. + // unencrypted parts will be replaced by an error message + // that is added as "the message" to the chat then. + // + // if we just return here, the header is missing + // and the caller cannot display the message + // and try to assign the message to a chat + warn!(context, "decryption failed: {}", err); + (mail, Default::default(), true) + } + }; let mut parser = MimeMessage { parts: Vec::new(), @@ -215,7 +220,7 @@ impl MimeMessage { parser.heuristically_parse_ndn(context).await; parser.parse_headers(context)?; - if parser.signatures.is_empty() { + if warn_empty_signature && parser.signatures.is_empty() { for part in parser.parts.iter_mut() { part.error = "No valid signature".to_string(); }