diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 21dcf1c05..9a59a4624 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -630,8 +630,7 @@ pub(crate) async fn receive_imf_inner( return Ok(None); }; - let prevent_rename = (mime_parser.is_mailinglist_message() && !mime_parser.was_encrypted()) - || mime_parser.get_header(HeaderDef::Sender).is_some(); + let prevent_rename = should_prevent_rename(&mime_parser); // get From: (it can be an address list!) and check if it is known (for known From:'s we add // the other To:/Cc: in the 3rd pass) @@ -1397,7 +1396,6 @@ async fn do_chat_assignment( context, mime_parser, to_ids, - from_id, allow_creation || test_normal_chat.is_some(), create_blocked, is_partial_download.is_some(), @@ -1567,7 +1565,6 @@ async fn do_chat_assignment( context, mime_parser, to_ids, - from_id, allow_creation, Blocked::Not, is_partial_download.is_some(), @@ -2464,7 +2461,6 @@ async fn lookup_or_create_adhoc_group( context: &Context, mime_parser: &MimeMessage, to_ids: &[Option], - from_id: ContactId, allow_creation: bool, create_blocked: Blocked, is_partial_download: bool, @@ -2487,6 +2483,20 @@ async fn lookup_or_create_adhoc_group( return Ok(None); } + // Lookup address-contact by the From address. + let fingerprint = None; + let find_key_contact_by_addr = false; + let prevent_rename = should_prevent_rename(mime_parser); + let (from_id, _from_id_blocked, _incoming_origin) = from_field_to_contact_id( + context, + &mime_parser.from, + fingerprint, + prevent_rename, + find_key_contact_by_addr, + ) + .await? + .context("Cannot lookup addres-contact by the From field")?; + let grpname = mime_parser .get_subject() .map(|s| remove_subject_prefix(&s)) @@ -3963,5 +3973,12 @@ async fn lookup_key_contacts_by_address_list( Ok(contact_ids) } +/// Returns true if the message should not result in renaming +/// of the sender contact. +fn should_prevent_rename(mime_parser: &MimeMessage) -> bool { + (mime_parser.is_mailinglist_message() && !mime_parser.was_encrypted()) + || mime_parser.get_header(HeaderDef::Sender).is_some() +} + #[cfg(test)] mod receive_imf_tests; diff --git a/src/receive_imf/receive_imf_tests.rs b/src/receive_imf/receive_imf_tests.rs index 0fe1b4f16..a8ba00785 100644 --- a/src/receive_imf/receive_imf_tests.rs +++ b/src/receive_imf/receive_imf_tests.rs @@ -5352,3 +5352,57 @@ async fn test_group_introduction_no_gossip() -> Result<()> { Ok(()) } + +/// Tests reception of an encrypted group message +/// without Chat-Group-ID. +/// +/// The message should be displayed as +/// encrypted and have key-contact `from_id`, +/// but all group members should be address-contacts. +/// +/// Due to a bug in v2.10.0 this resulted +/// in creation of an ad hoc group with a key-contact. +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_encrypted_adhoc_group_message() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + + // Bob receives encrypted message from Alice + // sent to multiple recipients, + // but without a group ID. + let received = receive_imf( + bob, + include_bytes!("../../test-data/message/encrypted-group-without-id.eml"), + false, + ) + .await? + .unwrap(); + let msg = Message::load_from_db(bob, *received.msg_ids.last().unwrap()) + .await + .unwrap(); + + let chat = Chat::load_from_db(bob, msg.chat_id).await.unwrap(); + assert_eq!(chat.typ, Chattype::Group); + assert_eq!(chat.is_encrypted(bob).await?, false); + + let contact_ids = get_chat_contacts(bob, chat.id).await?; + assert_eq!(contact_ids.len(), 3); + assert!(chat.is_self_in_chat(bob).await?); + + // Since the group is unencrypted, all contacts have + // to be address-contacts. + for contact_id in contact_ids { + let contact = Contact::get_by_id(bob, contact_id).await?; + if contact_id != ContactId::SELF { + assert_eq!(contact.is_key_contact(), false); + } + } + + // `from_id` of the message corresponds to key-contact of Alice + // even though the message is assigned to unencrypted chat. + let alice_contact_id = bob.add_or_lookup_contact_id(alice).await; + assert_eq!(msg.from_id, alice_contact_id); + + Ok(()) +} diff --git a/test-data/message/encrypted-group-without-id.eml b/test-data/message/encrypted-group-without-id.eml new file mode 100644 index 000000000..9a593208f --- /dev/null +++ b/test-data/message/encrypted-group-without-id.eml @@ -0,0 +1,69 @@ +Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; + boundary="18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17" +MIME-Version: 1.0 +From: +To: , +Subject: [...] +Date: Mon, 28 Jul 2025 14:15:14 +0000 +Message-ID: <48b9e9cc-2bae-4d41-89b4-a409e2c60c28@localhost> +References: <48b9e9cc-2bae-4d41-89b4-a409e2c60c28@localhost> +Chat-Version: 1.0 +Autocrypt: addr=alice@example.org; prefer-encrypt=mutual; keydata=mDMEXlh13RYJKwYBBAHaRw8BAQdAzfVIAleCXMJrq8VeLlEVof6ITCviMktKjmcBKAu4m5 + C0GUFsaWNlIDxhbGljZUBleGFtcGxlLm9yZz7CkgQQFggAOgUCaIeF8RYhBC5vossjtTLXKGNLWGSw + j2Gp7ZRDAhsDAh4BBQsJCAcCBhUKCQgLAgQWAgMBAScCGQEACgkQZLCPYantlEM66gD/b9qi1/H1Cr + UwwlW2akVX86Q0gX6isyKfuNu/CdTdzaQBAIHRxvwlBNZr56qMGL7CyVy6LmBslLlbQwAdclM9t9UE + uDgEXlh13RIKKwYBBAGXVQEFAQEHQAbtyNbLZIUBTwqeW2W5tVbrusWLJ+nTUmtF7perLbYdAwEIB8 + J4BBgWCAAgBQJoh4XxAhsMFiEELm+iyyO1MtcoY0tYZLCPYantlEMACgkQZLCPYantlEPG2QD8DthL + 48j1wnjw+Kby7CmAm/M+Me82izk8dGNPn442jJ4A/2r+YmqfUPK2XDXPRwvVBAIz5bL44fe7gNkUUu + XMnzkP + + +--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17 +Content-Type: application/pgp-encrypted; charset="utf-8" +Content-Description: PGP/MIME version identification +Content-Transfer-Encoding: 7bit + +Version: 1 + +--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17 +Content-Type: application/octet-stream; name="encrypted.asc"; + charset="utf-8" +Content-Description: OpenPGP encrypted message +Content-Disposition: inline; filename="encrypted.asc"; +Content-Transfer-Encoding: 7bit + +-----BEGIN PGP MESSAGE----- + +wV4D5tq63hTeebASAQdA5TP3lUjawDdYRzMW0HUyxu0kFUgWtYo+O6pyNE0FJRQw +JKI3nzp0ymh7YKVftd1rc25tWJ2Vjo9ase7H1puGHsfmnY7sqlsMfXrIahM9BGH6 +wcBMA+PY3JvEjuMiAQf7BYh7QtxJFimYIj/z8oevEu2YywQhYCl0GFslqDt+45/a +O/49ivcVfr7U0HZoGVTzzrS8+1K//lSj5VLr6pxUNHTNZMIvN1AGRYTpZP4BktYO +uPOhWdNgq30bt4ufxKTRt4mKm2W7OcexyWLkRX19+W2uGm44PP4o3uKQOLJpIZY3 +1QKCNCt/JKeF8v3/jmBZqIrtZUC3tB2RwO5MOOjnE2RoE0tLNFvlGJA9TBRvEAhH +4WA+m3kjAeQh0YNG9ujZAgzm8PRvXyiIdhOggpVJ6lVdXXgZMyiglamHdAG8cTcY +VJxI4bR0ZLMXhMqLgLoNfGDpiM75B+5fKJ7U9ICwKcHATAOfNAZQDav2jwEH/0W8 +EwR2OuHbB5EphrJ6IisPfE8FrR4BbRs4lMZ6tH1oCrGsoAwr3FtpN9C7o+a0Jp5+ +qiYmXDnThipsnMbd0P5OLhZvtG3ZEf9N69hBmDFmWiSJtG+7n1NRlTJ8H9H1r6gO +M07bVqca5bmXiVsTavQ87io0Pr8WGcTUfggqOp3WM1SRNgovE+3ZE8w/ugVIshVz +ri70ZVxAqC1s/0dg9NH4JAnegf8Ds3pRMvSwBaF4EArZ1IPpcNArA592GBKf8BuA +0WGuPSaB/QHSRf9Kar2Wt3/AJXZ8SPCo2S8K/Joc3nuOV2evlKIDeMR9ezbpdWHU +bc5CrZj4U5T3PJx+mLrSwesBPtVHq90EC3+/WpXOd1xlFcVy5CqRVbNOiBFO4fMY +hwnGFFKyK8h8AYU54yXlGdLFeuZSDPTJNueWI917jEIoh2gJm0vJBhdLDhNyPQH8 +FwTn6PM29pw5F9Mz4ZEkLqyffGAcWq1CFW8FHDu6pshKFFyPXSolOq+1kbqEgpsV +mYxAZIUJMqrOTAALYyp9kwjjb+O99NCCVNBAjULhG3vme4l8YiAiewQYd5pItcj8 +pWI1h+Dp7xWKRrPWVj7TH3gqphRtFm+1X9bw+h4Uz+Qs8bwp7bpIj+SGwEgIDjf5 +gefdhpUYf44xcFWALpQJUHNkLXGCs13GXuRUi/eFaDE/cY9JSkbVDPt7BColO5KD +sfzcWxVzE7EqmY8zixR387Fj5BnyjAGm7Kxj7iWkJtngAEKsRbC1PbPUP1O3equs +bM2mMfIBVPep7rWjWHs3uweM2ULUCJkT5wurUR9Pkn+t7jxReNcjWtR9dR0MAksp +GW7qsxIE4EQ86n3X34sR3TNRANIfC1qBFOHa5L5rI6cnyK9e1WSasdRMsZ74e1ot +SySYW0mVZxA/ZV5SYiVWbZVk58PJqdlWasF3blgKwEYjs6AJTpKMBj3YjAnr6CeK +5jWc5wWxyihtRyyriKvFVII0YBbdHF3+W1dnFQGakgWeEPxt1d5zPnizo0V9BewT +BnKlxrj1DtU8n79qRBp4yK2Ks/W/aQxQheEJ00t5ua8aUJTaj6RQqiK5GcH6DU/D +LerLVfRNwDk8mh3YBTOe65ovGa2/WfWXXs/0nHGOhX2ayhd3gtyMnizRohLJZsMK +gYWkF9k6vMBs7mZhm0lobVatYianJkM1cT5DdOtVqfO95K3GOHE7ON9WiZLkmXTH +WEp750aqWjdiu0uveoY7hoAxL+A/IshTQWhXMQ== +=ESpw +-----END PGP MESSAGE----- + + +--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17--