From 2e69210825238cc89d9ac9e147df796296e39d30 Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 5 Jan 2024 00:00:58 +0000 Subject: [PATCH 1/3] refactor: use wait_for_incoming_msg_event() more --- deltachat-rpc-client/tests/test_something.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/deltachat-rpc-client/tests/test_something.py b/deltachat-rpc-client/tests/test_something.py index 2ceb98c995..807a966df7 100644 --- a/deltachat-rpc-client/tests/test_something.py +++ b/deltachat-rpc-client/tests/test_something.py @@ -140,12 +140,9 @@ def test_chat(acfactory) -> None: alice_chat_bob = alice_contact_bob.create_chat() alice_chat_bob.send_text("Hello!") - while True: - event = bob.wait_for_event() - if event.kind == EventType.INCOMING_MSG: - chat_id = event.chat_id - msg_id = event.msg_id - break + event = bob.wait_for_incoming_msg_event() + chat_id = event.chat_id + msg_id = event.msg_id message = bob.get_message_by_id(msg_id) snapshot = message.get_snapshot() assert snapshot.chat_id == chat_id @@ -224,12 +221,9 @@ def test_message(acfactory) -> None: alice_chat_bob = alice_contact_bob.create_chat() alice_chat_bob.send_text("Hello!") - while True: - event = bob.wait_for_event() - if event.kind == EventType.INCOMING_MSG: - chat_id = event.chat_id - msg_id = event.msg_id - break + event = bob.wait_for_incoming_msg_event() + chat_id = event.chat_id + msg_id = event.msg_id message = bob.get_message_by_id(msg_id) snapshot = message.get_snapshot() From 4dc596e646df02d1097e0ab94075f6efc89dc63c Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 5 Jan 2024 01:42:24 +0000 Subject: [PATCH 2/3] fix(mimefactory): do not wrap MDNs into multipart/mixed part --- src/mimefactory.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/mimefactory.rs b/src/mimefactory.rs index fff1942766..5ed9e57266 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -768,6 +768,30 @@ impl<'a> MimeFactory<'a> { .build(), ) .header(("Subject".to_string(), "...".to_string())) + } else if matches!(self.loaded, Loaded::Mdn { .. }) { + // Never add outer multipart/mixed wrapper to MDN + // as multipart/report Content-Type is used to recognize MDNs + // by Delta Chat receiver and Chatmail servers + // allowing them to be unencrypted and not contain Autocrypt header + // without resetting Autocrypt encryption or triggering Chatmail filter + // that normally only allows encrypted mails. + + // Hidden headers are dropped. + + // Store protected headers in the outer message. + let message = headers + .protected + .iter() + .fold(message, |message, header| message.header(header.clone())); + + let protected: HashSet
= HashSet::from_iter(headers.protected.into_iter()); + for h in headers.unprotected.split_off(0) { + if !protected.contains(&h) { + headers.unprotected.push(h); + } + } + + message } else { // Store hidden headers in the inner unencrypted message. let message = headers From 3bcdd1770afd917ea7f26c29573342a84d96208d Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 5 Jan 2024 00:00:29 +0000 Subject: [PATCH 3/3] test: test that read receipts don't degrade encryption This is broken since 44227d7b866f4aa173c63ffc989f38b44774e40d mimeparser only recognizes read receipts by the Content-Type being "multipart/report". If multipart/report is hidden inside multipart/mixed and the message is not encrypted, it degrades encryption. --- deltachat-rpc-client/tests/test_something.py | 43 ++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/deltachat-rpc-client/tests/test_something.py b/deltachat-rpc-client/tests/test_something.py index 807a966df7..6e1b08998b 100644 --- a/deltachat-rpc-client/tests/test_something.py +++ b/deltachat-rpc-client/tests/test_something.py @@ -396,3 +396,46 @@ def test_provider_info(rpc) -> None: rpc.set_config(account_id, "socks5_enabled", "1") provider_info = rpc.get_provider_info(account_id, "github.com") assert provider_info is None + + +def test_mdn_doesnt_break_autocrypt(acfactory) -> None: + alice, bob = acfactory.get_online_accounts(2) + + bob_addr = bob.get_config("addr") + + alice_contact_bob = alice.create_contact(bob_addr, "Bob") + + # Bob creates chat manually so chat with Alice is accepted. + alice_chat_bob = alice_contact_bob.create_chat() + + # Alice sends a message to Bob. + alice_chat_bob.send_text("Hello Bob!") + event = bob.wait_for_incoming_msg_event() + msg_id = event.msg_id + message = bob.get_message_by_id(msg_id) + snapshot = message.get_snapshot() + + # Bob sends a message to Alice. + bob_chat_alice = snapshot.chat + bob_chat_alice.accept() + bob_chat_alice.send_text("Hello Alice!") + event = alice.wait_for_incoming_msg_event() + msg_id = event.msg_id + message = alice.get_message_by_id(msg_id) + snapshot = message.get_snapshot() + assert snapshot.show_padlock + + # Alice reads Bob's message. + message.mark_seen() + while True: + event = bob.wait_for_event() + if event.kind == EventType.MSG_READ: + break + + # Bob sends a message to Alice, it should also be encrypted. + bob_chat_alice.send_text("Hi Alice!") + event = alice.wait_for_incoming_msg_event() + msg_id = event.msg_id + message = alice.get_message_by_id(msg_id) + snapshot = message.get_snapshot() + assert snapshot.show_padlock