Parse additional message IDs in MDNs

This commit is contained in:
Alexander Krotov
2020-01-18 00:24:38 +03:00
parent 93800fd834
commit 493bf5ed08
2 changed files with 78 additions and 8 deletions

View File

@@ -10,6 +10,10 @@ pub enum HeaderDef {
Cc, Cc,
Disposition, Disposition,
OriginalMessageId, OriginalMessageId,
/// Delta Chat extension for message IDs in combined MDNs
XAdditionalMessageIds,
ListId, ListId,
References, References,
InReplyTo, InReplyTo,

View File

@@ -742,8 +742,17 @@ impl<'a> MimeMessage<'a> {
.flatten() .flatten()
.and_then(|v| parse_message_id(&v)) .and_then(|v| parse_message_id(&v))
{ {
let additional_message_ids = report_fields
.get_first_value(&HeaderDef::XAdditionalMessageIds.get_headername())
.ok()
.flatten()
.map_or_else(Vec::new, |v| {
v.split(' ').filter_map(parse_message_id).collect()
});
return Ok(Some(Report { return Ok(Some(Report {
original_message_id, original_message_id,
additional_message_ids,
})); }));
} }
} }
@@ -770,16 +779,20 @@ impl<'a> MimeMessage<'a> {
let mut mdn_recognized = false; let mut mdn_recognized = false;
for report in &self.reports { for report in &self.reports {
for original_message_id in
std::iter::once(&report.original_message_id).chain(&report.additional_message_ids)
{
if let Some((chat_id, msg_id)) = message::mdn_from_ext( if let Some((chat_id, msg_id)) = message::mdn_from_ext(
self.context, self.context,
from_id, from_id,
&report.original_message_id, original_message_id,
sent_timestamp, sent_timestamp,
) { ) {
self.context.call_cb(Event::MsgRead { chat_id, msg_id }); self.context.call_cb(Event::MsgRead { chat_id, msg_id });
mdn_recognized = true; mdn_recognized = true;
} }
} }
}
if self.has_chat_version() || mdn_recognized { if self.has_chat_version() || mdn_recognized {
let mut param = Params::new(); let mut param = Params::new();
@@ -853,7 +866,10 @@ fn update_gossip_peerstates(
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct Report { pub(crate) struct Report {
/// Original-Message-ID header
original_message_id: String, original_message_id: String,
/// X-Additional-Message-IDs
additional_message_ids: Vec<String>,
} }
fn parse_message_id(field: &str) -> Option<String> { fn parse_message_id(field: &str) -> Option<String> {
@@ -1384,4 +1400,54 @@ Disposition: manual-action/MDN-sent-automatically; displayed\n\
assert_eq!(message.parts.len(), 0); assert_eq!(message.parts.len(), 0);
assert_eq!(message.reports.len(), 2); assert_eq!(message.reports.len(), 2);
} }
#[test]
fn test_parse_mdn_with_additional_message_ids() {
let context = dummy_context();
let raw = b"Subject: =?utf-8?q?Chat=3A_Message_opened?=\n\
Date: Mon, 10 Jan 2020 00:00:00 +0000\n\
Chat-Version: 1.0\n\
Message-ID: <bar@example.org>\n\
To: Alice <alice@example.org>\n\
From: Bob <bob@example.org>\n\
Content-Type: multipart/report; report-type=disposition-notification;\n\t\
boundary=\"kJBbU58X1xeWNHgBtTbMk80M5qnV4N\"\n\
\n\
\n\
--kJBbU58X1xeWNHgBtTbMk80M5qnV4N\n\
Content-Type: text/plain; charset=utf-8\n\
\n\
The \"Encrypted message\" message you sent was displayed on the screen of the recipient.\n\
\n\
This is no guarantee the content was read.\n\
\n\
\n\
--kJBbU58X1xeWNHgBtTbMk80M5qnV4N\n\
Content-Type: message/disposition-notification\n\
\n\
Reporting-UA: Delta Chat 1.0.0-beta.22\n\
Original-Recipient: rfc822;bob@example.org\n\
Final-Recipient: rfc822;bob@example.org\n\
Original-Message-ID: <foo@example.org>\n\
Disposition: manual-action/MDN-sent-automatically; displayed\n\
X-Additional-Message-IDs: <foo@example.com> <foo@example.net>\n\
\n\
\n\
--kJBbU58X1xeWNHgBtTbMk80M5qnV4N--\n\
";
let message = MimeMessage::from_bytes(&context.ctx, &raw[..]).unwrap();
assert_eq!(
message.get_subject(),
Some("Chat: Message opened".to_string())
);
assert_eq!(message.parts.len(), 0);
assert_eq!(message.reports.len(), 1);
assert_eq!(message.reports[0].original_message_id, "foo@example.org");
assert_eq!(
&message.reports[0].additional_message_ids,
&["foo@example.com", "foo@example.net"]
);
}
} }