diff --git a/CHANGELOG.md b/CHANGELOG.md index c29bce7dc..425e85305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - treat "NO" IMAP response to MOVE and COPY commands as an error #3058 - Fix a bug where messages in the Spam folder created contact requests #3015 - Fix a bug where drafts disappeared after some days #3067 +- Parse MS Exchange read receipts and mark the original message as read #3075 - do not retry message sending infinitely in case of permanent SMTP failure #3070 - set message state to failed when retry limit is exceeded #3072 diff --git a/src/mimeparser.rs b/src/mimeparser.rs index e39191890..c61d004e5 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -1203,6 +1203,9 @@ impl MimeMessage { if let Some(_disposition) = report_fields.get_header_value(HeaderDef::Disposition) { let original_message_id = report_fields .get_header_value(HeaderDef::OriginalMessageId) + // MS Exchange doesn't add an Original-Message-Id header. Instead, they put + // the original message id into the In-Reply-To header: + .or_else(|| report.headers.get_header_value(HeaderDef::InReplyTo)) .and_then(|v| parse_message_id(&v).ok()); let additional_message_ids = report_fields .get_header_value(HeaderDef::AdditionalMessageIds) @@ -1480,8 +1483,8 @@ async fn update_gossip_peerstates( pub(crate) struct Report { /// Original-Message-ID header /// - /// It MUST be present if the original message has a Message-ID according to RFC 8098, but MS - /// Exchange does not add it nevertheless, in which case it is `None`. + /// It MUST be present if the original message has a Message-ID according to RFC 8098. + /// In case we can't find it (shouldn't happen), this is None. original_message_id: Option, /// Additional-Message-IDs additional_message_ids: Vec, @@ -3183,10 +3186,32 @@ Message. #[async_std::test] async fn test_ms_exchange_mdn() -> Result<()> { let t = TestContext::new_alice().await; - let raw = + t.set_config(Config::ShowEmails, Some("2")).await?; + + let original = + include_bytes!("../test-data/message/ms_exchange_report_original_message.eml"); + dc_receive_imf(&t, original, "INBOX", false).await?; + let original_msg_id = t.get_last_msg().await.id; + + // 1. Test mimeparser directly + let mdn = include_bytes!("../test-data/message/ms_exchange_report_disposition_notification.eml"); - let mimeparser = MimeMessage::from_bytes(&t.ctx, raw).await?; - assert!(!mimeparser.mdn_reports.is_empty()); + let mimeparser = MimeMessage::from_bytes(&t.ctx, mdn).await?; + assert_eq!(mimeparser.mdn_reports.len(), 1); + assert_eq!( + mimeparser.mdn_reports[0].original_message_id.as_deref(), + Some("d5904dc344eeb5deaf9bb44603f0c716@posteo.de") + ); + assert!(mimeparser.mdn_reports[0].additional_message_ids.is_empty()); + + // 2. Test that marking the original msg as read works + dc_receive_imf(&t, mdn, "INBOX", false).await?; + + assert_eq!( + original_msg_id.get_state(&t).await?, + MessageState::OutMdnRcvd + ); + Ok(()) } } diff --git a/test-data/message/ms_exchange_report_disposition_notification.eml b/test-data/message/ms_exchange_report_disposition_notification.eml index cb4f4e4e0..4a039ddc1 100644 --- a/test-data/message/ms_exchange_report_disposition_notification.eml +++ b/test-data/message/ms_exchange_report_disposition_notification.eml @@ -1,43 +1,43 @@ -Return-Path: +Return-Path: Delivered-To: anonymous@posteo.de Received: from proxy02.posteo.name ([127.0.0.1]) - by dovecot16.posteo.name (Dovecot) with LMTP id Cp2uFxP1sWHbCQEAchYRkQ - for ; Thu, 09 Dec 2021 13:25:38 +0100 + by dovecot16.posteo.name (Dovecot) with LMTP id GaxcARout2HxiwMAchYRkQ + for ; Mon, 13 Dec 2021 12:35:32 +0100 Received: from proxy02.posteo.de ([127.0.0.1]) - by proxy02.posteo.name (Dovecot) with LMTP id MWsaCwrvsWG0wgEAGFAyLg - ; Thu, 09 Dec 2021 13:25:38 +0100 -Received: from mailin06.posteo.de (unknown [10.0.1.6]) - by proxy02.posteo.de (Postfix) with ESMTPS id 4J8tXy0KkMz120l - for ; Thu, 9 Dec 2021 13:25:38 +0100 (CET) -Received: from mx04.posteo.de (mailin06.posteo.de [127.0.0.1]) - by mailin06.posteo.de (Postfix) with ESMTPS id F24DE215B8 - for ; Thu, 9 Dec 2021 13:25:37 +0100 (CET) + by proxy02.posteo.name (Dovecot) with LMTP id q/LiCqwqt2FMTQEAGFAyLg + ; Mon, 13 Dec 2021 12:35:32 +0100 +Received: from mailin05.posteo.de (unknown [10.0.1.5]) + by proxy02.posteo.de (Postfix) with ESMTPS id 4JCKFJ1LCLz1214 + for ; Mon, 13 Dec 2021 12:35:32 +0100 (CET) +Received: from mx03.posteo.de (mailin05.posteo.de [127.0.0.1]) + by mailin05.posteo.de (Postfix) with ESMTPS id 1B26420012 + for ; Mon, 13 Dec 2021 12:35:32 +0100 (CET) X-Virus-Scanned: amavisd-new at posteo.de X-Spam-Flag: NO X-Spam-Score: 0.011 X-Spam-Level: X-Spam-Status: No, score=0.011 tagged_above=-1000 required=7 tests=[HTML_MESSAGE=0.001, T_POSTEO_TLSINY=0.01] autolearn=disabled -X-Posteo-Antispam-Signature: v=1; e=base64; a=aes-256-gcm; d=27yedFdXeAzOobR4x685XJ/5e6WQmX8PP5pSnOlGU2a9Ismhk38wb5AS44xh1yeL5PUxla78UEsHwGkPR0IyPRlHWaLMFLd5CJZN3GzFfrj/2CuB+cd1hOLpp9hRmCebc3rchuDr +X-Posteo-Antispam-Signature: v=1; e=base64; a=aes-256-gcm; d=RzB41PpqvrD+cuxf3UAqQLiXQL4MHazHZcKeOYJw75deIl7zxtrLXqfAZCeq2IPKt/njRRONUbfuvNdvLxg4mBJ0Rnb53wFOKOqtEpTzxYoQff3yqBpGSohr0DBG26PyBHi7ba/7 Authentication-Results: posteo.de; dmarc=none (p=none dis=none) header.from=example.org X-Posteo-TLS-Received-Status: TLSv1.2 Received: from mail.example.org (mail.example.org [0.0.0.0]) - by mx04.posteo.de (Postfix) with ESMTPS id 4J8tXx38vRz10yw - for ; Thu, 9 Dec 2021 13:25:37 +0100 (CET) -Received: from [192.168.1.11] (port=22105 helo=mail.example.org) + by mx03.posteo.de (Postfix) with ESMTPS id 4JCKFH2ZM7zyx0 + for ; Mon, 13 Dec 2021 12:35:31 +0100 (CET) +Received: from [192.168.1.11] (port=27040 helo=mail.example.org) by mail.example.org with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (Exim 4.94.2) - (envelope-from ) - id 1mvIUG-0007VC-2U - for anonymous@posteo.at; Thu, 09 Dec 2021 13:25:24 +0100 -From: Anonymous -To: Anonymous + (envelope-from ) + id 1mwjc6-0003hM-2K + for alice@example.org; Mon, 13 Dec 2021 12:35:26 +0100 +From: Anonymous_2 +To: Anonymous_1 Subject: Gelesen: Test message Thread-Topic: Test message -Thread-Index: AQHX7Dt/+5f88Aokk0KrqG0hbF8dN6wqFvxh -Date: Thu, 9 Dec 2021 12:25:24 +0000 -Message-ID: <1711fc3548cd4b2699ccd4fffac17713@anonymous> -In-Reply-To: <75dd051097b02468183707ad0dd62ebd@posteo.de> +Thread-Index: AQHX8BVZ9B3+kB6CNUCtJ9eQIONSNawwSqpi +Date: Mon, 13 Dec 2021 11:35:26 +0000 +Message-ID: <59b1d0c94a8d4834b7ab779a76647d44@mail.example.org> +In-Reply-To: Accept-Language: de-AT, de-DE, en-US Content-Language: de-DE X-MS-Has-Attach: @@ -45,29 +45,29 @@ X-MS-TNEF-Correlator: x-ms-exchange-transport-fromentityheader: Hosted x-originating-ip: [192.168.120.215] Content-Type: multipart/report; - boundary="_000_1711fc3548cd4b2699ccd4fffac17713anonymous_"; + boundary="_000_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_"; report-type=disposition-notification MIME-Version: 1.0 ---_000_1711fc3548cd4b2699ccd4fffac17713anonymous_ +--_000_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_ Content-Type: multipart/alternative; - boundary="_002_1711fc3548cd4b2699ccd4fffac17713anonymous_" + boundary="_002_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_" ---_002_1711fc3548cd4b2699ccd4fffac17713anonymous_ +--_002_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Ihre Nachricht - An: Anonymous + An: Anonymous_2 Betreff: Test message - Gesendet: Mittwoch, 8. Dezember 2021 14:57:05 (UTC+01:00) Amsterdam, Ber= -lin, Bern, Rom, Stockholm, Wien + Gesendet: Montag, 13. Dezember 2021 12:33:58 (UTC+01:00) Amsterdam, Berl= +in, Bern, Rom, Stockholm, Wien - wurde am Donnerstag, 9. Dezember 2021 13:24:34 (UTC+01:00) Amsterdam, Berl= -in, Bern, Rom, Stockholm, Wien gelesen. + wurde am Montag, 13. Dezember 2021 12:34:40 (UTC+01:00) Amsterdam, Berlin,= + Bern, Rom, Stockholm, Wien gelesen. ---_002_1711fc3548cd4b2699ccd4fffac17713anonymous_ +--_002_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable @@ -83,26 +83,26 @@ ding-left: 4pt; border-left: #800000 2px solid; } -->
Ihre Nachricht

-   An: Anonymous
+   An: Anonymous_2
   Betreff: Test message
-   Gesendet: Mittwoch, 8. Dezember 2021 14:57:05 (UTC+01:00) = -Amsterdam, Berlin, Bern, Rom, Stockholm, Wien
+   Gesendet: Montag, 13. Dezember 2021 12:33:58 (UTC+01:00) A= +msterdam, Berlin, Bern, Rom, Stockholm, Wien

- wurde am Donnerstag, 9. Dezember 2021 13:24:34 (UTC+01:00) Amster= -dam, Berlin, Bern, Rom, Stockholm, Wien gelesen.
+ wurde am Montag, 13. Dezember 2021 12:34:40 (UTC+01:00) Amsterdam= +, Berlin, Bern, Rom, Stockholm, Wien gelesen.
---_002_1711fc3548cd4b2699ccd4fffac17713anonymous_-- +--_002_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_-- ---_000_1711fc3548cd4b2699ccd4fffac17713anonymous_ +--_000_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_ Content-Type: message/disposition-notification -Final-recipient: RFC822; anonymous@example.org +Final-recipient: RFC822; bob@example.net Disposition: automatic-action/MDN-sent-automatically; displayed -X-MSExch-Correlation-Key: coNC5vaCQkiAOjek1v1Uew== -X-Display-Name: Anonymous +X-MSExch-Correlation-Key: nf7/jgN6Qk+WzsrkY5s9WA== +X-Display-Name: Anonymous_2 ---_000_1711fc3548cd4b2699ccd4fffac17713anonymous_-- +--_000_59b1d0c94a8d4834b7ab779a76647d44mailexampleorg_-- diff --git a/test-data/message/ms_exchange_report_original_message.eml b/test-data/message/ms_exchange_report_original_message.eml new file mode 100644 index 000000000..891b5329f --- /dev/null +++ b/test-data/message/ms_exchange_report_original_message.eml @@ -0,0 +1,34 @@ +Received: We have to put a Received header here. Otherwise, the message would be ignored + because DC thinks it's a draft, and the test fails. + Alternatively, we could configure the Sentobox folder in the test. +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="=_3293d145f71bf71c4bb97415536759d6" +Date: Mon, 13 Dec 2021 12:33:58 +0100 +From: Anonymous_1 +To: Anonymous_2 +Subject: Test message +Return-Receipt-To: Anonymous_1 +Disposition-Notification-To: Anonymous_1 +Message-ID: +X-Sender: alice@example.org +User-Agent: Posteo Webmail + +--=_3293d145f71bf71c4bb97415536759d6 +Content-Transfer-Encoding: 7bit +Content-Type: text/plain; charset=US-ASCII + + This is a test! + +Best regards +--=_3293d145f71bf71c4bb97415536759d6 +Content-Transfer-Encoding: quoted-printable +Content-Type: text/html; charset=UTF-8 + + + +This is a test!

Best regards + + +--=_3293d145f71bf71c4bb97415536759d6--