From 6bb2adaf459264460c45d57831407b1436d0efd9 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 30 Nov 2019 19:09:04 +0100 Subject: [PATCH] some fixes for mdn handling --- src/mimeparser.rs | 50 +++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 97ee40e5c..a6692a859 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -305,10 +305,12 @@ impl<'a> MimeParser<'a> { if let Some(dn_to_addr) = addrs.first() { if let Some(from_field) = self.lookup_field("From") { - let value = from_field; - let from_addrs = mailparse::addrparse(&value).unwrap(); + info!(self.context, "From {:?}", from_field); + let from_addrs = mailparse::addrparse(&from_field).unwrap(); + if let Some(from_addr) = from_addrs.first() { - if from_addr == dn_to_addr { + info!(self.context, "comparing {:?} - {:?}", from_addr, dn_to_addr); + if compare_addrs(from_addr, dn_to_addr) { if let Some(part_4) = self.get_last_nonmeta_mut() { part_4.param.set_int(Param::WantsMdn, 1); } @@ -484,8 +486,8 @@ impl<'a> MimeParser<'a> { (DC_MIMETYPE_MP_REPORT, _) => { /* RFC 6522: the first part is for humans, the second for machines */ if mail.subparts.len() >= 2 { - let ct = mail.get_content_disposition()?; - if let Some(report_type) = ct.params.get("report-type") { + info!(self.context, "report: {:?}", &mail.ctype); + if let Some(report_type) = mail.ctype.params.get("report-type") { if report_type == "disposition-notification" { if let Some(report) = self.process_report(mail)? { self.reports.push(report); @@ -790,31 +792,15 @@ impl<'a> MimeParser<'a> { } fn process_report(&self, report: &mailparse::ParsedMail<'_>) -> Result> { - let ct = report.get_content_disposition()?; - let report_type = ct.params.get("report-type"); - if report_type.is_none() { - return Ok(None); - } - let report_type = report_type.unwrap(); - if report_type != "disposition-notification" || report.subparts.len() < 2 { - // the first part is for humans, the second for machines - return Ok(None); - } - // to get a clear functionality, do not show incoming MDNs if the options is disabled if !self.mdns_enabled { return Ok(None); } - // 1. get content - let raw = report.subparts[1].get_body_raw()?; - let report_details = mailparse::parse_mail(&raw)?; - // 2. parse as mailheaders - let report_body = report_details.get_body_raw()?; + // parse as mailheaders + let report_body = report.subparts[1].get_body_raw()?; let (report_fields, _) = mailparse::parse_headers(&report_body)?; - // 3. retrieve information - // must be present if let Some(_disposition) = report_fields.get_first_value("Disposition").ok().flatten() { if let Some(original_message_id) = report_fields @@ -1059,6 +1045,24 @@ fn get_recipients<'a, S: AsRef, T: Iterator>(headers: T) -> recipients } +/// Check if the only addrs match, ignoring names. +fn compare_addrs(a: &mailparse::MailAddr, b: &mailparse::MailAddr) -> bool { + match a { + mailparse::MailAddr::Group(group_a) => match b { + mailparse::MailAddr::Group(group_b) => group_a + .addrs + .iter() + .zip(group_b.addrs.iter()) + .all(|(a, b)| a.addr == b.addr), + _ => false, + }, + mailparse::MailAddr::Single(single_a) => match b { + mailparse::MailAddr::Single(single_b) => single_a.addr == single_b.addr, + _ => false, + }, + } +} + #[cfg(test)] mod tests { use super::*;