diff --git a/src/chat.rs b/src/chat.rs index 5d7b3a307..53dc0abf8 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -4087,7 +4087,7 @@ pub async fn remove_contact_from_chat( } else { let mut sync = Nosync; - if chat.is_promoted() { + if chat.is_promoted() && chat.typ != Chattype::OutBroadcast { remove_from_chat_contacts_table(context, chat_id, contact_id).await?; } else { remove_from_chat_contacts_table_without_trace(context, chat_id, contact_id).await?; diff --git a/src/chat/chat_tests.rs b/src/chat/chat_tests.rs index ca56e35a2..431da2410 100644 --- a/src/chat/chat_tests.rs +++ b/src/chat/chat_tests.rs @@ -3344,6 +3344,11 @@ async fn test_remove_member_from_broadcast() -> Result<()> { let alice_bob_contact_id = alice.add_or_lookup_contact_id(bob).await; remove_contact_from_chat(alice, alice_chat_id, alice_bob_contact_id).await?; + // Alice must not remember old members, + // because we would like to remember the minimum information possible + let past_contacts = get_past_chat_contacts(alice, alice_chat_id).await?; + assert_eq!(past_contacts.len(), 0); + let remove_msg = alice.pop_sent_msg().await; let rcvd = bob.recv_msg(&remove_msg).await; assert_eq!(rcvd.text, "Member Me removed by alice@example.org."); diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 4d30dc033..562ab23f5 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -247,6 +247,37 @@ impl MimeFactory { // Do not encrypt messages to mailing lists. encryption_pubkeys = None; + } else if let Some(fp) = must_have_only_one_recipient(&msg, &chat) { + let fp = fp?; + // In a broadcast channel, only send member-added/removed messages + // to the affected member + let (authname, addr) = context + .sql + .query_row( + "SELECT authname, addr FROM contacts WHERE fingerprint=?", + (fp,), + |row| { + let authname: String = row.get(0)?; + let addr: String = row.get(1)?; + Ok((authname, addr)) + }, + ) + .await?; + + let public_key_bytes: Vec<_> = context + .sql + .query_get_value( + "SELECT public_key FROM public_keys WHERE fingerprint=?", + (fp,), + ) + .await? + .context("Can't send member addition/removal: missing key")?; + + recipients.push(addr.clone()); + to.push((authname, addr.clone())); + + let public_key = SignedPublicKey::from_slice(&public_key_bytes)?; + encryption_pubkeys = Some(vec![(addr, public_key)]); } else { let email_to_remove = if msg.param.get_cmd() == SystemMessage::MemberRemovedFromGroup { msg.param.get(Param::Arg) @@ -306,13 +337,6 @@ impl MimeFactory { for row in rows { let (authname, addr, fingerprint, id, add_timestamp, remove_timestamp, public_key_bytes_opt) = row?; - // In a broadcast channel, only send member-added/removed messages - // to the affected member: - if let Some(fp) = must_have_only_one_recipient(&msg, &chat) - && fp? != fingerprint { - continue; - } - let public_key_opt = if let Some(public_key_bytes) = &public_key_bytes_opt { Some(SignedPublicKey::from_slice(public_key_bytes)?) } else {