diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b81228ec..8e60a3f8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ ### Removed - node: remove unmaintained coverage scripts +### Fixes +- repair encrypted mails "mixed up" by Google Workspace "Append footer" function #3315 + ## 1.80.0 diff --git a/src/e2ee.rs b/src/e2ee.rs index 55bfc162f..26fc5cf15 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -266,13 +266,40 @@ fn get_mixed_up_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Option<&'a ParsedMail< } } +/// Returns a reference to the encrypted payload of a message turned into attachment. +/// +/// Google Workspace has an option "Append footer" which appends standard footer defined +/// by administrator to all outgoing messages. However, there is no plain text part in +/// encrypted messages sent by Delta Chat, so Google Workspace turns the message into +/// multipart/mixed MIME, where the first part is an empty plaintext part with a footer +/// and the second part is the original encrypted message. +fn get_attachment_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Option<&'a ParsedMail<'b>> { + if mail.ctype.mimetype != "multipart/mixed" { + return None; + } + if let [first_part, second_part] = &mail.subparts[..] { + if first_part.ctype.mimetype == "text/plain" + && second_part.ctype.mimetype == "multipart/encrypted" + { + get_autocrypt_mime(second_part) + } else { + None + } + } else { + None + } +} + async fn decrypt_if_autocrypt_message( context: &Context, mail: &ParsedMail<'_>, private_keyring: Keyring, public_keyring_for_validate: Keyring, ) -> Result, HashSet)>> { - let encrypted_data_part = match get_autocrypt_mime(mail).or_else(|| get_mixed_up_mime(mail)) { + let encrypted_data_part = match get_autocrypt_mime(mail) + .or_else(|| get_mixed_up_mime(mail)) + .or_else(|| get_attachment_mime(mail)) + { None => { // not an autocrypt mime message, abort and ignore return Ok(None); @@ -389,6 +416,7 @@ pub async fn ensure_secret_key_exists(context: &Context) -> Result { #[cfg(test)] mod tests { use crate::chat; + use crate::dc_receive_imf::dc_receive_imf; use crate::message::{Message, Viewtype}; use crate::param::Param; use crate::peerstate::ToSave; @@ -592,8 +620,8 @@ Sent with my Delta Chat Messenger: https://delta.chat"; assert!(!encrypt_helper.should_encrypt(&t, false, &ps).unwrap()); } - #[test] - fn test_mixed_up_mime() -> Result<()> { + #[async_std::test] + async fn test_mixed_up_mime() -> Result<()> { // "Mixed Up" mail as received when sending an encrypted // message using Delta Chat Desktop via ProtonMail IMAP/SMTP // Bridge. @@ -601,6 +629,7 @@ Sent with my Delta Chat Messenger: https://delta.chat"; let mail = mailparse::parse_mail(mixed_up_mime)?; assert!(get_autocrypt_mime(&mail).is_none()); assert!(get_mixed_up_mime(&mail).is_some()); + assert!(get_attachment_mime(&mail).is_none()); // Same "Mixed Up" mail repaired by Thunderbird 78.9.0. // @@ -611,6 +640,20 @@ Sent with my Delta Chat Messenger: https://delta.chat"; let mail = mailparse::parse_mail(repaired_mime)?; assert!(get_autocrypt_mime(&mail).is_some()); assert!(get_mixed_up_mime(&mail).is_none()); + assert!(get_attachment_mime(&mail).is_none()); + + // Another form of "Mixed Up" mail created by Google Workspace, + // where original message is turned into attachment to empty plaintext message. + let attachment_mime = include_bytes!("../test-data/message/google-workspace-mixed-up.eml"); + let mail = mailparse::parse_mail(attachment_mime)?; + assert!(get_autocrypt_mime(&mail).is_none()); + assert!(get_mixed_up_mime(&mail).is_none()); + assert!(get_attachment_mime(&mail).is_some()); + + let bob = TestContext::new_bob().await; + dc_receive_imf(&bob, attachment_mime, false).await?; + let msg = bob.get_last_msg().await; + assert_eq!(msg.text.as_deref(), Some("Hello from Thunderbird!")); Ok(()) } diff --git a/test-data/message/google-workspace-mixed-up.eml b/test-data/message/google-workspace-mixed-up.eml new file mode 100644 index 000000000..8ca6dcb17 --- /dev/null +++ b/test-data/message/google-workspace-mixed-up.eml @@ -0,0 +1,78 @@ +Subject: ... +MIME-Version: 1.0 +Date: Tue, 10 May 2022 08:24:11 +0000 +Chat-Version: 1.0 +Message-ID: +To: Bob +From: +Content-Type: multipart/mixed; boundary="000000000000b4907a05dea40c88" + +--000000000000b4907a05dea40c88 +Content-Type: text/plain; charset="UTF-8" +Content-Disposition: inline + + +-- + + + + + + + +--000000000000b4907a05dea40c88 +Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; + boundary="bi1vjiRd9u4EaEuno1ejliJactdnFl" + + +--bi1vjiRd9u4EaEuno1ejliJactdnFl +Content-Type: application/pgp-encrypted +Content-Description: PGP/MIME version identification + +Version: 1 + + +--bi1vjiRd9u4EaEuno1ejliJactdnFl +Content-Type: application/octet-stream; name="encrypted.asc" +Content-Description: OpenPGP encrypted message +Content-Disposition: inline; filename="encrypted.asc"; + +-----BEGIN PGP MESSAGE----- + +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 +=dcQr +-----END PGP MESSAGE----- + + +--bi1vjiRd9u4EaEuno1ejliJactdnFl-- + + +--000000000000b4907a05dea40c88--