Skip to content

Commit 0931d93

Browse files
authored
fix: Never send empty To: header (#6663)
fix #6662 by adding "hidden-recipients:" if To: header would be empty
1 parent 65ea456 commit 0931d93

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

src/mimefactory.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -607,10 +607,7 @@ impl MimeFactory {
607607
|| to.len() + past_members.len() == self.member_timestamps.len()
608608
);
609609
if to.is_empty() {
610-
to.push(Address::new_group(
611-
Some("hidden-recipients".to_string()),
612-
Vec::new(),
613-
));
610+
to.push(hidden_recipients());
614611
}
615612

616613
// Start with Internet Message Format headers in the order of the standard example
@@ -888,21 +885,23 @@ impl MimeFactory {
888885
} else if header_name == "to" {
889886
protected_headers.push(header.clone());
890887
if is_encrypted {
888+
let mut to_without_names = to
889+
.clone()
890+
.into_iter()
891+
.filter_map(|header| match header {
892+
Address::Address(mb) => Some(Address::Address(EmailAddress {
893+
name: None,
894+
email: mb.email,
895+
})),
896+
_ => None,
897+
})
898+
.collect::<Vec<_>>();
899+
if to_without_names.is_empty() {
900+
to_without_names.push(hidden_recipients());
901+
}
891902
unprotected_headers.push((
892903
original_header_name,
893-
Address::new_list(
894-
to.clone()
895-
.into_iter()
896-
.filter_map(|header| match header {
897-
Address::Address(mb) => Some(Address::Address(EmailAddress {
898-
name: None,
899-
email: mb.email,
900-
})),
901-
_ => None,
902-
})
903-
.collect::<Vec<_>>(),
904-
)
905-
.into(),
904+
Address::new_list(to_without_names).into(),
906905
));
907906
} else {
908907
unprotected_headers.push(header.clone());
@@ -1633,6 +1632,10 @@ impl MimeFactory {
16331632
}
16341633
}
16351634

1635+
fn hidden_recipients() -> Address<'static> {
1636+
Address::new_group(Some("hidden-recipients".to_string()), Vec::new())
1637+
}
1638+
16361639
async fn build_body_file(context: &Context, msg: &Message) -> Result<MimePart<'static>> {
16371640
let file_name = msg.get_filename().context("msg has no file")?;
16381641
let suffix = Path::new(&file_name)

src/mimefactory/mimefactory_tests.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,3 +898,23 @@ async fn test_dont_remove_self() -> Result<()> {
898898

899899
Ok(())
900900
}
901+
902+
/// Regression test: mimefactory should never create an empty to header,
903+
/// also not if the Selftalk parameter is missing
904+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
905+
async fn test_no_empty_to_header() -> Result<()> {
906+
let alice = &TestContext::new_alice().await;
907+
let mut self_chat = alice.get_self_chat().await;
908+
self_chat.param.remove(Param::Selftalk);
909+
self_chat.update_param(alice).await?;
910+
911+
let payload = alice.send_text(self_chat.id, "Hi").await.payload;
912+
assert!(
913+
// It would be equally fine if the payload contained `To: alice@example.org` or similar,
914+
// as long as it's a valid header
915+
payload.contains("To: \"hidden-recipients\": ;"),
916+
"Payload doesn't contain correct To: header: {payload}"
917+
);
918+
919+
Ok(())
920+
}

0 commit comments

Comments
 (0)