diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index fad00b47f..18ddec832 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -171,7 +171,7 @@ pub fn dc_receive_imf( } } }; - if mime_parser.get_last_nonmeta().is_some() { + if mime_parser.parts.last().is_some() { if let Err(err) = add_parts( context, &mut mime_parser, @@ -198,7 +198,7 @@ pub fn dc_receive_imf( bail!("add_parts error: {:?}", err); } } else { - // there are no non-meta data in message, do some basic calculations so that the varaiables + // there are parts in this message, do some basic calculations so that the variables // are correct in the further processing if sent_timestamp > time() { sent_timestamp = time() @@ -588,10 +588,6 @@ fn add_parts( let subject = mime_parser.get_subject().unwrap_or_default(); for part in mime_parser.parts.iter_mut() { - if part.is_meta { - continue; - } - if mime_parser.location_kml.is_some() && icnt == 1 && (part.msg == "-location-" || part.msg.is_empty()) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 526f1194d..eab89a81c 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use deltachat_derive::{FromSql, ToSql}; use lettre_email::mime::{self, Mime}; -use mailparse::{DispositionType, MailHeaderMap}; +use mailparse::{DispositionType, MailAddr, MailHeaderMap}; use crate::aheader::Aheader; use crate::blob::BlobObject; @@ -208,7 +208,6 @@ impl<'a> MimeParser<'a> { || filepart.typ == Viewtype::Voice || filepart.typ == Viewtype::Video || filepart.typ == Viewtype::File) - && !filepart.is_meta }; if need_drop { @@ -288,22 +287,16 @@ impl<'a> MimeParser<'a> { } } } - if !self.decrypting_failed { - if let Some(dn_field) = self.get(HeaderDef::ChatDispositionNotificationTo) { - if self.get_last_nonmeta().is_some() { - let addrs = mailparse::addrparse(&dn_field).unwrap(); - if let Some(dn_to_addr) = addrs.first() { - if let Some(from_field) = self.get(HeaderDef::From_) { - let from_addrs = mailparse::addrparse(&from_field).unwrap(); - - if let Some(from_addr) = from_addrs.first() { - 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); - } - } - } + // See if an MDN is requested from the other side + if !self.decrypting_failed && !self.parts.is_empty() { + if let Some(ref dn_to_addr) = + self.parse_first_addr(HeaderDef::ChatDispositionNotificationTo) + { + if let Some(ref from_addr) = self.parse_first_addr(HeaderDef::From_) { + if compare_addrs(from_addr, dn_to_addr) { + if let Some(part) = self.parts.last_mut() { + part.param.set_int(Param::WantsMdn, 1); } } } @@ -314,7 +307,7 @@ impl<'a> MimeParser<'a> { // 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.get_last_nonmeta().is_none() && self.reports.is_empty() { + if self.parts.is_empty() && self.reports.is_empty() { let mut part = Part::default(); part.typ = Viewtype::Text; @@ -353,14 +346,6 @@ impl<'a> MimeParser<'a> { AvatarAction::None } - pub fn get_last_nonmeta(&self) -> Option<&Part> { - self.parts.iter().rev().find(|part| !part.is_meta) - } - - pub fn get_last_nonmeta_mut(&mut self) -> Option<&mut Part> { - self.parts.iter_mut().rev().find(|part| !part.is_meta) - } - pub fn was_encrypted(&self) -> bool { !self.signatures.is_empty() } @@ -388,6 +373,20 @@ impl<'a> MimeParser<'a> { self.header.get(&headerdef.get_headername()) } + fn parse_first_addr(&self, headerdef: HeaderDef) -> Option { + if let Some(value) = self.get(headerdef.clone()) { + match mailparse::addrparse(&value) { + Ok(ref addrs) => { + return addrs.first().cloned(); + } + Err(err) => { + warn!(self.context, "header {} parse error: {:?}", headerdef, err); + } + } + } + None + } + fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result { if mail.ctype.params.get("protected-headers").is_some() { if mail.ctype.mimetype == "text/rfc822-headers" { @@ -876,7 +875,6 @@ fn is_known(key: &str) -> bool { #[derive(Debug, Default, Clone)] pub struct Part { pub typ: Viewtype, - pub is_meta: bool, pub mimetype: Option, pub msg: String, pub msg_raw: Option, @@ -1118,6 +1116,26 @@ mod tests { ); } + #[test] + fn test_parse_first_addr() { + let context = dummy_context(); + let raw = b"From: hello@one.org, world@two.org\n\ + Chat-Disposition-Notification-To: wrong + Content-Type: text/plain; + Chat-Version: 1.0\n\ + \n\ + test1\n\ + \x00"; + + let mimeparser = MimeParser::from_bytes(&context.ctx, &raw[..]).unwrap(); + + let of = mimeparser.parse_first_addr(HeaderDef::From_).unwrap(); + assert_eq!(of, mailparse::addrparse("hello@one.org").unwrap()[0]); + + let of = mimeparser.parse_first_addr(HeaderDef::ChatDispositionNotificationTo); + assert!(of.is_none()); + } + #[test] fn test_mimeparser_with_context() { let context = dummy_context();