From 00e1d00dfa5b64f19a59386fdf3fe4fca7a1d346 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sat, 25 Jul 2026 23:15:27 +0200 Subject: [PATCH] fix: send MDNs to all authentic relays of a contact, not just whatever get_addr() returns. --- src/mimefactory.rs | 4 +++- src/mimefactory/mimefactory_tests.rs | 30 +++++++++++++++++++++++++++- src/smtp.rs | 9 +++++---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 72ecd3468..7abae8621 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -578,10 +578,12 @@ impl MimeFactory { let timestamp = time(); let addr = contact.get_addr().to_string(); + let mut recipients = vec![addr.clone()]; let encryption_pubkeys = if from_id == ContactId::SELF { Some(Vec::new()) } else if contact.is_key_contact() { if let Some(key) = contact.public_key(context).await? { + recipients = addresses_from_public_key(&key).unwrap_or_else(|| vec![addr.clone()]); Some(vec![(addr.clone(), key)]) } else { Some(Vec::new()) @@ -595,7 +597,7 @@ impl MimeFactory { from_displayname: "".to_string(), sender_displayname: None, selfstatus: "".to_string(), - recipients: vec![addr], + recipients, encryption_pubkeys, to: vec![("".to_string(), contact.get_addr().to_string())], past_members: vec![], diff --git a/src/mimefactory/mimefactory_tests.rs b/src/mimefactory/mimefactory_tests.rs index a508fa455..937fdacbd 100644 --- a/src/mimefactory/mimefactory_tests.rs +++ b/src/mimefactory/mimefactory_tests.rs @@ -14,8 +14,9 @@ use crate::chat::{ }; use crate::chatlist::Chatlist; use crate::constants; -use crate::contact::{Origin, import_vcard}; +use crate::contact::{Origin, import_public_key, import_vcard}; use crate::headerdef::HeaderDef; +use crate::key::{load_self_secret_key, secret_key_to_public_key}; use crate::message; use crate::mimeparser::MimeMessage; use crate::receive_imf::receive_imf; @@ -327,6 +328,33 @@ async fn test_mdn_create_encrypted() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_mdn_sent_to_all_relays() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + + let rcvd = tcm.send_recv_accept(bob, alice, "Heyho").await; + + // Bob's key gets a second relay address and Alice merges the newer key. + let bob_secret_key = load_self_secret_key(bob).await?; + let bob_public_key = secret_key_to_public_key( + bob, + bob_secret_key, + u32::try_from(time())? + 100, + "bob@example.net", + "bob@example.net,bob@relay2.example", + )?; + import_public_key(alice, &bob_public_key).await?; + + let mimefactory = MimeFactory::from_mdn(alice, rcvd.from_id, rcvd.rfc724_mid, vec![]).await?; + let mut recipients = mimefactory.recipients(); + recipients.sort(); + assert_eq!(recipients, vec!["bob@example.net", "bob@relay2.example"]); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_mdn_autocrypt_throttle() -> Result<()> { async fn mdn_has_aheader( diff --git a/src/smtp.rs b/src/smtp.rs index 9c29fb7e5..0655c761a 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -596,13 +596,14 @@ async fn send_mdn_rfc724_mid( ) .await?; let encrypted = mimefactory.will_be_encrypted(); + let mut recipients = if contact_id == ContactId::SELF { + Vec::new() + } else { + mimefactory.recipients() + }; let rendered_msg = Box::pin(mimefactory.render(context)).await?; let body = rendered_msg.message; - let mut recipients = Vec::new(); - if contact_id != ContactId::SELF { - recipients.push(contact.get_addr().to_string()); - } if context.get_config_bool(Config::BccSelf).await? { add_self_recipients(context, &mut recipients, encrypted).await?; }