From f02c17cae4ae34892d9bb4bb62744eb8027cbc6f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 4 Jun 2020 18:13:01 +0200 Subject: [PATCH 01/37] Parse standard ndns (e.g. Gmail) --- src/dc_receive_imf.rs | 48 +++++++ src/message.rs | 22 +++ src/mimeparser.rs | 62 ++++++-- test-data/message/gmail_ndn.eml | 242 ++++++++++++++++++++++++++++++++ 4 files changed, 365 insertions(+), 9 deletions(-) create mode 100644 test-data/message/gmail_ndn.eml diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 3620eac35..d401c7def 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2324,4 +2324,52 @@ mod tests { "Carl" ); } + + #[async_std::test] + async fn test_parse_ndn() { + let t = dummy_context().await; + t.ctx + .set_config(Config::Addr, Some("alice@example.org")) + .await + .unwrap(); + t.ctx + .set_config(Config::ConfiguredAddr, Some("alice@example.org")) + .await + .unwrap(); + t.ctx + .set_config(Config::Configured, Some("1")) + .await + .unwrap(); + + dc_receive_imf( + &t.ctx, + b"From: alice@example.org\n\ + To: assidhfaaspocwaeofi@gmail.com\n\ + Subject: foo\n\ + Message-ID: \n\ + Chat-Version: 1.0\n\ + Chat-Disposition-Notification-To: alice@example.org\n\ + Date: Sun, 22 Mar 2020 22:37:57 +0000\n\ + \n\ + hello\n", + "INBOX", + 1, + false, + ) + .await + .unwrap(); + + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + let msg_id = chats.get_msg_id(0).unwrap(); + + let raw = include_bytes!("../test-data/message/gmail_ndn.eml"); + dc_receive_imf(&t.ctx, raw, "INBOX", 1, false) + .await + .unwrap(); + + assert_eq!( + Message::load_from_db(&t.ctx, msg_id).await.unwrap().state, + MessageState::OutFailed + ); + } } diff --git a/src/message.rs b/src/message.rs index 1c77b4017..2c539695f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1384,6 +1384,28 @@ pub async fn mdn_from_ext( None } +pub async fn ndn_from_ext( + context: &Context, + from_id: u32, + rfc724_mid: &str, + error: impl AsRef, +) { + if from_id <= DC_MSG_ID_LAST_SPECIAL || rfc724_mid.is_empty() { + return; + } + + match rfc724_mid_exists(context, rfc724_mid).await { + Ok(Some((_, _, msg_id))) => { + set_msg_failed(context, msg_id, Some(error)).await; + } + Ok(None) => info!( + context, + "Failed to select NDN, could not find failed msg {}", rfc724_mid + ), + Err(e) => info!(context, "Failed to select NDN {:?}", e), + } +} + /// The number of messages assigned to real chat (!=deaddrop, !=trash) pub async fn get_real_msg_cnt(context: &Context) -> i32 { match context diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 17883e137..b5e0bcaf5 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -54,6 +54,7 @@ pub struct MimeMessage { pub(crate) user_avatar: Option, pub(crate) group_avatar: Option, pub(crate) reports: Vec, + pub(crate) failed_msg: Option, } #[derive(Debug, PartialEq)] @@ -182,6 +183,7 @@ impl MimeMessage { message_kml: None, user_avatar: None, group_avatar: None, + failed_msg: None, }; parser.parse_mime_recursive(context, &mail).await?; parser.parse_headers(context)?; @@ -550,8 +552,8 @@ impl MimeMessage { (mime::MULTIPART, "report") => { /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { - if let Some(report_type) = mail.ctype.params.get("report-type") { - if report_type == "disposition-notification" { + match mail.ctype.params.get("report-type").map(|s| s as &str) { + Some("disposition-notification") => { if let Some(report) = self.process_report(context, mail)? { self.reports.push(report); } @@ -565,13 +567,24 @@ impl MimeMessage { self.parts.push(part); any_part_added = true; - } else { - /* eg. `report-type=delivery-status`; - maybe we should show them as a little error icon */ + } + Some("delivery-status") => { + if let Some(report) = self.process_delivery_status(context, mail)? { + self.failed_msg = Some(report); + } + + let mut part = Part::default(); + part.typ = Viewtype::Unknown; + self.parts.push(part); + + any_part_added = true; + } + Some(_) => { if let Some(first) = mail.subparts.iter().next() { any_part_added = self.parse_mime_recursive(context, first).await?; } } + None => {} } } } @@ -842,10 +855,6 @@ impl MimeMessage { /// Handle reports (only MDNs for now) pub async fn handle_reports(&self, context: &Context, from_id: u32, sent_timestamp: i64) { - if self.reports.is_empty() { - return; - } - for report in &self.reports { for original_message_id in std::iter::once(&report.original_message_id).chain(&report.additional_message_ids) @@ -858,6 +867,41 @@ impl MimeMessage { } } } + + if let Some(original_message_id) = &self.failed_msg { + message::ndn_from_ext(context, from_id, original_message_id, "TODO error message").await + } + } + + fn process_delivery_status( + &self, + context: &Context, + report: &mailparse::ParsedMail<'_>, + ) -> Result> { + // parse as mailheaders + if let Some(original_msg) = report + .subparts + .iter() + .find(|p| p.ctype.mimetype == "message/rfc822") + { + let report_body = original_msg.get_body_raw()?; + let (report_fields, _) = mailparse::parse_headers(&report_body)?; + + if let Some(original_message_id) = report_fields + .get_header_value(HeaderDef::MessageId) + .and_then(|v| parse_message_id(&v).ok()) + { + return Ok(Some(original_message_id)); + } + + warn!( + context, + "ignoring unknown ndn-notification, Message-Id: {:?}", + report_fields.get_header_value(HeaderDef::MessageId) + ); + } + + Ok(None) } } diff --git a/test-data/message/gmail_ndn.eml b/test-data/message/gmail_ndn.eml new file mode 100644 index 000000000..f73ff115a --- /dev/null +++ b/test-data/message/gmail_ndn.eml @@ -0,0 +1,242 @@ +Delivered-To: alice@gmail.com +Received: by 2002:a1c:b4d7:0:0:0:0:0 with SMTP id d206csp3026053wmf; + Mon, 18 May 2020 09:23:25 -0700 (PDT) +X-Received: by 2002:a5d:4651:: with SMTP id j17mr19532177wrs.50.1589819005555; + Mon, 18 May 2020 09:23:25 -0700 (PDT) +ARC-Seal: i=1; a=rsa-sha256; t=1589819005; cv=none; + d=google.com; s=arc-20160816; + b=IZbNnzzuYzTFuqfuZwpd3ehqpYYGpn31c8DsfGbQ8rpbS0OTTROkVYvihQl8Ne/8X/ + brEWsrcmaCh9WpFMzpI+cp/TY39uusnI6qdp5rcgrFmFgoANtwf3TBBj1+f7wBPn46BP + dQOUsg/J8KVfvzVgvL1x4uyJ0m9QirDgJeJ/BvrswbTleRQK7oY3fIireUCDxj6r2lCB + 1Z0TKw1mgIb1LiFMZz8kvCNn3R4KSFnwS8rIju0hYwnsioNiExVQgumXL+RVkEZ9BMzf + UdoWIAw3VW+MOZFTpfLCEfgIPtLg/gtE0Q1P+a3KKpi8dkPiV2n6DGMecy9lTLtdhCXt + pnaA== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=in-reply-to:references:subject:from:date:message-id:auto-submitted + :to:dkim-signature; + bh=5xjZvcHbEGbMY0K2QB+3U6tpm1L1LAVv5h1pd4YXDEE=; + b=nNP0DktrSjdBaFfhhoDi2O9KVKM0iXE5ZgubQ0q0ff68Z6Ke7c8dDBXEsZoToI0s4Y + w90KyJFpgMJLFmP3iVDRqCfohi2y1HGdWg5VXQPTvzM7+YozZRlbNNV9UsuyRY91CXrJ + a2XREBgB+LPMGQivwcHtUMZfyNv/4uiwWivk+92ySNDhxqOiDt4R5Jak/7RkZMFwQpsE + JGwk6asM6VqZlihkF24lKv3pPaob6feyX3wD5N0+Mqiy1kQTj2JkpQk6nkTmdf0gapZe + fOhU1NkbNfbuS3U7m2gEUiyktE+MhV/MgAzgBhm9bgNt2gQLVWju8rHkPndfv1PDmEkC + FsYQ== +ARC-Authentication-Results: i=1; mx.google.com; + dkim=pass header.i=@googlemail.com header.s=20161025 header.b=dPisws+O; + spf=pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) smtp.helo=mail-sor-f69.google.com; + dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com +Return-Path: <> +Received: from mail-sor-f69.google.com (mail-sor-f69.google.com. [209.85.220.69]) + by mx.google.com with SMTPS id s18sor5584435wrb.25.2020.05.18.09.23.25 + for + (Google Transport Security); + Mon, 18 May 2020 09:23:25 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) client-ip=209.85.220.69; +Authentication-Results: mx.google.com; + dkim=pass header.i=@googlemail.com header.s=20161025 header.b=dPisws+O; + spf=pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) smtp.helo=mail-sor-f69.google.com; + dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=googlemail.com; s=20161025; + h=to:auto-submitted:message-id:date:from:subject:references + :in-reply-to; + bh=5xjZvcHbEGbMY0K2QB+3U6tpm1L1LAVv5h1pd4YXDEE=; + b=dPisws+OwGFyOy0a612XYZgvz5T71GcJRJtU068/Tce8vN/+ggIQtUsZnZtsphe71v + 2NvfP9ULxR4cXvomTvhrYAk19KdxN/S7SeyBbmXv3x/tg+DBVCmmPS/6RXrcl6Ms3Hkw + uPFQ9S3KcvHe/2bcb5LSTA/stIP4tuxxAXvsX2j+MjPYPWKAl50jkSbWK98U0Q0U+MTl + pKaaC9s9iEBafac8BFZCy4DfpumKlemNEyRa3cSV2hw+DYHKA5peModrK1A2tcsfstFF + rZi8yF/D90RIFbE04DI2QCxB3trsChNF1aYF06aSzI//wsfM1+lb+uGPi0YVkw3n4HrX + Xw4w== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:to:auto-submitted:message-id:date:from:subject + :references:in-reply-to; + bh=5xjZvcHbEGbMY0K2QB+3U6tpm1L1LAVv5h1pd4YXDEE=; + b=A/NCOtgbpA7VzB1G7ZFo8TA2FfrjuqjGdwMrJr3yXe21FrBFwzssprJwOkynqoVLkK + iJU7uMF/KTcQPDEmOLFThzFfe5GCx7eJtZPhwY+FbBlC5sq4I55/xaQLd0gOZ1BYXwMn + 2bk169d2aoukbaLbGSQZF3d9atd+/e48YzkRxpmUoLcrWk2LcHAeQIG7SgT9pfX5DKPr + VpxM5/GMVEBbTRhBIWCeVSfpYCs80l0xEeTC3/B5lzpzMVDE8QCW6Dwh75b4Tb2K6yru + Zsy5ZpRmwv0wrkrb2vM+pl4IMkaF7s8XosIvlIT++fQV5xDFItT4atpykZvSDB92RKV0 + 8lEA== +X-Gm-Message-State: AOAM532RG/PT3ChZHBCDORGLtAjKvX8TGBuOy+AxrnEaJT6v1ieb+VV1 + +ejly+/6UthxHYlkOJYAszCSgL4dKVFotoVaN7LhEA== +X-Google-Smtp-Source: ABdhPJz6veVKWhomCL4gK+whrybuMzHCDCq8AowgQvi7sobpMoM/k9CDw79jo1j3OUcTz6MEeUYLxEXuNIuu4zyoS7kVtsUYryGFHAI= +X-Received: by 2002:a5d:5183:: with SMTP id k3mr20545185wrv.159.1589819005394; + Mon, 18 May 2020 09:23:25 -0700 (PDT) +Content-Type: multipart/report; boundary="00000000000012d63005a5ee9520"; report-type=delivery-status +To: alice@gmail.com +Received: by 2002:a5d:5183:: with SMTP id k3mr13704211wrv.159; Mon, 18 May + 2020 09:23:25 -0700 (PDT) +Return-Path: <> +Auto-Submitted: auto-replied +Message-ID: <5ec2b67d.1c69fb81.213af.67a5.GMR@mx.google.com> +Date: Mon, 18 May 2020 09:23:25 -0700 (PDT) +From: Mail Delivery Subsystem +Subject: Delivery Status Notification (Failure) +References: +In-Reply-To: +X-Failed-Recipients: assidhfaaspocwaeofi@gmail.com + +--00000000000012d63005a5ee9520 +Content-Type: multipart/related; boundary="00000000000012dc0005a5ee952f" + +--00000000000012dc0005a5ee952f +Content-Type: multipart/alternative; boundary="00000000000012dc0705a5ee9530" + +--00000000000012dc0705a5ee9530 +Content-Type: text/plain; charset="UTF-8" + + +** Die Adresse wurde nicht gefunden ** + +Ihre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann. + +Hier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser + +Antwort: + +550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp + +--00000000000012dc0705a5ee9530 +Content-Type: text/html; charset="UTF-8" + + + + + + + + + + + + + + + + +--00000000000012dc0705a5ee9530-- +--00000000000012dc0005a5ee952f +Content-Type: image/png; name="icon.png" +Content-Disposition: attachment; filename="icon.png" +Content-Transfer-Encoding: base64 +Content-ID: + +iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAACXBIWXMAABYlAAAWJQFJUiTwAAAA +GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABTdJREFUeNrsnD9sFEcUh5+PRMqZ +yA0SPhAUQAQFUkyTgiBASARo6QApqVIkfdxGFJFSgGhJAUIiBaQB0ZIOKVCkwUgURjIg2fxL4kS+ +YDvkbC/388bi8N16Z4/d7J/5PsniuD3fyePP772ZeTsDQRAYQL/UGAJAIEAgQCBAIAAEAgQCBAIE +AkAgyJT3Mv+Eq7vYK8mTE+MDRCAghQECAeRQA5V2ZOpmg5vDx3NPzRbmGRMEcmTrEbNNB8zWfRD+ +f/Efs2e3zCZvMjaksBg27TfbcuSNPEKP9ZyuAQKtHX2O9ncNgWC57umMPKvRNb0GEKgnLoUyxTQC +rcns0/6uIRAs8/hGf9cQCJZpTpjdO2f25/03z+mxntM1eLtsZAgiUtX4JcaBCAQIBAgECARQ8CJa +G5jab4J4pm4WZmO3OALVh802fIwcLkyPkcKAGggAgQCBAIEAgQCBABAIEAjKA/1AnahhbO5FdOOY +VsrrDbPBYcYKgf5D2wLaV3p+22xh1u17tO3S+DTcvxvagUDeivPgx/a/95J/73w7Sj26Hn4pKo2M +ehuV/KyBJM6d0f7k6RKx/R63vvL2tmf/ItDdM2ZTP6f7nkp9Y2fDx1v9akmpIU+KSCLVUghUQfSL +zVKeTklbLxGoctw/nzC5rw8L5KRNbkpnKq6pgSqEClzNnFzY+XnYWrt6VpVk1vbwWvg+RKCKMOUw +Q1LEOXA+/MX3mpJvGDHb265xtnzmFoUK1HaKQGlMtePYM+q2KKjXuaS1NJYIEKgI8jhEgqHt4cqy +Ky53j3hyHz2bqSLp2o2LbJ7MxKovkGqXteoWpaOk96O9/yF/dF7NwlS36AuIQIBA5celQK4PIxBE +4LLzrtoLgaALdSy6CJRkWQCBPGLsTHznomZ9nszUECgJ2ml3WWHe+QVFNPSQx6UdZNtxr9pbEShN +eTTz8mQXHoHSlke7+Z+c9m6VGoHSkEfs/trLW3wQKApN1V3lGfnGu2Z6BFoLtYCs3GWBPAiUCLVh +/HoaeRCoT9R873KLM/IgUBfapnCpe5AHgXry4pf412ihEHkQqCdxd5VqrcezhUIESsJMTJ+Pdthp +Z0WgyNlXXPHc2Mc4IVAELl2Gnh8mhUDvCkfbIVAkcbf/aOoO3fMKhqAD3frTa4quwpn0hUDOkQhI +YYBAgECAQAAU0QlYObl+5Ug8NcprZkZxjUCxRPVA6zmtEXHCBykskrhjgHXN09PoEcgFl4M4H11j +nBAoApcj6ZoPGScEAgTKApcDoTw5sgWB+sGlz1n90IBAPdE6j1o21PfcC11jLagL1oFWRyGlKU3p +OxcSJQ7NZAjkhHp/uG2HFAYIBAgECASAQIBAgECAQAAIBOkxEARBtp9wdVfAMOfIifEBIhCQwgCB +ABAI0oV2jhxZ+nfBatuPZfgBCy0Eqqo8c01b+uu51XZvzOgDWoHNTGR+pCwpLEd5svuAZXlO2uEr +PyEQ8hRWHgRCHmqg0sjTnLalv6crJQ8C/U8stqNO0I4+VZOHFIY8COS1PGL2ybd5yUMKK7s8zYmL +dujyd3n+nESgcsvzZd4/KwIhDwIhT35QA6UyE1qyxZnfvJMHgdKS549JC1qvvJOHFIY8CFR5eV5O +XimqPAhUdHnmfx+zgxdOFXkoqIGKKs/cswnb/8Oeog8HEai48nxUhiFBIORBIOShBioskkbySCLk +IQIhDwIhj28p7FApR6b1qlEbHGpkO/rr6215vi/zH1r2x7tApSGFAQIBAgECAQIBIBAgECAQIBBA +LK8FGADCTxYrr+EVJgAAAABJRU5ErkJggg== +--00000000000012dc0005a5ee952f-- +--00000000000012d63005a5ee9520 +Content-Type: message/delivery-status + +Reporting-MTA: dns; googlemail.com +Arrival-Date: Mon, 18 May 2020 09:23:25 -0700 (PDT) +X-Original-Message-ID: + +Final-Recipient: rfc822; assidhfaaspocwaeofi@gmail.com +Action: failed +Status: 5.1.1 +Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does not exist. Please try + 550-5.1.1 double-checking the recipient's email address for typos or + 550-5.1.1 unnecessary spaces. Learn more at + 550 5.1.1 https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp +Last-Attempt-Date: Mon, 18 May 2020 09:23:25 -0700 (PDT) + +--00000000000012d63005a5ee9520 +Content-Type: message/rfc822 + +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20161025; + h=mime-version:from:date:message-id:subject:to; + bh=gtlm3j0shCgZYOVxUt74zkQ69Zq+GTQeHeXLfMlrhlk=; + b=a185ogBcMzF9whNVWvuyUoUunNZk3Vc1kEIFmPkX0IxLpAFcI+fOQajOSromGl7Oyi + yecLwQevpww2Xd0XjZ3UkZvrI9m9koRmh0QeoHvgTRORiVwj08+PVc3N4F9bCO4w9i0J + ir7SSsJqBCDovoIFSFDyNa64vs6Nxno0cH/DaPG7pVTdD+3jfB7nLXIsMQYeX+1eP6rB + UhKxH82r7Mh9CI2PWDQpVtGj63AMUEyHgE9Ou08PWbbKjrQOasoG3Tw8tB1GoN1XYssM + rxOTgWEoTiduZ35AUH6h+eChOn9OHuI3SPECcVob70Qndayia3dMKfHMO6sEx9J0Wpic + 29vg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:mime-version:from:date:message-id:subject:to; + bh=gtlm3j0shCgZYOVxUt74zkQ69Zq+GTQeHeXLfMlrhlk=; + b=miGIfL5BgnkD3wQvS34RtGwRRoh+8gJT5sFFfdX/hVyG/dvjXfdwP4yyNWr8ox8iY2 + BLlahS4y4VGcbG1e2aYjurnWNytGu6utQcZax/uUngJ0bTOwXW1VaIiEZtqd6gTV+8d/ + rrfQ459+4vXqIoQf0+Oi/U6dWwgJvPPjjRiToWdF3vIJE8R1iTRdZbW4lkgxSADbmskg + noT/gWGWblHtR6uuGuKGJ3bkhJKCBnjavKh0LlbWEeFBZfmVNPRvzEFWHjBDdu5wvSL5 + 0QJ+Qn0Orfn5CJuN3xPfzT1S2rI2iYZx37KX9zyMnZEx0ilkTYqCtBPWkrXRYDSXcxYS + Y1ag== +X-Gm-Message-State: AOAM531vhwpXiK8M12286dOJx0Q5fBl9ZaH6BJKts93GoxvPv0xdryP0 + jg9wYmoP5MUHudsxAMCYDFsCUMVx2PEywyIsaQqklw== +X-Google-Smtp-Source: ABdhPJxlVJtTODM3pZZSTbbpAAAQRU8XbmuosDF9fgQZmVwxGZSzRWl22o+moppVRU/r8xMAyf0r3+qXwEBe1vZfjZo= +X-Received: by 2002:a5d:5183:: with SMTP id k3mr20545162wrv.159.1589819005034; + Mon, 18 May 2020 09:23:25 -0700 (PDT) +MIME-Version: 1.0 +From: +Date: Mon, 18 May 2020 18:23:39 +0200 +Message-ID: +Subject: Kommt sowieso nicht an +To: assidhfaaspocwaeofi@gmail.com +Content-Type: multipart/alternative; boundary="0000000000000d652a05a5ee95df" + +--0000000000000d652a05a5ee95df +Content-Type: text/plain; charset="UTF-8" + +Wollte nur was testen + +--0000000000000d652a05a5ee95df +Content-Type: text/html; charset="UTF-8" + +
Wollte nur was testen
+ +--0000000000000d652a05a5ee95df-- + +--00000000000012d63005a5ee9520-- From 3757e5dca16f9c258691416d4d694bbc08e6576d Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 5 Jun 2020 23:00:01 +0200 Subject: [PATCH 02/37] Try to add decent error msg (doesnt work yet) --- src/dc_receive_imf.rs | 21 +++++++++++++---- src/message.rs | 53 +++++++++++++++++++++++++++++++++++-------- src/mimeparser.rs | 16 ++++++++++--- src/stock.rs | 3 +++ 4 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index d401c7def..d2628e9ab 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -238,7 +238,7 @@ pub async fn dc_receive_imf( cleanup(context, &create_event_to_send, created_db_entries); mime_parser - .handle_reports(context, from_id, sent_timestamp) + .handle_reports(context, from_id, sent_timestamp, &mime_parser.parts) .await; Ok(()) @@ -2367,9 +2367,22 @@ mod tests { .await .unwrap(); + let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); + assert_eq!(msg.state, MessageState::OutFailed); assert_eq!( - Message::load_from_db(&t.ctx, msg_id).await.unwrap().state, - MessageState::OutFailed - ); + msg.param.get(Param::Error), + Some( + r"** Die Adresse wurde nicht gefunden ** + +Ihre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann. + +Hier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser + +Antwort: + +550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp +" + ) + ) } } diff --git a/src/message.rs b/src/message.rs index 2c539695f..06d2234cc 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1388,21 +1388,56 @@ pub async fn ndn_from_ext( context: &Context, from_id: u32, rfc724_mid: &str, - error: impl AsRef, + error: Option>, ) { if from_id <= DC_MSG_ID_LAST_SPECIAL || rfc724_mid.is_empty() { return; } - match rfc724_mid_exists(context, rfc724_mid).await { - Ok(Some((_, _, msg_id))) => { - set_msg_failed(context, msg_id, Some(error)).await; + let res = context + .sql + .query_row( + concat!( + "SELECT", + " m.id AS msg_id,", + " c.id AS chat_id,", + " c.type AS type,", + " m.to_id AS to_id", + " FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id", + " WHERE rfc724_mid=? AND from_id=1", + ), + paramsv![rfc724_mid], + |row| { + Ok(( + row.get::<_, MsgId>("msg_id")?, + row.get::<_, ChatId>("chat_id")?, + row.get::<_, Chattype>("type")?, + row.get::<_, u32>("to_id")?, + )) + }, + ) + .await; + if let Err(ref err) = res { + info!(context, "Failed to select NDN {:?}", err); + } + + if let Ok((msg_id, chat_id, chat_type, contact_id)) = res { + set_msg_failed(context, msg_id, error).await; + + if chat_type == Chattype::Group || chat_type == Chattype::VerifiedGroup { + let contact = Contact::load_from_db(context, contact_id).await.unwrap(); + chat::add_info_msg( + context, + chat_id, + context + .stock_string_repl_str( + StockMessage::FailedSendingTo, + contact.get_display_name(), + ) + .await, + ) + .await; } - Ok(None) => info!( - context, - "Failed to select NDN, could not find failed msg {}", rfc724_mid - ), - Err(e) => info!(context, "Failed to select NDN {:?}", e), } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index b5e0bcaf5..41f4c844f 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -572,7 +572,6 @@ impl MimeMessage { if let Some(report) = self.process_delivery_status(context, mail)? { self.failed_msg = Some(report); } - let mut part = Part::default(); part.typ = Viewtype::Unknown; self.parts.push(part); @@ -854,7 +853,13 @@ impl MimeMessage { } /// Handle reports (only MDNs for now) - pub async fn handle_reports(&self, context: &Context, from_id: u32, sent_timestamp: i64) { + pub async fn handle_reports( + &self, + context: &Context, + from_id: u32, + sent_timestamp: i64, + parts: &Vec, + ) { for report in &self.reports { for original_message_id in std::iter::once(&report.original_message_id).chain(&report.additional_message_ids) @@ -869,7 +874,12 @@ impl MimeMessage { } if let Some(original_message_id) = &self.failed_msg { - message::ndn_from_ext(context, from_id, original_message_id, "TODO error message").await + let error = parts + .iter() + .find(|p| p.typ == Viewtype::Text) + .map(|p| &p.msg); + info!(context, "msg_failed {:?}", error); + message::ndn_from_ext(context, from_id, original_message_id, error).await } } diff --git a/src/stock.rs b/src/stock.rs index 33dfd70ba..a172d2dd1 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -182,6 +182,9 @@ pub enum StockMessage { #[strum(props(fallback = "Message from %1$s"))] SubjectForNewContact = 73, + + #[strum(props(fallback = "Failed to send message to %1$s. See 'info' for more details."))] + FailedSendingTo = 74, } /* From 8350729cbb62a8539e824f6e0d73e25e772d7da9 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 6 Jun 2020 12:58:47 +0200 Subject: [PATCH 03/37] Improve errors --- src/chat.rs | 4 ++-- src/dc_receive_imf.rs | 5 +++++ src/job.rs | 2 +- src/message.rs | 8 ++++---- src/mimeparser.rs | 12 +++++++----- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index c8fa0c411..48f22e44b 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -1464,7 +1464,7 @@ pub async fn send_msg( } } msg.param.remove(Param::PrepForwards); - msg.save_param_to_disk(context).await; + msg.update_param(context).await; } return send_msg_inner(context, chat_id, msg).await; } @@ -2596,7 +2596,7 @@ pub async fn forward_msgs( .set(Param::PrepForwards, new_msg_id.to_u32().to_string()); } - msg.save_param_to_disk(context).await; + msg.update_param(context).await; msg.param = save_param; } else { msg.state = MessageState::OutPending; diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index d2628e9ab..1675cb73b 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2327,6 +2327,8 @@ mod tests { #[async_std::test] async fn test_parse_ndn() { + use std::io::Write; + let t = dummy_context().await; t.ctx .set_config(Config::Addr, Some("alice@example.org")) @@ -2367,7 +2369,10 @@ mod tests { .await .unwrap(); + println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); + std::io::stdout().flush().unwrap(); + assert_eq!(msg.state, MessageState::OutFailed); assert_eq!( msg.param.get(Param::Error), diff --git a/src/job.rs b/src/job.rs index 6eb4997f1..a5501ceb8 100644 --- a/src/job.rs +++ b/src/job.rs @@ -806,7 +806,7 @@ pub async fn send_msg_job(context: &Context, msg_id: MsgId) -> Result 0 { self.param.set_int(Param::Duration, duration); } - self.save_param_to_disk(context).await; + self.update_param(context).await; } - pub async fn save_param_to_disk(&mut self, context: &Context) -> bool { + pub async fn update_param(&mut self, context: &Context) -> bool { context .sql .execute( @@ -1256,7 +1256,7 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option { if let Some(first) = mail.subparts.iter().next() { @@ -878,7 +881,6 @@ impl MimeMessage { .iter() .find(|p| p.typ == Viewtype::Text) .map(|p| &p.msg); - info!(context, "msg_failed {:?}", error); message::ndn_from_ext(context, from_id, original_message_id, error).await } } From f0837cfa737906a822fbb32c83d31feff849a290 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 6 Jun 2020 17:05:24 +0200 Subject: [PATCH 04/37] Repair errors saved for messages --- src/dc_receive_imf.rs | 19 ++++++------------- src/message.rs | 31 ++++++++++++++++++++----------- src/param.rs | 3 --- src/sql.rs | 10 ++++++++++ 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 1675cb73b..db096480a 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2328,6 +2328,7 @@ mod tests { #[async_std::test] async fn test_parse_ndn() { use std::io::Write; + use std::{thread, time}; let t = dummy_context().await; t.ctx @@ -2369,25 +2370,17 @@ mod tests { .await .unwrap(); + thread::sleep(time::Duration::from_millis(1000)); + println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); std::io::stdout().flush().unwrap(); + thread::sleep(time::Duration::from_millis(1000)); assert_eq!(msg.state, MessageState::OutFailed); assert_eq!( - msg.param.get(Param::Error), - Some( - r"** Die Adresse wurde nicht gefunden ** - -Ihre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann. - -Hier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser - -Antwort: - -550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp -" - ) + msg.error.as_ref().map(|s| s.as_str()), + Some("Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp") ) } } diff --git a/src/message.rs b/src/message.rs index c4a10075c..7d8bf2ecf 100644 --- a/src/message.rs +++ b/src/message.rs @@ -255,6 +255,7 @@ pub struct Message { pub(crate) starred: bool, pub(crate) chat_blocked: Blocked, pub(crate) location_id: u32, + pub(crate) error: Option, pub(crate) param: Params, } @@ -289,6 +290,7 @@ impl Message { " m.timestamp_rcvd AS timestamp_rcvd,", " m.type AS type,", " m.state AS state,", + " m.error AS error,", " m.msgrmsg AS msgrmsg,", " m.txt AS txt,", " m.param AS param,", @@ -316,6 +318,7 @@ impl Message { msg.timestamp_rcvd = row.get("timestamp_rcvd")?; msg.viewtype = row.get("type")?; msg.state = row.get("state")?; + msg.error = row.get("error")?; msg.is_dc_message = row.get("msgrmsg")?; let text; @@ -937,7 +940,7 @@ pub async fn get_msg_info(context: &Context, msg_id: MsgId) -> String { } ret += "\n"; - if let Some(err) = msg.param.get(Param::Error) { + if let Some(err) = &msg.error { ret += &format!("Error: {}", err) } @@ -1251,27 +1254,33 @@ pub async fn exists(context: &Context, msg_id: MsgId) -> bool { pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option>) { if let Ok(mut msg) = Message::load_from_db(context, msg_id).await { + let error = error.map(|e| e.as_ref().to_string()).unwrap_or_default(); if msg.state.can_fail() { msg.state = MessageState::OutFailed; - } - if let Some(error) = error { - msg.param.set(Param::Error, error.as_ref()); - warn!(context, "{} failed: {}", msg_id, error.as_ref()); + warn!(context, "{} failed: {}", msg_id, error); + } else { + warn!( + context, + "{} seems to have failed ({}), but state is {}", msg_id, error, msg.state + ) } - if context + match context .sql .execute( - "UPDATE msgs SET state=?, param=? WHERE id=?;", - paramsv![msg.state, msg.param.to_string(), msg_id], + "UPDATE msgs SET state=?, error=? WHERE id=?;", + paramsv![msg.state, error, msg_id], ) .await - .is_ok() { - context.emit_event(Event::MsgFailed { + Ok(_) => context.emit_event(Event::MsgFailed { chat_id: msg.chat_id, msg_id, - }); + }), + Err(e) => { + error!(context, "{:?}", e); + println!("{:?}", e) + } } } } diff --git a/src/param.rs b/src/param.rs index 7e2d8f08c..d5c79e8d8 100644 --- a/src/param.rs +++ b/src/param.rs @@ -65,9 +65,6 @@ pub enum Param { /// For Messages Arg4 = b'H', - /// For Messages - Error = b'L', - /// For Messages AttachGroupImage = b'A', diff --git a/src/sql.rs b/src/sql.rs index 3f3ee9a40..7e7346f10 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -779,6 +779,7 @@ async fn open( timestamp INTEGER DEFAULT 0, \ type INTEGER DEFAULT 0, \ state INTEGER DEFAULT 0, \ + error TEXT DEFAULT '', \ msgrmsg INTEGER DEFAULT 1, \ bytes INTEGER DEFAULT 0, \ txt TEXT DEFAULT '', \ @@ -1241,6 +1242,15 @@ async fn open( .await?; sql.set_raw_config_int(context, "dbversion", 63).await?; } + if dbversion < 64 { + info!(context, "[migration] v63"); + sql.execute( + "ALTER TABLE chats ADD COLUMN error TEXT DEFAULT '';", + paramsv![], + ) + .await?; + sql.set_raw_config_int(context, "dbversion", 64).await?; + } // (2) updates that require high-level objects // (the structure is complete now and all objects are usable) From 6ded0d3bc1c08a7d05032a890bb3b1ef60baa55a Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 6 Jun 2020 17:53:57 +0200 Subject: [PATCH 05/37] Do not show error messages in chat --- src/dc_receive_imf.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index db096480a..b644165b3 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -405,6 +405,17 @@ async fn add_parts( .await .unwrap_or_default(); + if chat_id.is_unset() { + // check if the message belongs to a mailing list + if mime_parser.failed_msg.is_some() { + *chat_id = ChatId::new(DC_CHAT_ID_TRASH); + info!( + context, + "Message belongs to an NDN list and is not shown in a chat.", + ); + } + } + // get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list, // it might also be blocked and displayed in the deaddrop as a result if chat_id.is_unset() { @@ -2327,7 +2338,6 @@ mod tests { #[async_std::test] async fn test_parse_ndn() { - use std::io::Write; use std::{thread, time}; let t = dummy_context().await; @@ -2374,8 +2384,6 @@ mod tests { println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); - std::io::stdout().flush().unwrap(); - thread::sleep(time::Duration::from_millis(1000)); assert_eq!(msg.state, MessageState::OutFailed); assert_eq!( From 6b763bf4178d08a26e8b562ad6441ef5e265aef5 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 6 Jun 2020 18:00:22 +0200 Subject: [PATCH 06/37] Return true for MessageState::OutMdnRcvd.can_fail() because it could be a group message and only some recipients failed --- src/message.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/message.rs b/src/message.rs index 7d8bf2ecf..31b31b7c7 100644 --- a/src/message.rs +++ b/src/message.rs @@ -766,9 +766,10 @@ impl From for LotState { impl MessageState { pub fn can_fail(self) -> bool { match self { - MessageState::OutPreparing | MessageState::OutPending | MessageState::OutDelivered => { - true - } + MessageState::OutPreparing + | MessageState::OutPending + | MessageState::OutDelivered + | MessageState::OutMdnRcvd => true, _ => false, } } @@ -1327,10 +1328,7 @@ pub async fn mdn_from_ext( if let Ok((msg_id, chat_id, chat_type, msg_state)) = res { let mut read_by_all = false; - // if already marked as MDNS_RCVD msgstate_can_fail() returns false. - // however, it is important, that ret_msg_id is set above as this - // will allow the caller eg. to move the message away - if msg_state.can_fail() { + if msg_state != MessageState::OutMdnRcvd && msg_state != MessageState::OutFailed { let mdn_already_in_table = context .sql .exists( From 016b96e30e8c25fa63eacfea8ca100656085aa4e Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sun, 7 Jun 2020 12:50:29 +0200 Subject: [PATCH 07/37] Fix migration --- src/sql.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sql.rs b/src/sql.rs index 7e7346f10..94e38cd91 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -1245,7 +1245,7 @@ async fn open( if dbversion < 64 { info!(context, "[migration] v63"); sql.execute( - "ALTER TABLE chats ADD COLUMN error TEXT DEFAULT '';", + "ALTER TABLE msgs ADD COLUMN error TEXT DEFAULT '';", paramsv![], ) .await?; From a30486112fe34ebcf736245c701e9dedeeab6782 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 14:30:54 +0200 Subject: [PATCH 08/37] Add test --- src/dc_receive_imf.rs | 77 +++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index b644165b3..eda689103 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2338,21 +2338,7 @@ mod tests { #[async_std::test] async fn test_parse_ndn() { - use std::{thread, time}; - - let t = dummy_context().await; - t.ctx - .set_config(Config::Addr, Some("alice@example.org")) - .await - .unwrap(); - t.ctx - .set_config(Config::ConfiguredAddr, Some("alice@example.org")) - .await - .unwrap(); - t.ctx - .set_config(Config::Configured, Some("1")) - .await - .unwrap(); + let t = configured_offline_context().await; dc_receive_imf( &t.ctx, @@ -2379,9 +2365,6 @@ mod tests { dc_receive_imf(&t.ctx, raw, "INBOX", 1, false) .await .unwrap(); - - thread::sleep(time::Duration::from_millis(1000)); - println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); @@ -2391,4 +2374,62 @@ mod tests { Some("Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp") ) } + + #[async_std::test] + async fn test_parse_ndn_group_msg() { + let t = configured_offline_context().await; + + dc_receive_imf( + &t.ctx, + b"From: alice@example.org\n\ + To: bob@example.org, assidhfaaspocwaeofi@gmail.com\n\ + Subject: foo\n\ + Message-ID: \n\ + Chat-Version: 1.0\n\ + Chat-Group-ID: abcde\n\ + Chat-Group-Name: foo\n\ + Chat-Disposition-Notification-To: alice@example.org\n\ + Date: Sun, 22 Mar 2020 22:37:57 +0000\n\ + \n\ + hello\n", + "INBOX", + 1, + false, + ) + .await + .unwrap(); + + let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); + let msg_id = chats.get_msg_id(0).unwrap(); + + let raw = include_bytes!("../test-data/message/gmail_ndn.eml"); + dc_receive_imf(&t.ctx, raw, "INBOX", 1, false) + .await + .unwrap(); + + println!("Loading msg {}…", msg_id); + let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); + + assert_eq!(msg.state, MessageState::OutFailed); + + let msgs = chat::get_chat_msgs(&t.ctx, msg.chat_id, 0, None).await; + let mut found = false; + for id in msgs.iter() { + let m = Message::load_from_db(&t.ctx, *id).await.unwrap(); + if m.from_id == DC_CONTACT_ID_INFO + && m.text + == Some( + t.ctx + .stock_string_repl_str( + StockMessage::FailedSendingTo, + "assidhfaaspocwaeofi@gmail.com", + ) + .await, + ) + { + found = true; + } + } + assert!(found); + } } From df9cb5e3b8d04f10f462358f42dde42f8d13e099 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 14:32:46 +0200 Subject: [PATCH 09/37] Fix error in message info --- src/message.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/message.rs b/src/message.rs index 31b31b7c7..884c1a28f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -942,7 +942,9 @@ pub async fn get_msg_info(context: &Context, msg_id: MsgId) -> String { ret += "\n"; if let Some(err) = &msg.error { - ret += &format!("Error: {}", err) + if !err.is_empty() { + ret += &format!("Error: {}", err) + } } if let Some(path) = msg.get_file(context) { From b7d0f29002acbfdea47146accd0b87ba14705d90 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 14:41:14 +0200 Subject: [PATCH 10/37] Add test-data/message/gmx_ndn.eml --- test-data/message/gmx_ndn.eml | 113 ++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 test-data/message/gmx_ndn.eml diff --git a/test-data/message/gmx_ndn.eml b/test-data/message/gmx_ndn.eml new file mode 100644 index 000000000..1c498d2f7 --- /dev/null +++ b/test-data/message/gmx_ndn.eml @@ -0,0 +1,113 @@ +Return-Path: <> +Received: from mout-bounce.gmx.net ([212.227.15.44]) by mx-ha.gmx.net + (mxgmx101 [212.227.17.5]) with ESMTPS (Nemesis) id 1Mr97m-1jC6Y01o86-00oEqk + for ; Tue, 09 Jun 2020 14:35:30 +0200 +Received: from localhost by mout-bounce.gmx.net id 0LhiZF-1jDTj11ZoH-00msO3 + Tue, 09 Jun 2020 14:35:30 +0200 +Date: Tue, 09 Jun 2020 14:35:30 +0200 +From: "GMX Mailer Daemon" +To: hocuri@gmx.de +Subject: Mail delivery failed: returning message to sender +Auto-Submitted: auto-replied +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit +X-UI-Out-Filterresults: unknown:0;V03:K0:O8yx6kuPaGQ=:0wIDPNXEr0wX2oNsLnXaWA + == +Envelope-To: +X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3; +X-Spam-Flag: NO +X-UI-Filterresults: notjunk:1;V03:K0:QcE43EBhMmU=:IC5vvzi9jhPS/698Wuubzw1Q4N + h87X9j9B3CBN0ZKXB67KepwyNHmh9pxmFIUOMimylv7UK9np+j3X55roOd0nX9BmaaZ3Twvqf + UaSsxmyU+cNr6m3+oOb3udJBLe2pJEZDk1cOwACb5NXzYPSaIj4APfGCyvrzIx3FGkNuScNBb + tCbbKUJ0GB/VmJLB34XfF6dNN+Iwv9IQ9Yrvw/VXv9vWKsi3qRGGUt3yRw5jUKhQlBY21Pnoq + m0LqoMbAKfH1tKEQ/5TymH1ei50YKyWzZ89ISkQwkbYLaqN+6meGACpY18j43VCU9Fk4WQR7y + 3XvBYh2CO0CnCn+M9VsnasYag2sNrySe9nzyKfRTaxEg8qlJtl7kS4GX/FsxhHPavkqnU62Gl + 9V5TxIG7tmIR0Bf11sPzG/WGegoOHxrfz+qYR81llLMOHznpdDRKjsYDtO/rFBGZzYTiCZsrW + dZPVXV25SVcrDGZOaop3JoCbglmXLcSLLhmfE5MzyJEGte3I+6EiZJNeIe8qN3wMDTsRtJL9S + J6b2F/5/kTGVAWnXtNlf69BholCrxvjC4Snt3Xjc+7WIO8iw2c5YjmWy+4bAwd4uWll529hZd + 6pUYGwjFRnKleivCaJIt7DqbvbE7GZSbQH8fXm3zYqYTrrxiWdlykdoOA1OGbeM06RHJt3mJB + osZPU8BZKt0OiBOW64vg6gyAsNC0f02EA7dvRWYgFYqlSogfWZQIOKDKibMVHpIaA0foXg4BG + TEQDlsTIL0n2WC9WVqkMdm6xUXHgpArCrAsUhw3mEqPywEfJeBHn60tP2vQ9+pDIQAj5dQCDV + y96qSiCX4p31HfrWwAXB9mHfl4OO/tPcKUGBclj2rZ/NMc4O+7yDedLWXQnRzQExfOJLBbBh3 + xgiNlWFHvDLn0pKG9EI1+3wJ7m2GF2jzDtbQTBv9z26DuAq5WbHZHupzeyfP7VCVXcKuB6sG1 + 3+LWcdYtcXfqT58HwcvDLwowC4uJpiHfHwtVdiGMtHnmYLysp0V425g+vofQfNzBgR3d9JC15 + G+HS44o6x6Legm6KnHYH3k0KhR7fgcgswJv/S+I/ryppUhGb2jezVZIUzgvAplzIUDAWnrHdF + KVqZ5wBJ0acShIfgMlsIxnBmcnIQ4R4jq3zAyj4XTFxVUFanU8ySiXubxV5PzJqj+GsVa2sjx + 9n/xQRJLwgMC4BYqzP6lEPwg/g5AneDAnl7ZlcQPC4SCMblC8N1KZyyIDTXPOI/o4lfdMYb9P + 7DmBp2S8aA2yuDe5XT20OmX3kVWeBOsBaAGvVFpIn7gwIDqnFh9WSMP6mkCwfChN3D1yLquYB + KAODgRZV5lVNmK+eOjW8m2oiRxmfxrjXLtw5PEhn3RkiRN4HnoePJeoYC7SG4EUwg+wYPu3M6 + exP/YigoE6bjuBS5d0imUTRDMiwg469GyrFo1J1GkRVvj3lXSF4Nt11j6waqu1l0ReDYfU+QM + EMPGLEh1vRChCaqz4L7YI5FlSAVXxfmst0JRyE4k5r9CToEbZuYlPQ+jbcvptwBSaqzMb/YfT + cCrU2RWHUfmYIy8x8A/t8ScRbYPzs1lTK3yn1hYeXpw8Fgkip6DIIXAJwUUp+2SLcELICIo+p + uumMN0P/OZHH3V/hZ0dPr9xsYi7gdd/vyRIRPUwiL1rSp2WJGi+w4atun8kQBgnbAznRObDh1 + 4zzKhApX9jo5gtFN6640QDEI5KpsMuPoty4rj9OK163ntKWGR451n+5ZX2FilTlpZYlIPO9Hy + SrjHzBog4texceR1OLh4pb/WFB0XFSjQchPAltXCYQFs82aDDk/A0nOPk= + +This message was created automatically by mail delivery software. + +A message that you sent could not be delivered to one or more of +its recipients. This is a permanent error. The following address(es) +failed: + +snaerituhaeirns@gmail.com: +SMTP error from remote server for RCPT TO command, host: gmail-smtp-in.l.google.com (66.102.1.27) reason: 550-5.1.1 The email account that you tried to reach does not exist. Please + try +550-5.1.1 double-checking the recipient's email address for typos or +550-5.1.1 unnecessary spaces. Learn more at +550 5.1.1 https://support.google.com/mail/?p=NoSuchUser f6si2517766wmc.21 +9 - gsmtp + + + +--- The header of the original message is following. --- + +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; + s=badeba3b8450; t=1591706130; + bh=g3zLYH4xKxcPrHOD18z9YfpQcnk/GaJedfustWU5uGs=; + h=X-UI-Sender-Class:To:From:Subject:Date; + b=NwY6W33mI1bAq6lpr6kbY+LD2hO9cDJBItTgY3NRIT94A6rKTVlSmhFM3AxYgFnj0 + Db0hncsNRDqcdtRoOo8Emcah5NJURvEQohG37lkug3GqneB4+FNTdYCeQbOKlZn6on + pYYD/T9CmeL2HG3+8voeBjZIUenyXrF2WXG37hFY= +X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c +Received: from [192.168.178.30] ([84.57.126.154]) by mail.gmx.com (mrgmx005 + [212.227.17.190]) with ESMTPSA (Nemesis) id 1MKbkM-1jNoq60HKm-00KyL2 for + ; Tue, 09 Jun 2020 14:35:30 +0200 +To: snaerituhaeirns@gmail.com +From: Hocuri +Subject: test +Message-ID: <9c9c2a32-056b-3592-c372-d7e8f0bd4bc2@gmx.de> +Date: Tue, 9 Jun 2020 14:36:10 +0200 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 + Thunderbird/68.8.1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 7bit +Content-Language: de-DE +X-Provags-ID: V03:K1:7awoptmynaF5MqxCAincdsa7zFCwQFNkFb6xRxigK06uEiGN00b + Mv2wJU91CEd4mvCCWzrTtaWLZDLH8pjAWaT4+HvYIUbpwNx2jC6WHTppkYYRMVJnm4lG9pr + SUx1OlIcp0kbsnl3mB9xYNFwm9jzpR9Kx8QEHwIbZiiSFBcH56498UGQi//kKXVMos8C14o + I7cmwYmr8xB09DwLMKXfg== +X-Spam-Flag: NO +X-UI-Out-Filterresults: notjunk:1;V03:K0:NWQAUbhAkBc=:yAaolOnVCDWEZhgUwwvtEs + wXbSJ/GfMvDRpCkYpFBvHXOTpGm6hjdjQ0vLK2hvu/Hz22UdlWbIdc1J2oO9S5U20mIdc+1bS + TPSSpqPFc7ICPx4Wbvv2SEp9ZqH2q7ORC52UvUWfI6OjAJEPDNrXQFdUiZAa72hLj1NPeG6Qi + 4AbL2HwLfJ8s6TeOCm6TXRRuD+w1o/ASFOqQmoao2dFyZ2BaoAgOKPKxXYfwVGceuUygpchyS + 0d2bZYOXSLR+6rUYevjZAq1OCi9AIC6/wlkOe5yIRk4gJFMfPauaICsdnq3uZ9ikCAX83VWun + PJVMxTLTP54lgo2h0jMBX3uKk10+/wzXWplllxX9NnSa3x1V28n6raslNF0IoC6Pm72kC6Jzr + GkC22viCm3/Y4uHlPMOXbY5WFrQe/D9GKeJeXBLoGciNwIFkUG12a+iqWtoT+h5HVObTW8LxM + +UtEl97nAwxYSM+sGfIpasRpZc7r/SgN3JWGO9R9WaXpW4Cc1dH7RI+hzuZDsDUBEGTUTVPDo + 0SvjKHiJ6sUqGDyfv4HUgVutus6EYP27LALND4ekfom2DPRFopZhbtV5fZT7CL1Q1NogU7tYf + /FdmR1T1J1zCAZSFvyR5LBkfglZlHzgdnTF2heuxyqKq4dm0hnLFSULB1+CVWsg8hzrruvO5q + XzA6qIhBQUZmWo7wBpqpkBPxzjgTGGtXc5y5e6+crxYbbuQdnUWEnyw2xI4d6pJPqtHDA2/vT + ZgvNDUGceavTR5Rtyb14hhX4Q6dWK3ATy16j4hs9Aq+q/IKyVAX3A5nFYbJRIz+2YnoLr2YOa + IrScEorXjvTxjw+aBy73SZBe2REPzJ+O6k7chVrYjV9Q28FiGVuRYJYxWw/59Pes7IAbmfQBV + 4vqGCQQr4eG78gVwjw+SNdp4/6jdNkIHDqR4XW9id/r5wYxKKj4UUkSor3/+h9Rd9srh+GApy + uOxw/ejFvbRcxFIjvadpq1KLnO7nM27nJ4lp44ul3i7VUGefLM/45TCsuds2HM1iQWhPFQ54y + SA5sYjf73EUJdkHchaf5i+4uSOmbOWQ4Yvmd8+IoyoXAxvEzY2Xh53nWi8ZPY1Tu4Bw8GRrz7 + L+VK0QiWCg3/hM7wRlFFyshmMrScMk5fOf9ynqd0JbHB7u+n4/GUwx3im/w8+NgSd3YOz7wNU + KD1snDWoMUO8f23Ik1Osym688OLWNwKYT+mZbMIMXcz1fB+olRZn4czMhN5DiSb8hyOxRI8NE + PNfaoN87CXiRkgazV6U1eiRkfcK2AvI7zOJF1tclUHZ9awyYoXtxfEzZ+J/2TCXiC7V2iSkUF + EjwgPxlJmccccjsxc46v1ajnTxLo0tJbZ0+DJXWkCgQ0d/iiScQ= + + From 98b5f768b69d524337b52241016b2a41300438ed Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 17:21:33 +0200 Subject: [PATCH 11/37] Improve test, fixed compile errors from rebasing --- src/chat.rs | 16 ++++++------ src/dc_receive_imf.rs | 58 ++++++++++++++++++++++++++++++++----------- src/message.rs | 12 +++++---- src/mimeparser.rs | 3 ++- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 48f22e44b..b938fd5a9 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -424,7 +424,7 @@ impl ChatId { async fn get_parent_mime_headers(self, context: &Context) -> Option<(String, String, String)> { let collect = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)); - let (packed, rfc724_mid, mime_in_reply_to, mime_references): ( + let (rfc724_mid, mime_in_reply_to, mime_references, error): ( String, String, String, @@ -432,15 +432,14 @@ impl ChatId { ) = self .parent_query( context, - "param, rfc724_mid, mime_in_reply_to, mime_references", + "rfc724_mid, mime_in_reply_to, mime_references, error", collect, ) .await .ok() .flatten()?; - let param = packed.parse::().ok()?; - if param.exists(Param::Error) { + if !error.is_empty() { // Do not reply to error messages. // // An error message could be a group chat message that we failed to decrypt and @@ -454,12 +453,13 @@ impl ChatId { } async fn parent_is_encrypted(self, context: &Context) -> Result { - let collect = |row: &rusqlite::Row| Ok(row.get(0)?); - let packed: Option = self.parent_query(context, "param", collect).await?; + let collect = |row: &rusqlite::Row| Ok((row.get(0)?, row.get(1)?)); + let res: Option<(String, String)> = + self.parent_query(context, "param, error", collect).await?; - if let Some(ref packed) = packed { + if let Some((ref packed, ref error)) = res { let param = packed.parse::()?; - Ok(!param.exists(Param::Error) && param.exists(Param::GuaranteeE2ee)) + Ok(error.is_empty() && param.exists(Param::GuaranteeE2ee)) } else { // No messages Ok(false) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index eda689103..89f582293 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -665,8 +665,8 @@ async fn add_parts( "INSERT INTO msgs \ (rfc724_mid, server_folder, server_uid, chat_id, from_id, to_id, timestamp, \ timestamp_sent, timestamp_rcvd, type, state, msgrmsg, txt, txt_raw, param, \ - bytes, hidden, mime_headers, mime_in_reply_to, mime_references) \ - VALUES (?,?,?,?,?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?,?);", + bytes, hidden, mime_headers, mime_in_reply_to, mime_references, error) \ + VALUES (?,?,?,?,?,?, ?,?,?,?,?,?, ?,?,?,?,?,?, ?,?, ?);", )?; let is_location_kml = location_kml_is @@ -710,6 +710,7 @@ async fn add_parts( mime_headers, mime_in_reply_to, mime_references, + part.error, ])?; drop(stmt); @@ -2337,20 +2338,52 @@ mod tests { } #[async_std::test] - async fn test_parse_ndn() { - let t = configured_offline_context().await; + async fn test_parse_ndn_gmail() { + test_parse_ndn( + "alice@gmail.com", + "assidhfaaspocwaeofi@gmail.com", + "CABXKi8zruXJc_6e4Dr087H5wE7sLp+u250o0N2q5DdjF_r-8wg@mail.gmail.com", + include_bytes!("../test-data/message/gmail_ndn.eml"), + "Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp", + ) + .await; + } + + async fn test_parse_ndn( + self_addr: &str, + foreign_addr: &str, + rfc724_mid_outgoing: &str, + raw_ndn: &[u8], + error_msg: &str, + ) { + let t = dummy_context().await; + t.ctx + .set_config(Config::Addr, Some(self_addr)) + .await + .unwrap(); + t.ctx + .set_config(Config::ConfiguredAddr, Some(self_addr)) + .await + .unwrap(); + t.ctx + .set_config(Config::Configured, Some("1")) + .await + .unwrap(); dc_receive_imf( &t.ctx, - b"From: alice@example.org\n\ - To: assidhfaaspocwaeofi@gmail.com\n\ + format!( + "From: {}\n\ + To: {}\n\ Subject: foo\n\ - Message-ID: \n\ + Message-ID: <{}>\n\ Chat-Version: 1.0\n\ - Chat-Disposition-Notification-To: alice@example.org\n\ Date: Sun, 22 Mar 2020 22:37:57 +0000\n\ \n\ hello\n", + self_addr, foreign_addr, rfc724_mid_outgoing + ) + .as_bytes(), "INBOX", 1, false, @@ -2361,18 +2394,13 @@ mod tests { let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); let msg_id = chats.get_msg_id(0).unwrap(); - let raw = include_bytes!("../test-data/message/gmail_ndn.eml"); - dc_receive_imf(&t.ctx, raw, "INBOX", 1, false) + dc_receive_imf(&t.ctx, raw_ndn, "INBOX", 1, false) .await .unwrap(); - println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); assert_eq!(msg.state, MessageState::OutFailed); - assert_eq!( - msg.error.as_ref().map(|s| s.as_str()), - Some("Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp") - ) + assert_eq!(msg.error, error_msg); } #[async_std::test] diff --git a/src/message.rs b/src/message.rs index 884c1a28f..ad6679b18 100644 --- a/src/message.rs +++ b/src/message.rs @@ -255,7 +255,7 @@ pub struct Message { pub(crate) starred: bool, pub(crate) chat_blocked: Blocked, pub(crate) location_id: u32, - pub(crate) error: Option, + pub(crate) error: String, pub(crate) param: Params, } @@ -941,10 +941,9 @@ pub async fn get_msg_info(context: &Context, msg_id: MsgId) -> String { } ret += "\n"; - if let Some(err) = &msg.error { - if !err.is_empty() { - ret += &format!("Error: {}", err) - } + + if !msg.error.is_empty() { + ret += &format!("Error: {}", msg.error); } if let Some(path) = msg.get_file(context) { @@ -1432,8 +1431,10 @@ pub async fn ndn_from_ext( if let Ok((msg_id, chat_id, chat_type, contact_id)) = res { set_msg_failed(context, msg_id, error).await; + info!(context, "cht {} {} {}", chat_id, chat_type, contact_id); if chat_type == Chattype::Group || chat_type == Chattype::VerifiedGroup { + info!(context, "Adding info msg to chat {}", chat_id); let contact = Contact::load_from_db(context, contact_id).await.unwrap(); chat::add_info_msg( context, @@ -1446,6 +1447,7 @@ pub async fn ndn_from_ext( .await, ) .await; + context.emit_event(Event::ChatModified(chat_id)); } } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 1f4bae0f3..ecfdfaea9 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -529,7 +529,7 @@ impl MimeMessage { part.typ = Viewtype::Text; part.msg_raw = Some(txt.clone()); part.msg = txt; - part.param.set(Param::Error, "Decryption failed"); + part.error = "Decryption failed".to_string(); self.parts.push(part); @@ -1013,6 +1013,7 @@ pub struct Part { pub bytes: usize, pub param: Params, org_filename: Option, + pub error: String, } /// return mimetype and viewtype for a parsed mail From 2e59d5674e7c9b43811f500b568c154d6d57a75f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 17:38:10 +0200 Subject: [PATCH 12/37] fix sql --- src/sql.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sql.rs b/src/sql.rs index 94e38cd91..5c54e6f68 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -779,7 +779,6 @@ async fn open( timestamp INTEGER DEFAULT 0, \ type INTEGER DEFAULT 0, \ state INTEGER DEFAULT 0, \ - error TEXT DEFAULT '', \ msgrmsg INTEGER DEFAULT 1, \ bytes INTEGER DEFAULT 0, \ txt TEXT DEFAULT '', \ From bd2a7a3d402f5ed2949c4380449a7f9a6c8a29f8 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Tue, 9 Jun 2020 19:28:49 +0200 Subject: [PATCH 13/37] Correct failed recipient --- src/chat.rs | 5 +++-- src/dc_receive_imf.rs | 33 +++++++++++++++--------------- src/message.rs | 47 ++++++++++++++++++++++--------------------- src/mimeparser.rs | 24 ++++++++++++++++++---- 4 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index b938fd5a9..88611dceb 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2784,7 +2784,7 @@ pub(crate) async fn delete_and_reset_all_device_msgs(context: &Context) -> Resul pub(crate) async fn add_info_msg(context: &Context, chat_id: ChatId, text: impl AsRef) { let rfc724_mid = dc_create_outgoing_rfc724_mid(None, "@device"); - if context.sql.execute( + if let Err(e) = context.sql.execute( "INSERT INTO msgs (chat_id,from_id,to_id, timestamp,type,state, txt,rfc724_mid) VALUES (?,?,?, ?,?,?, ?,?);", paramsv![ chat_id, @@ -2796,7 +2796,8 @@ pub(crate) async fn add_info_msg(context: &Context, chat_id: ChatId, text: impl text.as_ref().to_string(), rfc724_mid, ] - ).await.is_err() { + ).await { + error!(context, "Could not add info msg: {}", e); return; } diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 89f582293..4c2608974 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2441,23 +2441,22 @@ mod tests { assert_eq!(msg.state, MessageState::OutFailed); let msgs = chat::get_chat_msgs(&t.ctx, msg.chat_id, 0, None).await; - let mut found = false; - for id in msgs.iter() { - let m = Message::load_from_db(&t.ctx, *id).await.unwrap(); - if m.from_id == DC_CONTACT_ID_INFO - && m.text - == Some( - t.ctx - .stock_string_repl_str( - StockMessage::FailedSendingTo, - "assidhfaaspocwaeofi@gmail.com", - ) - .await, + println!("Loading {}…", msg.chat_id); + let last_msg = Message::load_from_db(&t.ctx, *msgs.last().unwrap()) + .await + .unwrap(); + + assert_eq!(last_msg.from_id, DC_CONTACT_ID_INFO); + assert_eq!( + last_msg.text, + Some( + t.ctx + .stock_string_repl_str( + StockMessage::FailedSendingTo, + "assidhfaaspocwaeofi@gmail.com", ) - { - found = true; - } - } - assert!(found); + .await, + ) + ); } } diff --git a/src/message.rs b/src/message.rs index ad6679b18..2c1a45747 100644 --- a/src/message.rs +++ b/src/message.rs @@ -14,7 +14,7 @@ use crate::error::{ensure, Error}; use crate::events::Event; use crate::job::{self, Action}; use crate::lot::{Lot, LotState, Meaning}; -use crate::mimeparser::SystemMessage; +use crate::mimeparser::{FailedMsg, SystemMessage}; use crate::param::*; use crate::pgp::*; use crate::stock::StockMessage; @@ -1392,13 +1392,12 @@ pub async fn mdn_from_ext( None } -pub async fn ndn_from_ext( +pub(crate) async fn ndn_from_ext( context: &Context, - from_id: u32, - rfc724_mid: &str, + failed: &FailedMsg, error: Option>, ) { - if from_id <= DC_MSG_ID_LAST_SPECIAL || rfc724_mid.is_empty() { + if failed.rfc724_mid.is_empty() { return; } @@ -1410,17 +1409,15 @@ pub async fn ndn_from_ext( " m.id AS msg_id,", " c.id AS chat_id,", " c.type AS type,", - " m.to_id AS to_id", " FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id", " WHERE rfc724_mid=? AND from_id=1", ), - paramsv![rfc724_mid], + paramsv![failed.rfc724_mid], |row| { Ok(( row.get::<_, MsgId>("msg_id")?, row.get::<_, ChatId>("chat_id")?, row.get::<_, Chattype>("type")?, - row.get::<_, u32>("to_id")?, )) }, ) @@ -1429,25 +1426,29 @@ pub async fn ndn_from_ext( info!(context, "Failed to select NDN {:?}", err); } - if let Ok((msg_id, chat_id, chat_type, contact_id)) = res { + if let Ok((msg_id, chat_id, chat_type)) = res { set_msg_failed(context, msg_id, error).await; - info!(context, "cht {} {} {}", chat_id, chat_type, contact_id); if chat_type == Chattype::Group || chat_type == Chattype::VerifiedGroup { - info!(context, "Adding info msg to chat {}", chat_id); - let contact = Contact::load_from_db(context, contact_id).await.unwrap(); - chat::add_info_msg( - context, - chat_id, - context - .stock_string_repl_str( - StockMessage::FailedSendingTo, - contact.get_display_name(), + if let Some(failed_recipient) = &failed.failed_recipient { + let contact_id = + Contact::lookup_id_by_addr(context, failed_recipient, Origin::Unknown).await; + if let Ok(contact) = Contact::load_from_db(context, contact_id).await { + // Tell the user which of the recipients failed if we know that (because in a group, this might otherwise be unclear) + chat::add_info_msg( + context, + chat_id, + context + .stock_string_repl_str( + StockMessage::FailedSendingTo, + contact.get_display_name(), + ) + .await, ) - .await, - ) - .await; - context.emit_event(Event::ChatModified(chat_id)); + .await; + context.emit_event(Event::ChatModified(chat_id)); + } + } } } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index ecfdfaea9..0ffea486c 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -54,7 +54,7 @@ pub struct MimeMessage { pub(crate) user_avatar: Option, pub(crate) group_avatar: Option, pub(crate) reports: Vec, - pub(crate) failed_msg: Option, + pub(crate) failed_msg: Option, } #[derive(Debug, PartialEq)] @@ -881,7 +881,7 @@ impl MimeMessage { .iter() .find(|p| p.typ == Viewtype::Text) .map(|p| &p.msg); - message::ndn_from_ext(context, from_id, original_message_id, error).await + message::ndn_from_ext(context, original_message_id, error).await } } @@ -889,7 +889,7 @@ impl MimeMessage { &self, context: &Context, report: &mailparse::ParsedMail<'_>, - ) -> Result> { + ) -> Result> { // parse as mailheaders if let Some(original_msg) = report .subparts @@ -903,7 +903,17 @@ impl MimeMessage { .get_header_value(HeaderDef::MessageId) .and_then(|v| parse_message_id(&v).ok()) { - return Ok(Some(original_message_id)); + let mut to_list = get_recipients(&report_fields); + let to = if to_list.len() == 1 { + Some(to_list.pop().unwrap()) + } else { + None // We do not know which recipient failed + }; + + return Ok(Some(FailedMsg { + rfc724_mid: original_message_id, + failed_recipient: to.map(|s| s.addr), + })); } warn!( @@ -970,6 +980,12 @@ pub(crate) struct Report { additional_message_ids: Vec, } +#[derive(Debug)] +pub(crate) struct FailedMsg { + pub rfc724_mid: String, + pub failed_recipient: Option, +} + pub(crate) fn parse_message_ids(ids: &str) -> Result> { // take care with mailparse::msgidparse() that is pretty untolerant eg. wrt missing `<` or `>` let mut msgids = Vec::new(); From e7aee5b4f464f36e53465842e3d91576a3a976b5 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 11:33:10 +0200 Subject: [PATCH 14/37] add gmx and posteo tests --- src/dc_receive_imf.rs | 40 ++++++++++- test-data/message/gmx_ndn.eml | 8 +-- test-data/message/posteo_ndn.eml | 113 +++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 test-data/message/posteo_ndn.eml diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 4c2608974..a25d1a4d6 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2349,6 +2349,30 @@ mod tests { .await; } + #[async_std::test] + async fn test_parse_ndn_gmx() { + test_parse_ndn( + "alice@gmx.com", + "snaerituhaeirns@gmail.com", + "9c9c2a32-056b-3592-c372-d7e8f0bd4bc2@gmx.de", + include_bytes!("../test-data/message/gmx_ndn.eml"), + "Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp", + ) + .await; + } + + #[async_std::test] + async fn test_parse_ndn_posteo() { + test_parse_ndn( + "alice@posteo.org", + "hanerthaertidiuea@gmx.de", + "04422840-f884-3e37-5778-8192fe22d8e1@posteo.de", + include_bytes!("../test-data/message/posteo_ndn.eml"), + "Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp", + ) + .await; + } + async fn test_parse_ndn( self_addr: &str, foreign_addr: &str, @@ -2405,11 +2429,23 @@ mod tests { #[async_std::test] async fn test_parse_ndn_group_msg() { - let t = configured_offline_context().await; + let t = dummy_context().await; + t.ctx + .set_config(Config::Addr, Some("alice@gmail.com")) + .await + .unwrap(); + t.ctx + .set_config(Config::ConfiguredAddr, Some("alice@gmail.com")) + .await + .unwrap(); + t.ctx + .set_config(Config::Configured, Some("1")) + .await + .unwrap(); dc_receive_imf( &t.ctx, - b"From: alice@example.org\n\ + b"From: alice@gmail.com\n\ To: bob@example.org, assidhfaaspocwaeofi@gmail.com\n\ Subject: foo\n\ Message-ID: \n\ diff --git a/test-data/message/gmx_ndn.eml b/test-data/message/gmx_ndn.eml index 1c498d2f7..1c45f57b9 100644 --- a/test-data/message/gmx_ndn.eml +++ b/test-data/message/gmx_ndn.eml @@ -1,12 +1,12 @@ Return-Path: <> Received: from mout-bounce.gmx.net ([212.227.15.44]) by mx-ha.gmx.net (mxgmx101 [212.227.17.5]) with ESMTPS (Nemesis) id 1Mr97m-1jC6Y01o86-00oEqk - for ; Tue, 09 Jun 2020 14:35:30 +0200 + for ; Tue, 09 Jun 2020 14:35:30 +0200 Received: from localhost by mout-bounce.gmx.net id 0LhiZF-1jDTj11ZoH-00msO3 Tue, 09 Jun 2020 14:35:30 +0200 Date: Tue, 09 Jun 2020 14:35:30 +0200 From: "GMX Mailer Daemon" -To: hocuri@gmx.de +To: alice@gmx.de Subject: Mail delivery failed: returning message to sender Auto-Submitted: auto-replied MIME-Version: 1.0 @@ -14,7 +14,7 @@ Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-UI-Out-Filterresults: unknown:0;V03:K0:O8yx6kuPaGQ=:0wIDPNXEr0wX2oNsLnXaWA == -Envelope-To: +Envelope-To: X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3; X-Spam-Flag: NO X-UI-Filterresults: notjunk:1;V03:K0:QcE43EBhMmU=:IC5vvzi9jhPS/698Wuubzw1Q4N @@ -74,7 +74,7 @@ Received: from [192.168.178.30] ([84.57.126.154]) by mail.gmx.com (mrgmx005 [212.227.17.190]) with ESMTPSA (Nemesis) id 1MKbkM-1jNoq60HKm-00KyL2 for ; Tue, 09 Jun 2020 14:35:30 +0200 To: snaerituhaeirns@gmail.com -From: Hocuri +From: Alice Subject: test Message-ID: <9c9c2a32-056b-3592-c372-d7e8f0bd4bc2@gmx.de> Date: Tue, 9 Jun 2020 14:36:10 +0200 diff --git a/test-data/message/posteo_ndn.eml b/test-data/message/posteo_ndn.eml new file mode 100644 index 000000000..eedc63e14 --- /dev/null +++ b/test-data/message/posteo_ndn.eml @@ -0,0 +1,113 @@ +Return-Path: <> +Delivered-To: alice@posteo.org +Received: from proxy02.posteo.name ([127.0.0.1]) + by dovecot03.posteo.local (Dovecot) with LMTP id zvCFJRzX317LGQIA+3EWog + for ; Tue, 09 Jun 2020 20:44:24 +0200 +Received: from proxy02.posteo.de ([127.0.0.1]) + by proxy02.posteo.name (Dovecot) with LMTP id mhNkNAnR316xBQMAGFAyLg + ; Tue, 09 Jun 2020 20:44:23 +0200 +Received: from mailin06.posteo.de (unknown [10.0.1.6]) + by proxy02.posteo.de (Postfix) with ESMTPS id 49hJtv3RRcz11m7 + for ; Tue, 9 Jun 2020 20:44:23 +0200 (CEST) +Received: from mx04.posteo.de (mailin06.posteo.de [127.0.0.1]) + by mailin06.posteo.de (Postfix) with ESMTPS id 6935920DD2 + for ; Tue, 9 Jun 2020 20:44:23 +0200 (CEST) +X-Virus-Scanned: amavisd-new at posteo.de +X-Spam-Flag: NO +X-Spam-Score: -1 +X-Spam-Level: +X-Spam-Status: No, score=-1 tagged_above=-1000 required=8 + tests=[ALL_TRUSTED=-1] autolearn=disabled +Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) + by mx04.posteo.de (Postfix) with ESMTPS id 49hJtv001Vz10kT + for ; Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +Authentication-Results: mx04.posteo.de; dmarc=none (p=none dis=none) header.from=mout01.posteo.de +Received: by mout01.posteo.de (Postfix) + id DCB6B1200DD; Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +Date: Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +From: MAILER-DAEMON@mout01.posteo.de (Mail Delivery System) +Subject: Undelivered Mail Returned to Sender +To: alice@posteo.org +Auto-Submitted: auto-replied +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="B39111200B9.1591728262/mout01.posteo.de" +Content-Transfer-Encoding: 7bit +Message-Id: <20200609184422.DCB6B1200DD@mout01.posteo.de> + +This is a MIME-encapsulated message. + +--B39111200B9.1591728262/mout01.posteo.de +Content-Description: Notification +Content-Type: text/plain; charset=us-ascii + +This is the mail system at host mout01.posteo.de. + +I'm sorry to have to inform you that your message could not +be delivered to one or more recipients. It's attached below. + +For further assistance, please send mail to postmaster. + +If you do so, please include this problem report. You can +delete your own text from the attached returned message. + + The mail system + +: host mx01.emig.gmx.net[212.227.17.5] said: 550 + Requested action not taken: mailbox unavailable (in reply to RCPT TO + command) + +--B39111200B9.1591728262/mout01.posteo.de +Content-Description: Delivery report +Content-Type: message/delivery-status + +Reporting-MTA: dns; mout01.posteo.de +X-Postfix-Queue-ID: B39111200B9 +X-Postfix-Sender: rfc822; alice@posteo.org +Arrival-Date: Tue, 9 Jun 2020 20:44:22 +0200 (CEST) + +Final-Recipient: rfc822; hanerthaertidiuea@gmx.de +Original-Recipient: rfc822;hanerthaertidiuea@gmx.de +Action: failed +Status: 5.0.0 +Remote-MTA: dns; mx01.emig.gmx.net +Diagnostic-Code: smtp; 550 Requested action not taken: mailbox unavailable + +--B39111200B9.1591728262/mout01.posteo.de +Content-Description: Undelivered Message Headers +Content-Type: text/rfc822-headers + +Return-Path: +Received: from mout01.posteo.de (unknown [10.0.0.65]) + by mout01.posteo.de (Postfix) with ESMTPS id B39111200B9 + for ; Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +Received: from submission-encrypt01.posteo.de (unknown [10.0.0.75]) + by mout01.posteo.de (Postfix) with ESMTPS id 8A684160060 + for ; Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.de; s=2017; + t=1591728262; bh=g3zLYH4xKxcPrHOD18z9YfpQcnk/GaJedfustWU5uGs=; + h=To:From:Subject:Date:From; + b=brJnt4PLAX3Tda1RHCo91aB1kMAL/Ku9dmO7D2DD41Zu5ShNsyqqyDkyxb1DsDn3O + 6KuBZe3/8gemBuCJ/mxzwd9v8sBnlrV+5afIk0Ye9VvthZsc4HoG79+FiVOi9F38o0 + DtJJFYFw/X7mAc5Xyt0B0JvtiTPpBdRAkluUQm+QW6cW6GGlwicVW19qvebzq+sHyP + X2bZ8wpo78yVgvjPBK3DLaXa+pKFMBjLdDUcIE2bZnY6u6F1x8SXGKGBoxVwdJipJx + v14so5IejNsf4LYJjH3Qb8xgK1aAi6e6nQn4YXV0INL6ahzgALiT9N6vwunNKYVJNi + fPPKvBWDfUS4Q== +Received: from customer (localhost [127.0.0.1]) + by submission (posteo.de) with ESMTPSA id 49hJtt1WPbz6tmV + for ; Tue, 9 Jun 2020 20:44:22 +0200 (CEST) +To: hanerthaertidiuea@gmx.de +From: deltachat +Subject: test +Message-ID: <04422840-f884-3e37-5778-8192fe22d8e1@posteo.de> +Date: Tue, 9 Jun 2020 20:45:02 +0200 +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 + Thunderbird/68.8.1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 7bit +Content-Language: de-DE +Posteo-User: alice@posteo.org +Posteo-Dkim: ok + +--B39111200B9.1591728262/mout01.posteo.de-- From 3899d70b3c3aa8af8aaec6184d50cfc6577801fc Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 11:59:06 +0200 Subject: [PATCH 15/37] I hate SQL --- src/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message.rs b/src/message.rs index 2c1a45747..83510a87d 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1408,7 +1408,7 @@ pub(crate) async fn ndn_from_ext( "SELECT", " m.id AS msg_id,", " c.id AS chat_id,", - " c.type AS type,", + " c.type AS type", " FROM msgs m LEFT JOIN chats c ON m.chat_id=c.id", " WHERE rfc724_mid=? AND from_id=1", ), From e1711855cc54c744f8b553ba9810c66fec71a2f5 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 12:06:14 +0200 Subject: [PATCH 16/37] Make the posteo test pass --- src/dc_receive_imf.rs | 2 +- src/mimeparser.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index a25d1a4d6..0b4ef1f05 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2368,7 +2368,7 @@ mod tests { "hanerthaertidiuea@gmx.de", "04422840-f884-3e37-5778-8192fe22d8e1@posteo.de", include_bytes!("../test-data/message/posteo_ndn.eml"), - "Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp", + "Undelivered Mail Returned to Sender – This is the mail system at host mout01.posteo.de.\n\nI\'m sorry to have to inform you that your message could not\nbe delivered to one or more recipients. It\'s attached below.\n\nFor further assistance, please send mail to postmaster.\n\nIf you do so, please include this problem report. You can\ndelete your own text from the attached returned message.\n\n The mail system\n\n: host mx01.emig.gmx.net[212.227.17.5] said: 550\n Requested action not taken: mailbox unavailable (in reply to RCPT TO\n command)", ) .await; } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 0ffea486c..56bb9e942 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -894,7 +894,7 @@ impl MimeMessage { if let Some(original_msg) = report .subparts .iter() - .find(|p| p.ctype.mimetype == "message/rfc822") + .find(|p| p.ctype.mimetype.contains("rfc822")) { let report_body = original_msg.get_body_raw()?; let (report_fields, _) = mailparse::parse_headers(&report_body)?; From 777df24c75b99d497c737838d40ab6bee28c4f4d Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 14:44:55 +0200 Subject: [PATCH 17/37] Make the gmx test pass --- src/dc_receive_imf.rs | 4 +- src/mimeparser.rs | 131 +++++++++----- test-data/message/aol_ndn.eml | 100 +++++++++++ test-data/message/gmail_ndn_group.eml | 242 ++++++++++++++++++++++++++ test-data/message/yahoo_ndn.eml | 100 +++++++++++ 5 files changed, 530 insertions(+), 47 deletions(-) create mode 100644 test-data/message/aol_ndn.eml create mode 100644 test-data/message/gmail_ndn_group.eml create mode 100644 test-data/message/yahoo_ndn.eml diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 0b4ef1f05..6bf07bf82 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2356,7 +2356,7 @@ mod tests { "snaerituhaeirns@gmail.com", "9c9c2a32-056b-3592-c372-d7e8f0bd4bc2@gmx.de", include_bytes!("../test-data/message/gmx_ndn.eml"), - "Delivery Status Notification (Failure) – ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp", + "Mail delivery failed: returning message to sender – This message was created automatically by mail delivery software.\n\nA message that you sent could not be delivered to one or more of\nits recipients. This is a permanent error. The following address(es)\nfailed:\n\nsnaerituhaeirns@gmail.com:\nSMTP error from remote server for RCPT TO command, host: gmail-smtp-in.l.google.com (66.102.1.27) reason: 550-5.1.1 The email account that you tried to reach does not exist. Please\n try\n550-5.1.1 double-checking the recipient\'s email address for typos or\n550-5.1.1 unnecessary spaces. Learn more at\n550 5.1.1 https://support.google.com/mail/?p=NoSuchUser f6si2517766wmc.21\n9 - gsmtp" ) .await; } @@ -2466,7 +2466,7 @@ mod tests { let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); let msg_id = chats.get_msg_id(0).unwrap(); - let raw = include_bytes!("../test-data/message/gmail_ndn.eml"); + let raw = include_bytes!("../test-data/message/gmail_ndn_group.eml"); dc_receive_imf(&t.ctx, raw, "INBOX", 1, false) .await .unwrap(); diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 56bb9e942..f895212b9 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -3,6 +3,7 @@ use std::future::Future; use std::pin::Pin; use deltachat_derive::{FromSql, ToSql}; +use lazy_static::lazy_static; use lettre_email::mime::{self, Mime}; use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo}; @@ -186,6 +187,7 @@ impl MimeMessage { failed_msg: None, }; parser.parse_mime_recursive(context, &mail).await?; + parser.heuristically_parse_ndn().await; parser.parse_headers(context)?; Ok(parser) @@ -855,6 +857,82 @@ impl MimeMessage { Ok(None) } + fn process_delivery_status( + &self, + context: &Context, + report: &mailparse::ParsedMail<'_>, + ) -> Result> { + // parse as mailheaders + if let Some(original_msg) = report + .subparts + .iter() + .find(|p| p.ctype.mimetype.contains("rfc822")) + { + let report_body = original_msg.get_body_raw()?; + let (report_fields, _) = mailparse::parse_headers(&report_body)?; + + if let Some(original_message_id) = report_fields + .get_header_value(HeaderDef::MessageId) + .and_then(|v| parse_message_id(&v).ok()) + { + let mut to_list = get_all_addresses_from_header(&report.headers, |header_key| { + header_key == "X-Failed-Recipients" + }); + let to = if to_list.len() == 1 { + Some(to_list.pop().unwrap()) + } else { + None // We do not know which recipient failed + }; + + return Ok(Some(FailedMsg { + rfc724_mid: original_message_id, + failed_recipient: to.map(|s| s.addr), + })); + } + + warn!( + context, + "ignoring unknown ndn-notification, Message-Id: {:?}", + report_fields.get_header_value(HeaderDef::MessageId) + ); + } + + Ok(None) + } + + async fn heuristically_parse_ndn(&mut self) -> Option<()> { + if self + .get(HeaderDef::Subject)? + .to_ascii_lowercase() + .contains("fail") + && self + .get(HeaderDef::From_)? + .to_ascii_lowercase() + .contains("daemon") + && self.failed_msg.is_none() + { + for line in self + .parts + .iter() + .filter_map(|p| p.msg_raw.as_ref()) + .flat_map(|p| p.lines()) + { + lazy_static! { + static ref RE: regex::Regex = regex::Regex::new(r"Message-ID:(.*)").unwrap(); + } + if let Some(c) = RE.captures(line) { + if let Ok(original_message_id) = parse_message_id(&c[1]) { + self.failed_msg = Some(FailedMsg { + rfc724_mid: original_message_id, + failed_recipient: None, + }) + } + } + } + } + None + } + /// Handle reports (only MDNs for now) pub async fn handle_reports( &self, @@ -877,54 +955,17 @@ impl MimeMessage { } if let Some(original_message_id) = &self.failed_msg { - let error = parts - .iter() - .find(|p| p.typ == Viewtype::Text) - .map(|p| &p.msg); + let error = parts.iter().find(|p| p.typ == Viewtype::Text).map(|p| { + let msg = &p.msg; + match msg.find("\n--- ") { + Some(footer_start) => &msg[..footer_start], + None => msg, + } + .trim() + }); message::ndn_from_ext(context, original_message_id, error).await } } - - fn process_delivery_status( - &self, - context: &Context, - report: &mailparse::ParsedMail<'_>, - ) -> Result> { - // parse as mailheaders - if let Some(original_msg) = report - .subparts - .iter() - .find(|p| p.ctype.mimetype.contains("rfc822")) - { - let report_body = original_msg.get_body_raw()?; - let (report_fields, _) = mailparse::parse_headers(&report_body)?; - - if let Some(original_message_id) = report_fields - .get_header_value(HeaderDef::MessageId) - .and_then(|v| parse_message_id(&v).ok()) - { - let mut to_list = get_recipients(&report_fields); - let to = if to_list.len() == 1 { - Some(to_list.pop().unwrap()) - } else { - None // We do not know which recipient failed - }; - - return Ok(Some(FailedMsg { - rfc724_mid: original_message_id, - failed_recipient: to.map(|s| s.addr), - })); - } - - warn!( - context, - "ignoring unknown ndn-notification, Message-Id: {:?}", - report_fields.get_header_value(HeaderDef::MessageId) - ); - } - - Ok(None) - } } async fn update_gossip_peerstates( diff --git a/test-data/message/aol_ndn.eml b/test-data/message/aol_ndn.eml new file mode 100644 index 000000000..d0f5188b8 --- /dev/null +++ b/test-data/message/aol_ndn.eml @@ -0,0 +1,100 @@ +X-Atlas-Received: from 10.218.248.40 by atlas207.aol.mail.ne1.yahoo.com with http; Wed, 10 Jun 2020 10:42:33 +0000 +Return-Path: <> +Received: from 74.6.131.123 (EHLO sonic311-13.consmr.mail.bf2.yahoo.com) + by atlas207.aol.mail.ne1.yahoo.com with SMTPs; Wed, 10 Jun 2020 10:42:33 +0000 +X-Originating-Ip: [74.6.131.123] +Received-SPF: none (domain of sonic311-13.consmr.mail.bf2.yahoo.com does not designate permitted sender hosts) +Authentication-Results: atlas207.aol.mail.ne1.yahoo.com; + dkim=pass header.i=@yahoo.com header.s=@bounce; + spf=none smtp.mailfrom=sonic311-13.consmr.mail.bf2.yahoo.com; + dmarc=success(p=REJECT) header.from=yahoo.com; +X-Apparently-To: deltachattestac@aol.com; Wed, 10 Jun 2020 10:42:33 +0000 +X-YMailISG: DkLFz_oWLDvt4_NIgCwKD1jZui63WnISNmlXQ_XYR2MqQH9y + Sa__GenYvUZEmGPWcZU0SLRtkdYKB66hm6jbzx7Pw4j6es6aXyOHs91T5xeW + Bvqm5IjytmXBG.ELVw0MjCKEPx36Wr5pptHuryDWttC8.qeN9w_SZy1kXtkE + vJDjXD1IIMZ1XpywJyBYu3Ld3AKkTd0mU3V7wbq3LY8A3dsgO7Gv8Doq4PyJ + 6DxK2NqUp.GOAjj_9pH97OFJCeUCjc.dlEVPbrvfBUPimoluyG00EnyyyhjL + KnDZiAZnCVUA9H2lfM0uWqNCF7CowDoehVecVHpiLJ7Xl415wQjOjWSTzatA + Buh2hsSQDbpPRLZbjnY0B4sC1vMKnCm3B2P04KYEWs7W_m_Ysvtidkg1SyKR + vsm8UDlDfLFSNtaE6LuxkgK90hVfM3qHXpnAPnUkB626ucgZAJDvXMg3q_S. + rMOcm0e5LPVON_LjqMSefreahzGebN88_klofvxDaBm7EZIFd933_EWrJ1yZ + P_hp5lPTaYmFTuukp8UR9ZfwVCbz6FmUzQwbNvGsmWgI2mVxgGgCay4OJKOk + gyTyQXzDGitU82HsLfgpIricWWdou7tlkwUQXv2w6p1.QbmbZ628n5xiN2jF + EQOqz9GHSdN4YPDGzbd2QrqkWWSXWcP4TRoFJMvPEnxwgqN4BrCMY52x2koF + Fj4Lm65pq26I7ErlHpYU4bN5Y2CbYZN5ppWtqalyMX167S8mDTF0vkW.0aqa + nLNu38OSqRfUqRPPQ7AQn3E14fcFq0pzxHANEVRzXKvEYhPOBu_90NxxamxU + G.eFig8PQFQIzOZwzN7KreILICiMNeZxRDoJdT5ouFy6t5fdNUYB_ee5byqg + wQxFpGY1oqjqnF8cKhoqXKbewhXnAHtruHmJctwcDFB6Z8Ky3trGEHXeFKUm + GDXN6bh1VT2YLVcWEmfzO3F.4zVSYcpsDkJD_a8_ywFNwxs.cXyhZyba4x7Y + 3X_XjCes4rCDftjcZuVBMiX3KYZNX.oooDLZBmsb3P.j1FQ8XIurzueTrFpE + O_dhyhgI.hOo8BweGv3a89eFdBCyhU1o7cEGK.mrU1sj3kX6d4FhfHmA8cGv + n50B5b94d3MpWSnSDFldjz0i2Jun6VUVYuG3yFqtsrf7ZnaTuxswub9SrhbO + mF02jK6oxTIWYUZEU8vgvciXeiS_YdSmJ1tzbeWJRFeo6ePbTbcZGmY- +X-Originating-IP: [74.6.131.123] +Received: from 10.220.180.155 (EHLO sonic311-13.consmr.mail.bf2.yahoo.com) (74.6.131.123) + by mta4011.aol.mail.ne1.yahoo.com with SMTPS; Wed, 10 Jun 2020 10:42:32 +0000 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=bounce; t=1591785751; bh=iNhZ8sZ9ZQS8RKoDRTbDsAW/YGN71KVQTVc/Xecb9UQ=; h=Date:From:To:Subject:From:Subject; b=IEjn12+yP0ddLWLojXRLLBx545x7trCIcmMiPuKViBb+UBCAT568e0nmwukVqF6FfeR4hcmWqISlyR22409sOckSZmf0+Fj3rgeaFAmhrl1l4P1uEdNSB4dMH3gcHxAN3DdTyUBQss2ZIyu7xnYJguCadQ1/1ELa865EtJJAkes= +Received: from sonic.gate.mail.ne1.yahoo.com by sonic311.consmr.mail.bf2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:42:31 +0000 +Date: Wed, 10 Jun 2020 10:42:31 +0000 +From: MAILER-DAEMON@yahoo.com +To: deltachattestac@aol.com +Message-ID: <1266721401.228154.1591785751559@sonic311.consmr.mail.bf2.yahoo.com> +Subject: Failure Notice +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit +Content-Length: 3322 + +Sorry, we were unable to deliver your message to the following address. + +: +550: 5.1.1 : Recipient address rejected: User unknown in virtual mailbox table + +--- Below this line is a copy of the message. + +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1591785750; bh=4ktMNgiiY0GHVCUgIv4TvXVESetaS2esyta25tCU5Rg=; h=Date:From:Reply-To:To:Subject:References:From:Subject; b=HLpgexVrsHu1BSnI+l+ob6hCyl2HRO3xPCLRg090QIR1LwMtMbccdjSSi6o17Qx1E/6Y0YHqHgDq+/vGxXZ72GyxHfimpHWYxfjhpgbuXxCbPZkcPejE1kjsR0LHLZ0lmHPuZYbY6pdpROfQC3jOwL616p0vhqZ4QwSTsQhmOBgydA85uIvTWqzjra0GNY5oS8k9CwSmE2N8bRPmEmZzkPytV2RimpEwylCy7IiJ7S6EURnyjxMO5uaZukNjh/XJLxzEEo1ief0EeYfYuq3BPTKHJf7FqV6Dzqu7bIbowVWBTTJ7eFAPUcDwoum5Yz5H63gp5ZFhghV0tDcAjSzOIA== +X-YMail-OSG: XrOprp8VM1l6O.1AuZ5z4b5aOZ5xPHdr1b50c6CBHbn7lnLF9ZdsolbJdKegkJi + NAXKKEdjXM4834uHoJ0tQijRGfPO2pZ8Ie0fgORrev_T1z0c9cmt92vSh2eH2CL3wpaY3nJBQqjL + XxcC3E7cmThUGmPXMCc8O6hYBtGJyyw0lFvegOkgNkIZ.VdHcMyCXoqzrLrTUx1AVI8j_5l7J_iL + wbrGBndP484r_S04WrvzM_i1yRg.Zl01q5o17SjS2vKn2mlLhZhNtBR1RyM9HmoZcEpOW0QesDHm + BLYBeag8wczZJBA6xuAVgLTwCkMHRCRqFMfb.22mpfY6HTwOP3EsG5.we8Ywe.7mSIVhfjozg9Bm + BR3qGGHKD7tJR4X8RFE.tRrnaJS_pUZ1frkJcxEpiau9VFvbTHm5QDltb5gLJUKcj1axNQcPOXF5 + 9lCbo04.yHhjrh.nBk0YmVAYR4.CtpnlgxFdB_ylCqy7cAVukViqvvYBE90PhmT2B8OZBK3LE8De + jvDIDmkyEe4vu6uE7AAlP.vOi5fFEtkGkGsI46uvUARICijKiIfVA5k7XeN3Ahz0Eil05w.kWPYv + SgA8r39ZLclSnGTn.bT5lz8toogaE.GeGz_ChdKT5MD9.1VFZVM1ir2RipJO1XPbBXGB2eWtTmje + WiuXY4ydHo.FusM7VREfyxfo7cUIFlcNwidJGSKYG3YQbj8Gx3ZFDBzW2rOqRhXLWNMbA4owKTiZ + FtcZTwSiGZvUefyMf0c_FWTLdgz.ZNyuDnMEqdAymAxX9vlTtA7pY8EPPC3TwHFG6Zrk2w_UA7Wv + mxfZbbCz26O4_1CnByCh1YBbb8ijWLCq3ZjnNcHSwdSZMpuysG3hAd42R.xNHM.W69WS6m0LnwQj + cnaoTVl6T1Me5EkWX7Z8i75nhIwV1csc74lFgb_.5uDjRKFjmA3KUu5UWDCiWjjWqEeMf6Fsl1nQ + ltXet3ZdssaDjmXfMncHv4Qz7nmH4z_QYovap4SApHUQjPgPPVZHsofmikIugjtzeXqM4OFN0xjZ + 0GzjH9W4EqGlWY29nwPOswrB429jvMHA5R.mBTS6mUBmYm924n4v9yJ2TUTOy4Vh.65Ngd8AsGgm + 75u125bogA5MKHMPGfWpnrys9lCyq3mmhtkkc58R3PYfX0iBXjdP7diVMQhjGgqZMPBbDhDzbECx + mlgcqfqVGwyOmWmKe0OUFjyMVxYV9DwucWIKA.sd02NWEZhDzoQ3CHkaedi3i3YAePx9jbNnNIuo + MY.d8jQDDBQxMtPcece79VtoHLAjwKNT5cSzlvpgJHNtVyOpWjOQ- +Received: from sonic.gate.mail.ne1.yahoo.com by sonic311.consmr.mail.bf2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:42:30 +0000 +Date: Wed, 10 Jun 2020 10:42:27 +0000 (UTC) +From: Delta Chat Test +Reply-To: Delta Chat Test +To: "hsnaeirternaeiho@testrun.org" +Message-ID: <1772450882.1447284.1591785747540@mail.yahoo.com> +Subject: test +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_1447283_353296880.1591785747539" +References: <1772450882.1447284.1591785747540.ref@mail.yahoo.com> +X-Mailer: WebService/1.1.16072 aolwebmail Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0 +Content-Length: 418 + +------=_Part_1447283_353296880.1591785747539 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit + +test +------=_Part_1447283_353296880.1591785747539 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 7bit + + +
test
+ +------=_Part_1447283_353296880.1591785747539-- diff --git a/test-data/message/gmail_ndn_group.eml b/test-data/message/gmail_ndn_group.eml new file mode 100644 index 000000000..77b66a26d --- /dev/null +++ b/test-data/message/gmail_ndn_group.eml @@ -0,0 +1,242 @@ +Delivered-To: alice@gmail.com +Received: by 2002:a02:6629:0:0:0:0:0 with SMTP id k41csp368502jac; + Wed, 10 Jun 2020 05:17:57 -0700 (PDT) +X-Received: by 2002:a6b:1448:: with SMTP id 69mr2898530iou.83.1591791475733; + Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +ARC-Seal: i=1; a=rsa-sha256; t=1591791475; cv=none; + d=google.com; s=arc-20160816; + b=a0vSKJPbMtGYFnuk1ye/gnnV00Zvva4OOJTMOyfm13xMJD0YAhzGVfa7Z+wn5sQ8dw + VAxpmDHCkjp4jol0C1iutiq2Nl0qma819oFPuuoMLLatKQXHpo8Jt+sL3MnwNR7J5bZC + 1c6Fjk75EIsRWhJd1HCkm44A6UYHxqqsTnzQCaNiHbjsRsvbggxwlMGSrZ4silxqSDvo + Pzd/YDLCvsnZNSNIjIckKAwtGmY6sXctZ+JnOTykXAyL32Milfwy1vRL9xm10Q14biTR + +qaIQp4E6WE63g1WHvfAjs0Dru7DalUh4GGl/NAwqVhY1gVyRD5E9/nODyHAfxjvaxDD + 4sMw== +ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; + h=in-reply-to:references:subject:from:date:message-id:auto-submitted + :to:dkim-signature; + bh=XaR1H4XeD+InO7mULPJn53omDGmxN+KG6DbSxyyErPM=; + b=OJbgbrktMKyczw25z/ib7lSdRX80PEK3Myh9fj4q6mDlXmPPv//Gv069znRQ4QbadM + HUXZH0WLMZcGyqI6SvGL/noxQ1O8yP0FYJJKTkoX0Gk2hHzfaE3x1scOP/o2FMMQXIFm + S4CgGBD6HHzBJYj/rSL3gzqLzx1Id/z5kTeDvH2cn8JJAcCE2q/nhjTyWUb87geoNlDJ + A1HRrLHK/0JOyRjHfg2zZCqIvSi1xmpiHStMyL9mfVyrQs98tsPxaOkJHjLplFARoPlr + mmmDvsFg7MPvFqkkANzz4JDHidnfKRULCgnrVj1yTU66UagUpQEGjZqz8/99YuU6nt1t + 81sQ== +ARC-Authentication-Results: i=1; mx.google.com; + dkim=pass header.i=@googlemail.com header.s=20161025 header.b=aO4aNy7C; + spf=pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) smtp.helo=mail-sor-f69.google.com; + dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com +Return-Path: <> +Received: from mail-sor-f69.google.com (mail-sor-f69.google.com. [209.85.220.69]) + by mx.google.com with SMTPS id w14sor16686480iow.23.2020.06.10.05.17.55 + for + (Google Transport Security); + Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +Received-SPF: pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) client-ip=209.85.220.69; +Authentication-Results: mx.google.com; + dkim=pass header.i=@googlemail.com header.s=20161025 header.b=aO4aNy7C; + spf=pass (google.com: best guess record for domain of postmaster@mail-sor-f69.google.com designates 209.85.220.69 as permitted sender) smtp.helo=mail-sor-f69.google.com; + dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=googlemail.com; s=20161025; + h=to:auto-submitted:message-id:date:from:subject:references + :in-reply-to; + bh=XaR1H4XeD+InO7mULPJn53omDGmxN+KG6DbSxyyErPM=; + b=aO4aNy7CUOk9O4Jnsue/DvMFY6Ph0C34AbpoxJH+mLZpOmt/KYGCGYWgunZgamF15U + Vm8JY5yLKGwkTz2m3abDnKNP4fpl6zeZ5fyk5LvXH2Jema0iocHai6pJZBoFGPnonNmd + MscTf1sEltbOxwfOmM1BRHX34c1jW0+8Yd2+Nhg2DPvzuq1brOVin6bUV4VX5EeeuNqT + ZTewjJVPmO/B5NQhdpG81FO5w4hKSQ/VzZXnap2thMf3gOmnaoR+tbsnOIAiklcLdJ7b + 57SKUwI041pwSmh9dffs0STl2GvMRSJyGCtBqMnzXgflqoGTcnPflWgR3LXHM/MIA0q8 + WqRQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:to:auto-submitted:message-id:date:from:subject + :references:in-reply-to; + bh=XaR1H4XeD+InO7mULPJn53omDGmxN+KG6DbSxyyErPM=; + b=iORAzNvXegQ8oSp4RYb/S168muAiBox769seMk49kDBIvXwI+N8P4mUZq/zDi8DmQd + +wlLzVzowQq6EofiSpjOJWT9IC/k8otk15PMGtgHE4BGSSeKn7L30d3ocQS93HzYnLmA + VBlHBdFTKrsfKhe2+CQyCosTDGRpbkQLuRRyhxChEq8ltvaOHgbu1+eCeb9PsPuh6OxH + kvTHJZeA9A+eLOl26pBmqGIWkr7FlYW0wI6YPoEs9WXX5LSFOQs6fm/9l366eIR7IFFI + ihX5LrZl/Cf0lwwYX7fqIMgnHy1K+QnKuEb+dRQGqLbxdIEls9bXIF98iPQVkEWzgSZy + ip8Q== +X-Gm-Message-State: AOAM531ahfHE6oS9/nuni8pNf9bwC+DXAcaLV0owBwNCj9kcTPLCCNhX + W1JNciK0ivEIVB4dgiyLE/5K7iKbEznQhqyG9Bi1QA== +X-Google-Smtp-Source: ABdhPJygljUXswH0ycJyHmXVthi5IjlDvP8QdYlMdHUPKEtgIZeUk69Acti5LnswGhg63T9/L0PuGZGBM5XE5BsP0mMNNDRZyt+DgnE= +X-Received: by 2002:a05:6638:101c:: with SMTP id r28mr2990163jab.84.1591791475516; + Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +Content-Type: multipart/report; boundary="00000000000074432a05a7b9d512"; report-type=delivery-status +To: alice@gmail.com +Received: by 2002:a05:6638:101c:: with SMTP id r28mr3059870jab.84; Wed, 10 Jun + 2020 05:17:55 -0700 (PDT) +Return-Path: <> +Auto-Submitted: auto-replied +Message-ID: <5ee0cf73.1c69fb81.6888.c2f4.GMR@mx.google.com> +Date: Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +From: Mail Delivery Subsystem +Subject: Delivery Status Notification (Failure) +References: +In-Reply-To: +X-Failed-Recipients: assidhfaaspocwaeofi@gmail.com + +--00000000000074432a05a7b9d512 +Content-Type: multipart/related; boundary="000000000000745e0805a7b9d51b" + +--000000000000745e0805a7b9d51b +Content-Type: multipart/alternative; boundary="000000000000745e1705a7b9d51c" + +--000000000000745e1705a7b9d51c +Content-Type: text/plain; charset="UTF-8" + + +** Die Adresse wurde nicht gefunden ** + +Ihre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann. + +Hier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser + +Antwort: + +550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient's email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser h20sor9401601jar.6 - gsmtp + +--000000000000745e1705a7b9d51c +Content-Type: text/html; charset="UTF-8" + + + + + + + + + + + + + + + + +--000000000000745e1705a7b9d51c-- +--000000000000745e0805a7b9d51b +Content-Type: image/png; name="icon.png" +Content-Disposition: attachment; filename="icon.png" +Content-Transfer-Encoding: base64 +Content-ID: + +iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAACXBIWXMAABYlAAAWJQFJUiTwAAAA +GXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABTdJREFUeNrsnD9sFEcUh5+PRMqZ +yA0SPhAUQAQFUkyTgiBASARo6QApqVIkfdxGFJFSgGhJAUIiBaQB0ZIOKVCkwUgURjIg2fxL4kS+ +YDvkbC/388bi8N16Z4/d7J/5PsniuD3fyePP772ZeTsDQRAYQL/UGAJAIEAgQCBAIAAEAgQCBAIE +AkAgyJT3Mv+Eq7vYK8mTE+MDRCAghQECAeRQA5V2ZOpmg5vDx3NPzRbmGRMEcmTrEbNNB8zWfRD+ +f/Efs2e3zCZvMjaksBg27TfbcuSNPEKP9ZyuAQKtHX2O9ncNgWC57umMPKvRNb0GEKgnLoUyxTQC +rcns0/6uIRAs8/hGf9cQCJZpTpjdO2f25/03z+mxntM1eLtsZAgiUtX4JcaBCAQIBAgECARQ8CJa +G5jab4J4pm4WZmO3OALVh802fIwcLkyPkcKAGggAgQCBAIEAgQCBABAIEAjKA/1AnahhbO5FdOOY +VsrrDbPBYcYKgf5D2wLaV3p+22xh1u17tO3S+DTcvxvagUDeivPgx/a/95J/73w7Sj26Hn4pKo2M +ehuV/KyBJM6d0f7k6RKx/R63vvL2tmf/ItDdM2ZTP6f7nkp9Y2fDx1v9akmpIU+KSCLVUghUQfSL +zVKeTklbLxGoctw/nzC5rw8L5KRNbkpnKq6pgSqEClzNnFzY+XnYWrt6VpVk1vbwWvg+RKCKMOUw +Q1LEOXA+/MX3mpJvGDHb265xtnzmFoUK1HaKQGlMtePYM+q2KKjXuaS1NJYIEKgI8jhEgqHt4cqy +Ky53j3hyHz2bqSLp2o2LbJ7MxKovkGqXteoWpaOk96O9/yF/dF7NwlS36AuIQIBA5celQK4PIxBE +4LLzrtoLgaALdSy6CJRkWQCBPGLsTHznomZ9nszUECgJ2ml3WWHe+QVFNPSQx6UdZNtxr9pbEShN +eTTz8mQXHoHSlke7+Z+c9m6VGoHSkEfs/trLW3wQKApN1V3lGfnGu2Z6BFoLtYCs3GWBPAiUCLVh +/HoaeRCoT9R873KLM/IgUBfapnCpe5AHgXry4pf412ihEHkQqCdxd5VqrcezhUIESsJMTJ+Pdthp +Z0WgyNlXXPHc2Mc4IVAELl2Gnh8mhUDvCkfbIVAkcbf/aOoO3fMKhqAD3frTa4quwpn0hUDOkQhI +YYBAgECAQAAU0QlYObl+5Ug8NcprZkZxjUCxRPVA6zmtEXHCBykskrhjgHXN09PoEcgFl4M4H11j +nBAoApcj6ZoPGScEAgTKApcDoTw5sgWB+sGlz1n90IBAPdE6j1o21PfcC11jLagL1oFWRyGlKU3p +OxcSJQ7NZAjkhHp/uG2HFAYIBAgECASAQIBAgECAQAAIBOkxEARBtp9wdVfAMOfIifEBIhCQwgCB +ABAI0oV2jhxZ+nfBatuPZfgBCy0Eqqo8c01b+uu51XZvzOgDWoHNTGR+pCwpLEd5svuAZXlO2uEr +PyEQ8hRWHgRCHmqg0sjTnLalv6crJQ8C/U8stqNO0I4+VZOHFIY8COS1PGL2ybd5yUMKK7s8zYmL +dujyd3n+nESgcsvzZd4/KwIhDwIhT35QA6UyE1qyxZnfvJMHgdKS549JC1qvvJOHFIY8CFR5eV5O +XimqPAhUdHnmfx+zgxdOFXkoqIGKKs/cswnb/8Oeog8HEai48nxUhiFBIORBIOShBioskkbySCLk +IQIhDwIhj28p7FApR6b1qlEbHGpkO/rr6215vi/zH1r2x7tApSGFAQIBAgECAQIBIBAgECAQIBBA +LK8FGADCTxYrr+EVJgAAAABJRU5ErkJggg== +--000000000000745e0805a7b9d51b-- +--00000000000074432a05a7b9d512 +Content-Type: message/delivery-status + +Reporting-MTA: dns; googlemail.com +Arrival-Date: Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +X-Original-Message-ID: + +Final-Recipient: rfc822; assidhfaaspocwaeofi@gmail.com +Action: failed +Status: 5.1.1 +Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does not exist. Please try + 550-5.1.1 double-checking the recipient's email address for typos or + 550-5.1.1 unnecessary spaces. Learn more at + 550 5.1.1 https://support.google.com/mail/?p=NoSuchUser h20sor9401601jar.6 - gsmtp +Last-Attempt-Date: Wed, 10 Jun 2020 05:17:55 -0700 (PDT) + +--00000000000074432a05a7b9d512 +Content-Type: message/rfc822 + +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20161025; + h=mime-version:from:date:message-id:subject:to; + bh=Y1ylbv3YC5frF/LtF2it4tQQ0OVZstDdWqivvggIOB0=; + b=eyr60XbgOrgHoZFpRYzw9WQIR7aEBaYKWhiEcqdnugB+hn0W2KVcTkKiL2C6zSF+jh + l+lM+dNZZTUcMqWx4kVgTVtqwUNea8OUqe+WLqx04ULwdKZn1okbKYovaiavCLKOKDnf + ZP5mNz3Ka/ywpCGoq8rdgnXc7NunnkWeaBpYY/BWOmLU4WNXX8zS7etXXhQE4YPQEJT4 + Sh2o/YIIjDLncJFMyE+25n3tbd2mIoLt4sjaCHE5ibm9w7zojyHM+LDCQ37cM74FEAAa + 88KTn0gSnCFBCfojhfxOH78CpySHG3FFfTlpCefwP2A5J9MQlb6QdSVa9STYSx3IntJ4 + L7Tg== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20161025; + h=x-gm-message-state:mime-version:from:date:message-id:subject:to; + bh=Y1ylbv3YC5frF/LtF2it4tQQ0OVZstDdWqivvggIOB0=; + b=pBL4/bKUDw5E2zo1uR2Tl69h2iTlMgIAcnzQgodPCbU4jZ9kH+F5H9rfbzXCjT06J7 + L72SYpdfgc5fOwM4GhRcdYnyK3wiXQ8ugpL19nbYt2iWo/vRF3GidawXXDGb2GUYpkzX + 1Mz531cy2/HOsmQbUQ7304KV+OUghtcg8eLNnFuhQch7n12Kk3yy3AOzjrLoktcdgIsy + /HxBjyut0Au+A2t6si+PVwTHvC647a0BioeV0tUYLigzu3/jgP9Hb8eRZaXTX5VC6iZi + 9QMH/+rXp05IK7OpGWh22xDpeV8CDkQ2sLFaBhKxtJ+nYoerM64t8EJXBBsVQb18ojGz + pW/A== +X-Gm-Message-State: AOAM5330q6kn/TKataMNEVigNfNdr/xii/PQgHXzJyMbwLvsETlNfLoy + 1rM9JBIGrcHeEDRx4qhZfl5S4bircceU7c3i6Fyn2fRO +X-Google-Smtp-Source: ABdhPJwysG+S90b/g+9mK7LgeHhmJTBowst6JMhL16+a0coTi7P1NVp9jjaNHJfhvhLodYG6eHIvWdbQGJnAP2brEzI= +X-Received: by 2002:a05:6638:101c:: with SMTP id r28mr2990137jab.84.1591791475066; + Wed, 10 Jun 2020 05:17:55 -0700 (PDT) +MIME-Version: 1.0 +From: Deltachat Test +Date: Wed, 10 Jun 2020 14:18:26 +0200 +Message-ID: +Subject: test +To: bob@example.org, assidhfaaspocwaeofi@gmail.com +Content-Type: multipart/alternative; boundary="0000000000006d8d7d05a7b9d5b3" + +--0000000000006d8d7d05a7b9d5b3 +Content-Type: text/plain; charset="UTF-8" + +test + +--0000000000006d8d7d05a7b9d5b3 +Content-Type: text/html; charset="UTF-8" + +
test
+ +--0000000000006d8d7d05a7b9d5b3-- + +--00000000000074432a05a7b9d512-- diff --git a/test-data/message/yahoo_ndn.eml b/test-data/message/yahoo_ndn.eml new file mode 100644 index 000000000..5f88d7497 --- /dev/null +++ b/test-data/message/yahoo_ndn.eml @@ -0,0 +1,100 @@ +X-Atlas-Received: from 10.218.250.153 by atlas222.free.mail.ne1.yahoo.com with http; Wed, 10 Jun 2020 10:11:23 +0000 +Return-Path: <> +Received: from 77.238.177.145 (EHLO sonic314-19.consmr.mail.ir2.yahoo.com) + by atlas222.free.mail.ne1.yahoo.com with SMTPs; Wed, 10 Jun 2020 10:11:23 +0000 +X-Originating-Ip: [77.238.177.145] +Received-SPF: none (domain of sonic314-19.consmr.mail.ir2.yahoo.com does not designate permitted sender hosts) +Authentication-Results: atlas222.free.mail.ne1.yahoo.com; + dkim=pass header.i=@yahoo.com header.s=@bounce; + spf=none smtp.mailfrom=sonic314-19.consmr.mail.ir2.yahoo.com; + dmarc=success(p=REJECT) header.from=yahoo.com; +X-Apparently-To: alice@yahoo.com; Wed, 10 Jun 2020 10:11:23 +0000 +X-YMailISG: RT5ZnycWLDvIW52uqHS_EWNgl31NdJPyLLB2F4SYb1GCAoo9 + pcninuVU5GDMBZykeMT4cSUt4ZqXxS5FdEeWJqtGIAtbEGbIL8Uhcoszqm4m + JuMJiQZwEE7W_fsS_9MUK5gZtMkhKkSnAuaeaOLKNYAwFZdBqA0uEYA5EmVf + EC9J4RGQ4hZvrMqMj_W.cj4pvbEC.pyirLxTfkICuUkZVguYoxG16y1EOJPw + B48fhXvF5ErU7WAHKxyRM3bMOg7b5pXHKn1dtRSVAXEuqBAQrWig1pePpYH1 + wO54sYT7cgmdiFvfLY5rR7YcBzopmKJBycKzBVoRLCY4gvoNyTLPKx9o3AAz + WU4B7TGejDBElYSLpfnyvQg8wU27zzo2IVBZWUNztP0Ca8CQ07Y7TxUZAO.f + DNO5c7nd81PHMRDbSeaw1BTV2Yd9vlBc7syYmwGvtVBJQwRU7qPN.DpFO2jC + 9j9DytVhm5231gdBBRSzW78yG.VvaIdJgq_YViKNM9VxFseTz3Sjt3TaYznP + gAVq.MxpopNsSZf_tedwAhXDWyrjKsRPK.v2ANivmuWGPednniEaMYhxJ05M + _5SnJ.hAU.l6h3HCEfiU.SH390_3tZgYNfxCo4GPPFMfnNPmKa3.rgpChBCz + 9CRexJ8BSFyCEeAhuqQ8vSJfSuittJmXvS6Tk8Rxd9HUJAtKzZ.xCWZQ4tA6 + Yp2aRG23_rK_C6hH8ArkkvbG.uVQTt6DltSX6avJLObBfIhBH0x64RoFjGee + vYXxM741Okm0jH7r79c8GhnAwas_bwfkaTW9e1nhYP0eyI36z_QwLYgOH3Mm + LrUcejpOMDR60QWDuDyRbWXOJdr3Q2K0ERhuAy6YnINq0sL3HX7t5wjsFLvp + _7Ri_eruTfIst4C7DZwERwui6aDSEAdF1Z8oZukBVmiyZsHmhJQCUik646iy + 3ASMR3lX7R3q2PBHQo2oC3qte8Fzz1FhKoMtfCGtIpeCazlkhDEJ6eTBSQ3R + Pe7M_GPiv3QNp7qu5CWHlzy6hWEKIkNwx.WRGYzfxkyJMmJm4UrhQYUfa4lG + Wb8n.mfYnS_KGYtzyRFNqAL0IGo.1MB9aG6qQk456Fz9GJgbHLWrMXVtyfrr + Uo7mKih8FCrdUKv5X6KBnpY0vvyoH5jrWyrvo3DW0bq_JvZ9U51JwUhoGY5U + c1t.yCSJbs8tnrGZHuUTOvouWzpCAJsk34AqRyH0wDJZQsAwBW5UZ3jx8ARA + FicoSqZCa4wEP9WaaXvfzFbmLW0- +X-Originating-IP: [77.238.177.145] +Received: from 10.217.135.165 (EHLO sonic314-19.consmr.mail.ir2.yahoo.com) (77.238.177.145) + by mta4277.mail.ne1.yahoo.com with SMTPS; Wed, 10 Jun 2020 10:11:21 +0000 +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=bounce; t=1591783879; bh=4BmZzBC/nu0AJ9r0i0xNuCENks2KZcuXCbjSHdzbg9Y=; h=Date:From:To:Subject:From:Subject; b=lPxu8goOGOLVgnwbndfdptZ7zI5VEo0lSSr+ONGxwdtuhrySKDU6Sp41/g6jWbAiVPT1947j/B5wOlPfa5tv4XkWrGf0JCbT1I20ZJIkNfNwt4F0qPnbJAiHFIDPxcY68utjC9IgPWJd0cGqJNXbFwbJBu88rtrbMoInzLakh5I= +Received: from sonic.gate.mail.ne1.yahoo.com by sonic314.consmr.mail.ir2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:11:19 +0000 +Date: Wed, 10 Jun 2020 10:11:19 +0000 +From: MAILER-DAEMON@yahoo.com +To: alice@yahoo.com +Message-ID: <1713051795.39992.1591783879940@sonic314.consmr.mail.ir2.yahoo.com> +Subject: Failure Notice +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit +Content-Length: 3347 + +Sorry, we were unable to deliver your message to the following address. + +: +554: delivery error: dd Not a valid recipient - atlas117.free.mail.ne1.yahoo.com + +--- Below this line is a copy of the message. + +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1591783876; bh=kXD6TZuQDjqZf/AEAJ2HCX32Titkj3IywytG6GSm4yQ=; h=Date:From:To:Subject:References:From:Subject; b=PexnIBxnVSkyutv/jVn+Wlt5QPuVHnWleP3baWlvqkXaKR51pCaZIoGJggMEonitEeJkcYpgplBawEBz0hlGf63NqOHHkxUk6U1olwc0y9kj5kDH5lrORgXrf7U4z5t+i5n0II36MxbG9n/5tDRXoiabLFoWx//3O9x/ZJvVWPlq8RBFzVG8aoL2TkBQAVcqX/vW1f3WJuopaUYWB4AzR3TyuC2kVQPFqbPMk+G/VmyuZFmZesh1bSBva5hdKYLxES5v8hvTIDRqSYZrnZ4V67MqicZ8m229Xf4Za8qOE+a2Z+Vv5VrQ+CjjPZwRAcmKHkLY80VCSkpeL2R2YG4APg== +X-YMail-OSG: 4spnw98VM1k_g51CM6oepdNEMiPFRtZ0ZG_zOBGIlhcNvS1mkzr8l8VTB0CY_Q0 + dR52ikl7QVYESerRQgcGqBfLwKpem7i1XSrCl2HuyHeWzF6Gu5MqFPMCak.v8GyDXNO075NEwNt1 + i18CJ29cEjiHthoamgmj0oqerAglglKRhTuuAFy4wUmZZm7VyvaW4wHUD1g7DeWGijQsCglSYMUK + CmoFcKsWOZBSYPMkp7iRwUp52pXHFin3qf4uQ27K_Sh.6s7KLAfWVkV7L_5AR3MyCPAVzm71.1yG + G7Vy5HSBgGMQ90B7VbcjOkCg3F4JNl4Z_P2ejV1KZ.tNoPLgO.FmsfFy1OXBGf3m2mDmRcuEO4K2 + mTRhsjZf.2iiWpx02b3tY.oUtYrIBXBVIFPbTB9sBMn_9Z_qdVmO3gjD6gCPEBzuVvEO0eZIrgaw + EDTZt8Z9tSRDm1.4gV8LWQBYShF7XuMV0togiLYIO8s_iTHcTbhKhPlwxP.mxr06xcx_9kzReVTL + 9lB1FkB5Jm0WccWHGhLBqeMjGDoaNqPxLqJ.1tI58tLXsPoR6m1NFVEdzI1G.4AVBeXZ_9BjgUhm + KY33sEg.GwIjUlWWWuSyRZ1q1K2nqi1z29wH2R1Glmdmx0lyqfMg9Xe8HV7YZu2CuZ8SlDLLB.rX + NU4PwMsNfU6pK2HejQPsJuyOlI5Q824rXRF5xTLYKsYcQptoFXyLe6MXKW1ThBLQV2nWYDRs_V.e + SBmt22TfuOwu4Y5ju0sXmztZ8zpiIC8_rnAa5bVBEHxzkic64UZdukDX9V12Pk3G2sGYRyPTH472 + wBX33JpDuq6BtrKr4FXjCLeVppARTHpiKM0jHMjmNf1bF0TvrcCsC9zAYtitAqgcGZNFETNuV3KM + 57XifdDEwUPOuww0ApSWO.iwP2POvIRBVlrxdgA8MbLmuuX4UxNCw23z1f7MVY6F3L60LUrX5GZO + aKaMmD1XTzx32J6c_TUmyuViT5vphqpEooTzHG2X7ALb4xC8yHlE4wDKyaEDARZ.8P2lO9T18oCz + OQvJjwDaLOkeAmo23yRMn70bYJK3tP9Z5cS1C0TE8PEtz4sd1syQUIZZ2g8JG_AQcE4lUZSZlIKN + AHjB8h8Uin35zKe0Le1DBjdQUmpgAETlmYE7V0nJDEmagB3dtpbokgRBuuBfhXlFpxHcnAmBFFFm + XOSLWEPnmxu2o8CCjjz3QUBy2fr3EI_D2VFpy..MuZgRwtES.l24m_95xtQxI28R4SWZN6LsS_rr + 1S33BJCCCAfXtCAFzCfz5.qSzHRYbLdY5do6yKj0pPLQTUTjlMwmCUGPcSJhsyxkkEVIK1W_Z16R + ZRls- +Received: from sonic.gate.mail.ne1.yahoo.com by sonic314.consmr.mail.ir2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:11:16 +0000 +Date: Wed, 10 Jun 2020 10:11:12 +0000 (UTC) +From: Delta Chat Test +To: "haeclirth.sinoenrat@yahoo.com" +Message-ID: <1680295672.3657931.1591783872936@mail.yahoo.com> +Subject: test +MIME-Version: 1.0 +Content-Type: multipart/alternative; + boundary="----=_Part_3657930_145367320.1591783872935" +References: <1680295672.3657931.1591783872936.ref@mail.yahoo.com> +X-Mailer: WebService/1.1.16072 YMailNorrin Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0 +Content-Length: 494 + +------=_Part_3657930_145367320.1591783872935 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 7bit + +test + +------=_Part_3657930_145367320.1591783872935 +Content-Type: text/html; charset=UTF-8 +Content-Transfer-Encoding: 7bit + +
test
+------=_Part_3657930_145367320.1591783872935-- From bde97b20e928af5f05a2a7c33c0b79d3e4fdcbdf Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 15:27:20 +0200 Subject: [PATCH 18/37] Repair getting x-failed-recipients header, all tests passing now --- src/dc_receive_imf.rs | 35 +++++------------------------------ src/mimeparser.rs | 2 +- src/test_utils.rs | 11 ++++++----- 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 6bf07bf82..a1e14a3dc 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1779,7 +1779,7 @@ mod tests { use crate::chat::ChatVisibility; use crate::chatlist::Chatlist; use crate::message::Message; - use crate::test_utils::{configured_offline_context, dummy_context}; + use crate::test_utils::*; #[test] fn test_hex_hash() { @@ -2380,19 +2380,7 @@ mod tests { raw_ndn: &[u8], error_msg: &str, ) { - let t = dummy_context().await; - t.ctx - .set_config(Config::Addr, Some(self_addr)) - .await - .unwrap(); - t.ctx - .set_config(Config::ConfiguredAddr, Some(self_addr)) - .await - .unwrap(); - t.ctx - .set_config(Config::Configured, Some("1")) - .await - .unwrap(); + let t = configured_offline_context_with_addr(self_addr).await; dc_receive_imf( &t.ctx, @@ -2429,26 +2417,14 @@ mod tests { #[async_std::test] async fn test_parse_ndn_group_msg() { - let t = dummy_context().await; - t.ctx - .set_config(Config::Addr, Some("alice@gmail.com")) - .await - .unwrap(); - t.ctx - .set_config(Config::ConfiguredAddr, Some("alice@gmail.com")) - .await - .unwrap(); - t.ctx - .set_config(Config::Configured, Some("1")) - .await - .unwrap(); + let t = configured_offline_context_with_addr("alice@gmail.com").await; dc_receive_imf( &t.ctx, b"From: alice@gmail.com\n\ To: bob@example.org, assidhfaaspocwaeofi@gmail.com\n\ Subject: foo\n\ - Message-ID: \n\ + Message-ID: \n\ Chat-Version: 1.0\n\ Chat-Group-ID: abcde\n\ Chat-Group-Name: foo\n\ @@ -2477,12 +2453,10 @@ mod tests { assert_eq!(msg.state, MessageState::OutFailed); let msgs = chat::get_chat_msgs(&t.ctx, msg.chat_id, 0, None).await; - println!("Loading {}…", msg.chat_id); let last_msg = Message::load_from_db(&t.ctx, *msgs.last().unwrap()) .await .unwrap(); - assert_eq!(last_msg.from_id, DC_CONTACT_ID_INFO); assert_eq!( last_msg.text, Some( @@ -2494,5 +2468,6 @@ mod tests { .await, ) ); + assert_eq!(last_msg.from_id, DC_CONTACT_ID_INFO); } } diff --git a/src/mimeparser.rs b/src/mimeparser.rs index f895212b9..1b7ca48b6 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -876,7 +876,7 @@ impl MimeMessage { .and_then(|v| parse_message_id(&v).ok()) { let mut to_list = get_all_addresses_from_header(&report.headers, |header_key| { - header_key == "X-Failed-Recipients" + header_key == "x-failed-recipients" }); let to = if to_list.len() == 1 { Some(to_list.pop().unwrap()) diff --git a/src/test_utils.rs b/src/test_utils.rs index 9724252a5..1502b1ccf 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -41,13 +41,14 @@ pub(crate) async fn dummy_context() -> TestContext { } pub(crate) async fn configured_offline_context() -> TestContext { + configured_offline_context_with_addr("alice@example.org").await +} + +pub(crate) async fn configured_offline_context_with_addr(addr: &str) -> TestContext { let t = dummy_context().await; + t.ctx.set_config(Config::Addr, Some(addr)).await.unwrap(); t.ctx - .set_config(Config::Addr, Some("alice@example.org")) - .await - .unwrap(); - t.ctx - .set_config(Config::ConfiguredAddr, Some("alice@example.org")) + .set_config(Config::ConfiguredAddr, Some(addr)) .await .unwrap(); t.ctx From c827c9d209e47508ad929df2c4983c703a773cd1 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Wed, 10 Jun 2020 15:43:38 +0200 Subject: [PATCH 19/37] Add yahoo test --- src/dc_receive_imf.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index a1e14a3dc..2aee485df 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2337,6 +2337,18 @@ mod tests { ); } + #[async_std::test] + async fn test_parse_ndn_yahoo() { + test_parse_ndn( + "alice@yahoo.com", + "haeclirth.sinoenrat@yahoo.com", + "1680295672.3657931.1591783872936@mail.yahoo.com", + include_bytes!("../test-data/message/yahoo_ndn.eml"), + "Failure Notice – Sorry, we were unable to deliver your message to the following address.\n\n:\n554: delivery error: dd Not a valid recipient - atlas117.free.mail.ne1.yahoo.com" + ) + .await; + } + #[async_std::test] async fn test_parse_ndn_gmail() { test_parse_ndn( From 20ad98d168347ac30264af2109c84465f3a60b7b Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 10:52:55 +0200 Subject: [PATCH 20/37] typo --- src/dc_receive_imf.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 2aee485df..34d03dc10 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -406,12 +406,12 @@ async fn add_parts( .unwrap_or_default(); if chat_id.is_unset() { - // check if the message belongs to a mailing list + // check if the message belongs to an NDN if mime_parser.failed_msg.is_some() { *chat_id = ChatId::new(DC_CHAT_ID_TRASH); info!( context, - "Message belongs to an NDN list and is not shown in a chat.", + "Message belongs to an NDN and is not shown in a chat.", ); } } From 7997e7dde4d2f6c2149b4ea9109d65df1af84aaf Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 11:03:52 +0200 Subject: [PATCH 21/37] remove println --- src/dc_receive_imf.rs | 1 - src/message.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 34d03dc10..6c17d4043 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2459,7 +2459,6 @@ mod tests { .await .unwrap(); - println!("Loading msg {}…", msg_id); let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap(); assert_eq!(msg.state, MessageState::OutFailed); diff --git a/src/message.rs b/src/message.rs index 83510a87d..785307adf 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1281,7 +1281,6 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option { error!(context, "{:?}", e); - println!("{:?}", e) } } } From 995660020b9096f74efd25992762e9c90211c24f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 12:28:20 +0200 Subject: [PATCH 22/37] rm unused aol_ndn.eml (aol's ndns are very similar to these of Yahoo) --- test-data/message/aol_ndn.eml | 100 ---------------------------------- 1 file changed, 100 deletions(-) delete mode 100644 test-data/message/aol_ndn.eml diff --git a/test-data/message/aol_ndn.eml b/test-data/message/aol_ndn.eml deleted file mode 100644 index d0f5188b8..000000000 --- a/test-data/message/aol_ndn.eml +++ /dev/null @@ -1,100 +0,0 @@ -X-Atlas-Received: from 10.218.248.40 by atlas207.aol.mail.ne1.yahoo.com with http; Wed, 10 Jun 2020 10:42:33 +0000 -Return-Path: <> -Received: from 74.6.131.123 (EHLO sonic311-13.consmr.mail.bf2.yahoo.com) - by atlas207.aol.mail.ne1.yahoo.com with SMTPs; Wed, 10 Jun 2020 10:42:33 +0000 -X-Originating-Ip: [74.6.131.123] -Received-SPF: none (domain of sonic311-13.consmr.mail.bf2.yahoo.com does not designate permitted sender hosts) -Authentication-Results: atlas207.aol.mail.ne1.yahoo.com; - dkim=pass header.i=@yahoo.com header.s=@bounce; - spf=none smtp.mailfrom=sonic311-13.consmr.mail.bf2.yahoo.com; - dmarc=success(p=REJECT) header.from=yahoo.com; -X-Apparently-To: deltachattestac@aol.com; Wed, 10 Jun 2020 10:42:33 +0000 -X-YMailISG: DkLFz_oWLDvt4_NIgCwKD1jZui63WnISNmlXQ_XYR2MqQH9y - Sa__GenYvUZEmGPWcZU0SLRtkdYKB66hm6jbzx7Pw4j6es6aXyOHs91T5xeW - Bvqm5IjytmXBG.ELVw0MjCKEPx36Wr5pptHuryDWttC8.qeN9w_SZy1kXtkE - vJDjXD1IIMZ1XpywJyBYu3Ld3AKkTd0mU3V7wbq3LY8A3dsgO7Gv8Doq4PyJ - 6DxK2NqUp.GOAjj_9pH97OFJCeUCjc.dlEVPbrvfBUPimoluyG00EnyyyhjL - KnDZiAZnCVUA9H2lfM0uWqNCF7CowDoehVecVHpiLJ7Xl415wQjOjWSTzatA - Buh2hsSQDbpPRLZbjnY0B4sC1vMKnCm3B2P04KYEWs7W_m_Ysvtidkg1SyKR - vsm8UDlDfLFSNtaE6LuxkgK90hVfM3qHXpnAPnUkB626ucgZAJDvXMg3q_S. - rMOcm0e5LPVON_LjqMSefreahzGebN88_klofvxDaBm7EZIFd933_EWrJ1yZ - P_hp5lPTaYmFTuukp8UR9ZfwVCbz6FmUzQwbNvGsmWgI2mVxgGgCay4OJKOk - gyTyQXzDGitU82HsLfgpIricWWdou7tlkwUQXv2w6p1.QbmbZ628n5xiN2jF - EQOqz9GHSdN4YPDGzbd2QrqkWWSXWcP4TRoFJMvPEnxwgqN4BrCMY52x2koF - Fj4Lm65pq26I7ErlHpYU4bN5Y2CbYZN5ppWtqalyMX167S8mDTF0vkW.0aqa - nLNu38OSqRfUqRPPQ7AQn3E14fcFq0pzxHANEVRzXKvEYhPOBu_90NxxamxU - G.eFig8PQFQIzOZwzN7KreILICiMNeZxRDoJdT5ouFy6t5fdNUYB_ee5byqg - wQxFpGY1oqjqnF8cKhoqXKbewhXnAHtruHmJctwcDFB6Z8Ky3trGEHXeFKUm - GDXN6bh1VT2YLVcWEmfzO3F.4zVSYcpsDkJD_a8_ywFNwxs.cXyhZyba4x7Y - 3X_XjCes4rCDftjcZuVBMiX3KYZNX.oooDLZBmsb3P.j1FQ8XIurzueTrFpE - O_dhyhgI.hOo8BweGv3a89eFdBCyhU1o7cEGK.mrU1sj3kX6d4FhfHmA8cGv - n50B5b94d3MpWSnSDFldjz0i2Jun6VUVYuG3yFqtsrf7ZnaTuxswub9SrhbO - mF02jK6oxTIWYUZEU8vgvciXeiS_YdSmJ1tzbeWJRFeo6ePbTbcZGmY- -X-Originating-IP: [74.6.131.123] -Received: from 10.220.180.155 (EHLO sonic311-13.consmr.mail.bf2.yahoo.com) (74.6.131.123) - by mta4011.aol.mail.ne1.yahoo.com with SMTPS; Wed, 10 Jun 2020 10:42:32 +0000 -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=bounce; t=1591785751; bh=iNhZ8sZ9ZQS8RKoDRTbDsAW/YGN71KVQTVc/Xecb9UQ=; h=Date:From:To:Subject:From:Subject; b=IEjn12+yP0ddLWLojXRLLBx545x7trCIcmMiPuKViBb+UBCAT568e0nmwukVqF6FfeR4hcmWqISlyR22409sOckSZmf0+Fj3rgeaFAmhrl1l4P1uEdNSB4dMH3gcHxAN3DdTyUBQss2ZIyu7xnYJguCadQ1/1ELa865EtJJAkes= -Received: from sonic.gate.mail.ne1.yahoo.com by sonic311.consmr.mail.bf2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:42:31 +0000 -Date: Wed, 10 Jun 2020 10:42:31 +0000 -From: MAILER-DAEMON@yahoo.com -To: deltachattestac@aol.com -Message-ID: <1266721401.228154.1591785751559@sonic311.consmr.mail.bf2.yahoo.com> -Subject: Failure Notice -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bit -Content-Length: 3322 - -Sorry, we were unable to deliver your message to the following address. - -: -550: 5.1.1 : Recipient address rejected: User unknown in virtual mailbox table - ---- Below this line is a copy of the message. - -DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1591785750; bh=4ktMNgiiY0GHVCUgIv4TvXVESetaS2esyta25tCU5Rg=; h=Date:From:Reply-To:To:Subject:References:From:Subject; b=HLpgexVrsHu1BSnI+l+ob6hCyl2HRO3xPCLRg090QIR1LwMtMbccdjSSi6o17Qx1E/6Y0YHqHgDq+/vGxXZ72GyxHfimpHWYxfjhpgbuXxCbPZkcPejE1kjsR0LHLZ0lmHPuZYbY6pdpROfQC3jOwL616p0vhqZ4QwSTsQhmOBgydA85uIvTWqzjra0GNY5oS8k9CwSmE2N8bRPmEmZzkPytV2RimpEwylCy7IiJ7S6EURnyjxMO5uaZukNjh/XJLxzEEo1ief0EeYfYuq3BPTKHJf7FqV6Dzqu7bIbowVWBTTJ7eFAPUcDwoum5Yz5H63gp5ZFhghV0tDcAjSzOIA== -X-YMail-OSG: XrOprp8VM1l6O.1AuZ5z4b5aOZ5xPHdr1b50c6CBHbn7lnLF9ZdsolbJdKegkJi - NAXKKEdjXM4834uHoJ0tQijRGfPO2pZ8Ie0fgORrev_T1z0c9cmt92vSh2eH2CL3wpaY3nJBQqjL - XxcC3E7cmThUGmPXMCc8O6hYBtGJyyw0lFvegOkgNkIZ.VdHcMyCXoqzrLrTUx1AVI8j_5l7J_iL - wbrGBndP484r_S04WrvzM_i1yRg.Zl01q5o17SjS2vKn2mlLhZhNtBR1RyM9HmoZcEpOW0QesDHm - BLYBeag8wczZJBA6xuAVgLTwCkMHRCRqFMfb.22mpfY6HTwOP3EsG5.we8Ywe.7mSIVhfjozg9Bm - BR3qGGHKD7tJR4X8RFE.tRrnaJS_pUZ1frkJcxEpiau9VFvbTHm5QDltb5gLJUKcj1axNQcPOXF5 - 9lCbo04.yHhjrh.nBk0YmVAYR4.CtpnlgxFdB_ylCqy7cAVukViqvvYBE90PhmT2B8OZBK3LE8De - jvDIDmkyEe4vu6uE7AAlP.vOi5fFEtkGkGsI46uvUARICijKiIfVA5k7XeN3Ahz0Eil05w.kWPYv - SgA8r39ZLclSnGTn.bT5lz8toogaE.GeGz_ChdKT5MD9.1VFZVM1ir2RipJO1XPbBXGB2eWtTmje - WiuXY4ydHo.FusM7VREfyxfo7cUIFlcNwidJGSKYG3YQbj8Gx3ZFDBzW2rOqRhXLWNMbA4owKTiZ - FtcZTwSiGZvUefyMf0c_FWTLdgz.ZNyuDnMEqdAymAxX9vlTtA7pY8EPPC3TwHFG6Zrk2w_UA7Wv - mxfZbbCz26O4_1CnByCh1YBbb8ijWLCq3ZjnNcHSwdSZMpuysG3hAd42R.xNHM.W69WS6m0LnwQj - cnaoTVl6T1Me5EkWX7Z8i75nhIwV1csc74lFgb_.5uDjRKFjmA3KUu5UWDCiWjjWqEeMf6Fsl1nQ - ltXet3ZdssaDjmXfMncHv4Qz7nmH4z_QYovap4SApHUQjPgPPVZHsofmikIugjtzeXqM4OFN0xjZ - 0GzjH9W4EqGlWY29nwPOswrB429jvMHA5R.mBTS6mUBmYm924n4v9yJ2TUTOy4Vh.65Ngd8AsGgm - 75u125bogA5MKHMPGfWpnrys9lCyq3mmhtkkc58R3PYfX0iBXjdP7diVMQhjGgqZMPBbDhDzbECx - mlgcqfqVGwyOmWmKe0OUFjyMVxYV9DwucWIKA.sd02NWEZhDzoQ3CHkaedi3i3YAePx9jbNnNIuo - MY.d8jQDDBQxMtPcece79VtoHLAjwKNT5cSzlvpgJHNtVyOpWjOQ- -Received: from sonic.gate.mail.ne1.yahoo.com by sonic311.consmr.mail.bf2.yahoo.com with HTTP; Wed, 10 Jun 2020 10:42:30 +0000 -Date: Wed, 10 Jun 2020 10:42:27 +0000 (UTC) -From: Delta Chat Test -Reply-To: Delta Chat Test -To: "hsnaeirternaeiho@testrun.org" -Message-ID: <1772450882.1447284.1591785747540@mail.yahoo.com> -Subject: test -MIME-Version: 1.0 -Content-Type: multipart/alternative; - boundary="----=_Part_1447283_353296880.1591785747539" -References: <1772450882.1447284.1591785747540.ref@mail.yahoo.com> -X-Mailer: WebService/1.1.16072 aolwebmail Mozilla/5.0 (X11; Linux x86_64; rv:77.0) Gecko/20100101 Firefox/77.0 -Content-Length: 418 - -------=_Part_1447283_353296880.1591785747539 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 7bit - -test -------=_Part_1447283_353296880.1591785747539 -Content-Type: text/html; charset=UTF-8 -Content-Transfer-Encoding: 7bit - - -
test
- -------=_Part_1447283_353296880.1591785747539-- From 8938cb257315887dcfb6b3ff85f29ca0990cab82 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 12:30:23 +0200 Subject: [PATCH 23/37] clippy --- src/mimeparser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 1b7ca48b6..b9fe3792d 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -939,7 +939,7 @@ impl MimeMessage { context: &Context, from_id: u32, sent_timestamp: i64, - parts: &Vec, + parts: &[Part], ) { for report in &self.reports { for original_message_id in From dd3f81a556334d4dc79b43bcf6a48a41290b3a6f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 13:18:19 +0200 Subject: [PATCH 24/37] Oops, add FAILED_SENDING_TO to deltachat.h --- deltachat-ffi/deltachat.h | 1 + 1 file changed, 1 insertion(+) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 6cf0b895b..6316cb94c 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4429,6 +4429,7 @@ void dc_event_unref(dc_event_t* event); #define DC_STR_UNKNOWN_SENDER_FOR_CHAT 72 #define DC_STR_SUBJECT_FOR_NEW_CONTACT 73 #define DC_STR_COUNT 73 +#define FAILED_SENDING_TO 74 /* * @} From c60ec00aac262035d59fc0844729206bd367b776 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 13:40:37 +0200 Subject: [PATCH 25/37] Oops #2, adapt DC_STR_COUNT in deltachat.h --- deltachat-ffi/deltachat.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 6316cb94c..9a84c85f7 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4428,9 +4428,10 @@ void dc_event_unref(dc_event_t* event); #define DC_STR_WELCOME_MESSAGE 71 #define DC_STR_UNKNOWN_SENDER_FOR_CHAT 72 #define DC_STR_SUBJECT_FOR_NEW_CONTACT 73 -#define DC_STR_COUNT 73 #define FAILED_SENDING_TO 74 +#define DC_STR_COUNT 74 + /* * @} */ From ffb6a84b1f935b6fdeb3cf874eb8c87bda487bdf Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 14:04:42 +0200 Subject: [PATCH 26/37] Warn instead of error --- src/chat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chat.rs b/src/chat.rs index 88611dceb..dfe1c4a98 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2797,7 +2797,7 @@ pub(crate) async fn add_info_msg(context: &Context, chat_id: ChatId, text: impl rfc724_mid, ] ).await { - error!(context, "Could not add info msg: {}", e); + warn!(context, "Could not add info msg: {}", e); return; } From 8ebce0c8612adb7497dc6f63ca7fbb550c4fa9fc Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 11 Jun 2020 15:41:22 +0200 Subject: [PATCH 27/37] warn instead of error --- src/message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/message.rs b/src/message.rs index 785307adf..ad6d5027b 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1280,7 +1280,7 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option { - error!(context, "{:?}", e); + warn!(context, "{:?}", e); } } } From 990c80cedf76ba66cfed6ed15bdc999c447c3ccc Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 12 Jun 2020 10:00:05 +0200 Subject: [PATCH 28/37] lots of small fixes from the reviews --- deltachat-ffi/deltachat.h | 2 +- src/message.rs | 9 +++++++-- src/mimeparser.rs | 4 +++- src/sql.rs | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 9a84c85f7..959b44d05 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -4428,7 +4428,7 @@ void dc_event_unref(dc_event_t* event); #define DC_STR_WELCOME_MESSAGE 71 #define DC_STR_UNKNOWN_SENDER_FOR_CHAT 72 #define DC_STR_SUBJECT_FOR_NEW_CONTACT 73 -#define FAILED_SENDING_TO 74 +#define DC_STR_FAILED_SENDING_TO 74 #define DC_STR_COUNT 74 diff --git a/src/message.rs b/src/message.rs index ad6d5027b..c54c21462 100644 --- a/src/message.rs +++ b/src/message.rs @@ -769,7 +769,7 @@ impl MessageState { MessageState::OutPreparing | MessageState::OutPending | MessageState::OutDelivered - | MessageState::OutMdnRcvd => true, + | MessageState::OutMdnRcvd => true, // OutMdnRcvd can still fail because it could be a group message and only some recipients failed. _ => false, } } @@ -1328,7 +1328,10 @@ pub async fn mdn_from_ext( if let Ok((msg_id, chat_id, chat_type, msg_state)) = res { let mut read_by_all = false; - if msg_state != MessageState::OutMdnRcvd && msg_state != MessageState::OutFailed { + if msg_state == MessageState::OutPreparing + || msg_state == MessageState::OutPending + || msg_state == MessageState::OutDelivered + { let mdn_already_in_table = context .sql .exists( @@ -1391,6 +1394,8 @@ pub async fn mdn_from_ext( None } +/// Marks a message as failed after an ndn (non-delivery-notification) arrived. +/// Where appropriate, also adds an info message telling the user which of the recipients of a group message failed. pub(crate) async fn ndn_from_ext( context: &Context, failed: &FailedMsg, diff --git a/src/mimeparser.rs b/src/mimeparser.rs index b9fe3792d..8d864c226 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -933,7 +933,9 @@ impl MimeMessage { None } - /// Handle reports (only MDNs for now) + /// Handle reports + /// (MDNs = Message Disposition Notification, the message was read + /// and NDNs = Non delivery notification, the message could not be delivered) pub async fn handle_reports( &self, context: &Context, diff --git a/src/sql.rs b/src/sql.rs index 5c54e6f68..a0c26e6e9 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -1242,7 +1242,7 @@ async fn open( sql.set_raw_config_int(context, "dbversion", 63).await?; } if dbversion < 64 { - info!(context, "[migration] v63"); + info!(context, "[migration] v64"); sql.execute( "ALTER TABLE msgs ADD COLUMN error TEXT DEFAULT '';", paramsv![], From adf4035775247b1f0fbf29b43115a343376ef16f Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 12 Jun 2020 10:05:45 +0200 Subject: [PATCH 29/37] rename reports --- src/dc_receive_imf.rs | 4 ++-- src/message.rs | 4 ++-- src/mimeparser.rs | 41 ++++++++++++++++++++++------------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 6c17d4043..eea482ead 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -407,7 +407,7 @@ async fn add_parts( if chat_id.is_unset() { // check if the message belongs to an NDN - if mime_parser.failed_msg.is_some() { + if mime_parser.failure_report.is_some() { *chat_id = ChatId::new(DC_CHAT_ID_TRASH); info!( context, @@ -648,7 +648,7 @@ async fn add_parts( let sent_timestamp = *sent_timestamp; let is_hidden = *hidden; let chat_id = *chat_id; - let is_mdn = !mime_parser.reports.is_empty(); + let is_mdn = !mime_parser.mdn_reports.is_empty(); // TODO: can this clone be avoided? let rfc724_mid = rfc724_mid.to_string(); diff --git a/src/message.rs b/src/message.rs index c54c21462..589c9adc2 100644 --- a/src/message.rs +++ b/src/message.rs @@ -14,7 +14,7 @@ use crate::error::{ensure, Error}; use crate::events::Event; use crate::job::{self, Action}; use crate::lot::{Lot, LotState, Meaning}; -use crate::mimeparser::{FailedMsg, SystemMessage}; +use crate::mimeparser::{FailureReport, SystemMessage}; use crate::param::*; use crate::pgp::*; use crate::stock::StockMessage; @@ -1398,7 +1398,7 @@ pub async fn mdn_from_ext( /// Where appropriate, also adds an info message telling the user which of the recipients of a group message failed. pub(crate) async fn ndn_from_ext( context: &Context, - failed: &FailedMsg, + failed: &FailureReport, error: Option>, ) { if failed.rfc724_mid.is_empty() { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 8d864c226..b19de3c2d 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -54,8 +54,8 @@ pub struct MimeMessage { pub message_kml: Option, pub(crate) user_avatar: Option, pub(crate) group_avatar: Option, - pub(crate) reports: Vec, - pub(crate) failed_msg: Option, + pub(crate) mdn_reports: Vec, + pub(crate) failure_report: Option, } #[derive(Debug, PartialEq)] @@ -178,13 +178,13 @@ impl MimeMessage { signatures, gossipped_addr, is_forwarded: false, - reports: Vec::new(), + mdn_reports: Vec::new(), is_system_message: SystemMessage::Unknown, location_kml: None, message_kml: None, user_avatar: None, group_avatar: None, - failed_msg: None, + failure_report: None, }; parser.parse_mime_recursive(context, &mail).await?; parser.heuristically_parse_ndn().await; @@ -357,7 +357,7 @@ impl MimeMessage { // just have send a message in the subject with an empty body. // Besides, we want to show something in case our incoming-processing // failed to properly handle an incoming message. - if self.parts.is_empty() && self.reports.is_empty() { + if self.parts.is_empty() && self.mdn_reports.is_empty() { let mut part = Part::default(); part.typ = Viewtype::Text; @@ -557,7 +557,7 @@ impl MimeMessage { match mail.ctype.params.get("report-type").map(|s| s as &str) { Some("disposition-notification") => { if let Some(report) = self.process_report(context, mail)? { - self.reports.push(report); + self.mdn_reports.push(report); } // Add MDN part so we can track it, avoid @@ -572,7 +572,7 @@ impl MimeMessage { } Some("delivery-status") => { if let Some(report) = self.process_delivery_status(context, mail)? { - self.failed_msg = Some(report); + self.failure_report = Some(report); } // Add all parts (in fact, AddSinglePartIfKnown() later check if @@ -861,7 +861,7 @@ impl MimeMessage { &self, context: &Context, report: &mailparse::ParsedMail<'_>, - ) -> Result> { + ) -> Result> { // parse as mailheaders if let Some(original_msg) = report .subparts @@ -884,7 +884,7 @@ impl MimeMessage { None // We do not know which recipient failed }; - return Ok(Some(FailedMsg { + return Ok(Some(FailureReport { rfc724_mid: original_message_id, failed_recipient: to.map(|s| s.addr), })); @@ -909,7 +909,7 @@ impl MimeMessage { .get(HeaderDef::From_)? .to_ascii_lowercase() .contains("daemon") - && self.failed_msg.is_none() + && self.failure_report.is_none() { for line in self .parts @@ -922,7 +922,7 @@ impl MimeMessage { } if let Some(c) = RE.captures(line) { if let Ok(original_message_id) = parse_message_id(&c[1]) { - self.failed_msg = Some(FailedMsg { + self.failure_report = Some(FailureReport { rfc724_mid: original_message_id, failed_recipient: None, }) @@ -943,7 +943,7 @@ impl MimeMessage { sent_timestamp: i64, parts: &[Part], ) { - for report in &self.reports { + for report in &self.mdn_reports { for original_message_id in std::iter::once(&report.original_message_id).chain(&report.additional_message_ids) { @@ -956,7 +956,7 @@ impl MimeMessage { } } - if let Some(original_message_id) = &self.failed_msg { + if let Some(original_message_id) = &self.failure_report { let error = parts.iter().find(|p| p.typ == Viewtype::Text).map(|p| { let msg = &p.msg; match msg.find("\n--- ") { @@ -1024,7 +1024,7 @@ pub(crate) struct Report { } #[derive(Debug)] -pub(crate) struct FailedMsg { +pub(crate) struct FailureReport { pub rfc724_mid: String, pub failed_recipient: Option, } @@ -1519,7 +1519,7 @@ Disposition: manual-action/MDN-sent-automatically; displayed\n\ ); assert_eq!(message.parts.len(), 1); - assert_eq!(message.reports.len(), 1); + assert_eq!(message.mdn_reports.len(), 1); } /// Test parsing multiple MDNs combined in a single message. @@ -1599,7 +1599,7 @@ Disposition: manual-action/MDN-sent-automatically; displayed\n\ ); assert_eq!(message.parts.len(), 2); - assert_eq!(message.reports.len(), 2); + assert_eq!(message.mdn_reports.len(), 2); } #[async_std::test] @@ -1646,10 +1646,13 @@ Additional-Message-IDs: \n\ ); assert_eq!(message.parts.len(), 1); - assert_eq!(message.reports.len(), 1); - assert_eq!(message.reports[0].original_message_id, "foo@example.org"); + assert_eq!(message.mdn_reports.len(), 1); assert_eq!( - &message.reports[0].additional_message_ids, + message.mdn_reports[0].original_message_id, + "foo@example.org" + ); + assert_eq!( + &message.mdn_reports[0].additional_message_ids, &["foo@example.com", "foo@example.net"] ); } From 27ff1c4a75b2c4750d1338740c05a62d74c11af3 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 12 Jun 2020 11:02:45 +0200 Subject: [PATCH 30/37] check in heuristically_parse_ndn() that rfc724_mid_exists() so that we do not ignore emails because we erreneously thought that it was an ndn --- src/dc_receive_imf.rs | 1 - src/mimeparser.rs | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index eea482ead..bd11ca947 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -406,7 +406,6 @@ async fn add_parts( .unwrap_or_default(); if chat_id.is_unset() { - // check if the message belongs to an NDN if mime_parser.failure_report.is_some() { *chat_id = ChatId::new(DC_CHAT_ID_TRASH); info!( diff --git a/src/mimeparser.rs b/src/mimeparser.rs index b19de3c2d..aa89925ab 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -187,7 +187,7 @@ impl MimeMessage { failure_report: None, }; parser.parse_mime_recursive(context, &mail).await?; - parser.heuristically_parse_ndn().await; + parser.heuristically_parse_ndn(context).await; parser.parse_headers(context)?; Ok(parser) @@ -900,7 +900,7 @@ impl MimeMessage { Ok(None) } - async fn heuristically_parse_ndn(&mut self) -> Option<()> { + async fn heuristically_parse_ndn(&mut self, context: &Context) -> Option<()> { if self .get(HeaderDef::Subject)? .to_ascii_lowercase() @@ -922,15 +922,19 @@ impl MimeMessage { } if let Some(c) = RE.captures(line) { if let Ok(original_message_id) = parse_message_id(&c[1]) { - self.failure_report = Some(FailureReport { - rfc724_mid: original_message_id, - failed_recipient: None, - }) + if let Ok(Some(_)) = + message::rfc724_mid_exists(context, &original_message_id).await + { + self.failure_report = Some(FailureReport { + rfc724_mid: original_message_id, + failed_recipient: None, + }) + } } } } } - None + None // Always return None, we just return anything so that we can use the '?' operator. } /// Handle reports @@ -956,7 +960,7 @@ impl MimeMessage { } } - if let Some(original_message_id) = &self.failure_report { + if let Some(failure_report) = &self.failure_report { let error = parts.iter().find(|p| p.typ == Viewtype::Text).map(|p| { let msg = &p.msg; match msg.find("\n--- ") { @@ -965,7 +969,7 @@ impl MimeMessage { } .trim() }); - message::ndn_from_ext(context, original_message_id, error).await + message::ndn_from_ext(context, failure_report, error).await } } } From 1fe85dfb3ccc24466ef46e9e6caa4c17d9e2ac85 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 12 Jun 2020 11:11:24 +0200 Subject: [PATCH 31/37] more functional --- src/mimeparser.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index aa89925ab..be9452676 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -911,25 +911,24 @@ impl MimeMessage { .contains("daemon") && self.failure_report.is_none() { - for line in self + lazy_static! { + static ref RE: regex::Regex = regex::Regex::new(r"Message-ID:(.*)").unwrap(); + } + for captures in self .parts .iter() - .filter_map(|p| p.msg_raw.as_ref()) - .flat_map(|p| p.lines()) + .filter_map(|part| part.msg_raw.as_ref()) + .flat_map(|part| part.lines()) + .filter_map(|line| RE.captures(line)) { - lazy_static! { - static ref RE: regex::Regex = regex::Regex::new(r"Message-ID:(.*)").unwrap(); - } - if let Some(c) = RE.captures(line) { - if let Ok(original_message_id) = parse_message_id(&c[1]) { - if let Ok(Some(_)) = - message::rfc724_mid_exists(context, &original_message_id).await - { - self.failure_report = Some(FailureReport { - rfc724_mid: original_message_id, - failed_recipient: None, - }) - } + if let Ok(original_message_id) = parse_message_id(&captures[1]) { + if let Ok(Some(_)) = + message::rfc724_mid_exists(context, &original_message_id).await + { + self.failure_report = Some(FailureReport { + rfc724_mid: original_message_id, + failed_recipient: None, + }) } } } From 52dfa9b5367f0234fde61f694b430546e99205ff Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 12 Jun 2020 23:01:19 +0200 Subject: [PATCH 32/37] Renaming, comment --- src/message.rs | 4 ++-- src/mimeparser.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/message.rs b/src/message.rs index 589c9adc2..ed107988f 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1287,7 +1287,7 @@ pub async fn set_msg_failed(context: &Context, msg_id: MsgId, error: Option>, diff --git a/src/mimeparser.rs b/src/mimeparser.rs index be9452676..6be66de6b 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -900,6 +900,7 @@ impl MimeMessage { Ok(None) } + /// Some providers like GMX and Yahoo do not send standard NDNs (Non Delivery notifications) async fn heuristically_parse_ndn(&mut self, context: &Context) -> Option<()> { if self .get(HeaderDef::Subject)? @@ -951,8 +952,7 @@ impl MimeMessage { std::iter::once(&report.original_message_id).chain(&report.additional_message_ids) { if let Some((chat_id, msg_id)) = - message::mdn_from_ext(context, from_id, original_message_id, sent_timestamp) - .await + message::handle_mdn(context, from_id, original_message_id, sent_timestamp).await { context.emit_event(Event::MsgRead { chat_id, msg_id }); } @@ -968,7 +968,7 @@ impl MimeMessage { } .trim() }); - message::ndn_from_ext(context, failure_report, error).await + message::handle_ndn(context, failure_report, error).await } } } From bbf049e95b90b623657cb9ef5dbfafeae590601d Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 13 Jun 2020 09:54:42 +0200 Subject: [PATCH 33/37] string --- src/stock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stock.rs b/src/stock.rs index a172d2dd1..cc4f91baa 100644 --- a/src/stock.rs +++ b/src/stock.rs @@ -183,7 +183,7 @@ pub enum StockMessage { #[strum(props(fallback = "Message from %1$s"))] SubjectForNewContact = 73, - #[strum(props(fallback = "Failed to send message to %1$s. See 'info' for more details."))] + #[strum(props(fallback = "Failed to send message to %1$s."))] FailedSendingTo = 74, } From fc88bff32fd67ef1df2947a27c9fcaddde506a9c Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Sat, 13 Jun 2020 02:17:08 +0200 Subject: [PATCH 34/37] make clippy happy --- src/dc_receive_imf.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index bd11ca947..5c0f979bc 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -405,14 +405,12 @@ async fn add_parts( .await .unwrap_or_default(); - if chat_id.is_unset() { - if mime_parser.failure_report.is_some() { - *chat_id = ChatId::new(DC_CHAT_ID_TRASH); - info!( - context, - "Message belongs to an NDN and is not shown in a chat.", - ); - } + if chat_id.is_unset() && mime_parser.failure_report.is_some() { + *chat_id = ChatId::new(DC_CHAT_ID_TRASH); + info!( + context, + "Message belongs to an NDN and is not shown in a chat.", + ); } // get the chat_id - a chat_id here is no indicator that the chat is displayed in the normal list, From 9f1112833fd46a4eff03ea0de616f9f71edae815 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 13 Jun 2020 12:06:02 +0200 Subject: [PATCH 35/37] let prefetch_should_download() check if it might be an ndn --- src/dc_receive_imf.rs | 9 +++++++++ src/headerdef.rs | 1 + src/imap/mod.rs | 13 ++++++++++++- src/mimeparser.rs | 4 +++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 5c0f979bc..bbf512bcf 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2382,6 +2382,7 @@ mod tests { .await; } + // ndn = Non Delivery Notification async fn test_parse_ndn( self_addr: &str, foreign_addr: &str, @@ -2415,6 +2416,14 @@ mod tests { let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap(); let msg_id = chats.get_msg_id(0).unwrap(); + // Check that the ndn would be downloaded: + let headers = mailparse::parse_mail(raw_ndn).unwrap().headers; + assert!( + crate::imap::prefetch_should_download(&t.ctx, &headers, ShowEmails::Off) + .await + .unwrap() + ); + dc_receive_imf(&t.ctx, raw_ndn, "INBOX", 1, false) .await .unwrap(); diff --git a/src/headerdef.rs b/src/headerdef.rs index 10beaf4c8..36d763b8d 100644 --- a/src/headerdef.rs +++ b/src/headerdef.rs @@ -21,6 +21,7 @@ pub enum HeaderDef { References, InReplyTo, Precedence, + ContentType, ChatVersion, ChatGroupId, ChatGroupName, diff --git a/src/imap/mod.rs b/src/imap/mod.rs index fb3eecda8..c2b4f05b7 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1449,7 +1449,7 @@ async fn prefetch_is_reply_to_chat_message( false } -async fn prefetch_should_download( +pub(crate) async fn prefetch_should_download( context: &Context, headers: &[mailparse::MailHeader<'_>], show_emails: ShowEmails, @@ -1457,6 +1457,16 @@ async fn prefetch_should_download( let is_chat_message = headers.get_header_value(HeaderDef::ChatVersion).is_some(); let is_reply_to_chat_message = prefetch_is_reply_to_chat_message(context, &headers).await; + let maybe_ndn = if let Some(subject) = headers.get_header_value(HeaderDef::Subject) { + subject.to_ascii_lowercase().contains("fail") + } else { + false + } || if let Some(ctype) = headers.get_header_value(HeaderDef::ContentType) { + ctype.starts_with("multipart/report") + } else { + false + }; + // Autocrypt Setup Message should be shown even if it is from non-chat client. let is_autocrypt_setup_message = headers .get_header_value(HeaderDef::AutocryptSetupMessage) @@ -1467,6 +1477,7 @@ async fn prefetch_should_download( let accepted_contact = origin.is_known(); let show = is_autocrypt_setup_message + || maybe_ndn || match show_emails { ShowEmails::Off => is_chat_message || is_reply_to_chat_message, ShowEmails::AcceptedContacts => { diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 6be66de6b..79c313044 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -900,7 +900,9 @@ impl MimeMessage { Ok(None) } - /// Some providers like GMX and Yahoo do not send standard NDNs (Non Delivery notifications) + /// Some providers like GMX and Yahoo do not send standard NDNs (Non Delivery notifications). + /// If you improve heuristics here you might also have to change prefetch_should_download() in imap/mod.rs. + /// Also you should add a test in dc_receive_imf.rs (there already are lots of test_parse_ndn_* tests). async fn heuristically_parse_ndn(&mut self, context: &Context) -> Option<()> { if self .get(HeaderDef::Subject)? From 45b871f76d7fec9d848ee3b86c631e342685cb9a Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 13 Jun 2020 14:18:16 +0200 Subject: [PATCH 36/37] Look at From instead of Subject and ContentType in prefetch_should_download. --- src/imap/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/imap/mod.rs b/src/imap/mod.rs index c2b4f05b7..6b3c250b3 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1457,12 +1457,8 @@ pub(crate) async fn prefetch_should_download( let is_chat_message = headers.get_header_value(HeaderDef::ChatVersion).is_some(); let is_reply_to_chat_message = prefetch_is_reply_to_chat_message(context, &headers).await; - let maybe_ndn = if let Some(subject) = headers.get_header_value(HeaderDef::Subject) { - subject.to_ascii_lowercase().contains("fail") - } else { - false - } || if let Some(ctype) = headers.get_header_value(HeaderDef::ContentType) { - ctype.starts_with("multipart/report") + let maybe_ndn = if let Some(from) = headers.get_header_value(HeaderDef::From_) { + from.to_ascii_lowercase().contains("daemon") } else { false }; From 15b30ceed1257ce70a0daeff14db67af26ce6ac5 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Sat, 13 Jun 2020 17:29:38 +0200 Subject: [PATCH 37/37] check for sender mailer-daemon as link2xt proposed --- src/imap/mod.rs | 2 +- src/mimeparser.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/imap/mod.rs b/src/imap/mod.rs index 6b3c250b3..3bb0bf249 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1458,7 +1458,7 @@ pub(crate) async fn prefetch_should_download( let is_reply_to_chat_message = prefetch_is_reply_to_chat_message(context, &headers).await; let maybe_ndn = if let Some(from) = headers.get_header_value(HeaderDef::From_) { - from.to_ascii_lowercase().contains("daemon") + from.to_ascii_lowercase().contains("mailer-daemon") } else { false }; diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 79c313044..1ac3e67c7 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -911,7 +911,7 @@ impl MimeMessage { && self .get(HeaderDef::From_)? .to_ascii_lowercase() - .contains("daemon") + .contains("mailer-daemon") && self.failure_report.is_none() { lazy_static! {