avoid addrparse to panic() and refactor according code a little with test.

This commit is contained in:
holger krekel
2019-12-15 18:27:38 +01:00
parent 4bacae3711
commit 09c7ab1ee6
2 changed files with 47 additions and 33 deletions

View File

@@ -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( if let Err(err) = add_parts(
context, context,
&mut mime_parser, &mut mime_parser,
@@ -198,7 +198,7 @@ pub fn dc_receive_imf(
bail!("add_parts error: {:?}", err); bail!("add_parts error: {:?}", err);
} }
} else { } 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 // are correct in the further processing
if sent_timestamp > time() { if sent_timestamp > time() {
sent_timestamp = time() sent_timestamp = time()
@@ -588,10 +588,6 @@ fn add_parts(
let subject = mime_parser.get_subject().unwrap_or_default(); let subject = mime_parser.get_subject().unwrap_or_default();
for part in mime_parser.parts.iter_mut() { for part in mime_parser.parts.iter_mut() {
if part.is_meta {
continue;
}
if mime_parser.location_kml.is_some() if mime_parser.location_kml.is_some()
&& icnt == 1 && icnt == 1
&& (part.msg == "-location-" || part.msg.is_empty()) && (part.msg == "-location-" || part.msg.is_empty())

View File

@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use deltachat_derive::{FromSql, ToSql}; use deltachat_derive::{FromSql, ToSql};
use lettre_email::mime::{self, Mime}; use lettre_email::mime::{self, Mime};
use mailparse::{DispositionType, MailHeaderMap}; use mailparse::{DispositionType, MailAddr, MailHeaderMap};
use crate::aheader::Aheader; use crate::aheader::Aheader;
use crate::blob::BlobObject; use crate::blob::BlobObject;
@@ -208,7 +208,6 @@ impl<'a> MimeParser<'a> {
|| filepart.typ == Viewtype::Voice || filepart.typ == Viewtype::Voice
|| filepart.typ == Viewtype::Video || filepart.typ == Viewtype::Video
|| filepart.typ == Viewtype::File) || filepart.typ == Viewtype::File)
&& !filepart.is_meta
}; };
if need_drop { 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() { // See if an MDN is requested from the other side
if let Some(from_field) = self.get(HeaderDef::From_) { if !self.decrypting_failed && !self.parts.is_empty() {
let from_addrs = mailparse::addrparse(&from_field).unwrap(); if let Some(ref dn_to_addr) =
self.parse_first_addr(HeaderDef::ChatDispositionNotificationTo)
if let Some(from_addr) = from_addrs.first() { {
if compare_addrs(from_addr, dn_to_addr) { if let Some(ref from_addr) = self.parse_first_addr(HeaderDef::From_) {
if let Some(part_4) = self.get_last_nonmeta_mut() { if compare_addrs(from_addr, dn_to_addr) {
part_4.param.set_int(Param::WantsMdn, 1); 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. // just have send a message in the subject with an empty body.
// Besides, we want to show something in case our incoming-processing // Besides, we want to show something in case our incoming-processing
// failed to properly handle an incoming message. // 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(); let mut part = Part::default();
part.typ = Viewtype::Text; part.typ = Viewtype::Text;
@@ -353,14 +346,6 @@ impl<'a> MimeParser<'a> {
AvatarAction::None 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 { pub fn was_encrypted(&self) -> bool {
!self.signatures.is_empty() !self.signatures.is_empty()
} }
@@ -388,6 +373,20 @@ impl<'a> MimeParser<'a> {
self.header.get(&headerdef.get_headername()) self.header.get(&headerdef.get_headername())
} }
fn parse_first_addr(&self, headerdef: HeaderDef) -> Option<MailAddr> {
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<bool> { fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result<bool> {
if mail.ctype.params.get("protected-headers").is_some() { if mail.ctype.params.get("protected-headers").is_some() {
if mail.ctype.mimetype == "text/rfc822-headers" { if mail.ctype.mimetype == "text/rfc822-headers" {
@@ -876,7 +875,6 @@ fn is_known(key: &str) -> bool {
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct Part { pub struct Part {
pub typ: Viewtype, pub typ: Viewtype,
pub is_meta: bool,
pub mimetype: Option<Mime>, pub mimetype: Option<Mime>,
pub msg: String, pub msg: String,
pub msg_raw: Option<String>, pub msg_raw: Option<String>,
@@ -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] #[test]
fn test_mimeparser_with_context() { fn test_mimeparser_with_context() {
let context = dummy_context(); let context = dummy_context();