diff --git a/Cargo.lock b/Cargo.lock index 1ae331de3..c4bcf1ccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -651,7 +651,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre)", "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "mailparse 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mailparse 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1473,7 +1473,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mailparse" -version = "0.10.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3299,7 +3299,7 @@ dependencies = [ "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" -"checksum mailparse 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6c03df7fe4bab038aaa2f313baae7600de0afd606f8244860801c46f53babdd8" +"checksum mailparse 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7181507a68fef921f011b0c0f143efca20871da5ab3963bdc064537278469cd2" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" diff --git a/Cargo.toml b/Cargo.toml index d54e42468..72cb02b89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ bitflags = "1.1.0" debug_stub_derive = "0.3.0" sanitize-filename = "0.2.1" stop-token = { version = "0.1.1", features = ["unstable"] } -mailparse = "0.10.2" +mailparse = "0.12.0" encoded-words = { git = "https://github.com/async-email/encoded-words", branch="master" } native-tls = "0.2.3" image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] } diff --git a/src/aheader.rs b/src/aheader.rs index a87f7be65..628de89f7 100644 --- a/src/aheader.rs +++ b/src/aheader.rs @@ -75,7 +75,7 @@ impl Aheader { wanted_from: &str, headers: &[mailparse::MailHeader<'_>], ) -> Option { - if let Ok(Some(value)) = headers.get_header_value(HeaderDef::Autocrypt) { + if let Some(value) = headers.get_header_value(HeaderDef::Autocrypt) { match Self::from_str(&value) { Ok(header) => { if addr_cmp(&header.addr, wanted_from) { diff --git a/src/e2ee.rs b/src/e2ee.rs index 55baf2acb..4ae91e9c6 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -126,7 +126,7 @@ pub fn try_decrypt( ) -> Result<(Option>, HashSet)> { let from = mail .headers - .get_header_value(HeaderDef::From_)? + .get_header_value(HeaderDef::From_) .and_then(|from_addr| mailparse::addrparse(&from_addr).ok()) .and_then(|from| from.extract_single_info()) .map(|from| from.addr) diff --git a/src/headerdef.rs b/src/headerdef.rs index df75adec7..af8343949 100644 --- a/src/headerdef.rs +++ b/src/headerdef.rs @@ -1,5 +1,5 @@ use crate::strum::AsStaticRef; -use mailparse::{MailHeader, MailHeaderMap, MailParseError}; +use mailparse::{MailHeader, MailHeaderMap}; #[derive(Debug, Display, Clone, PartialEq, Eq, EnumVariantNames, AsStaticStr)] #[strum(serialize_all = "kebab_case")] @@ -52,11 +52,11 @@ impl HeaderDef { } pub trait HeaderDefMap { - fn get_header_value(&self, headerdef: HeaderDef) -> Result, MailParseError>; + fn get_header_value(&self, headerdef: HeaderDef) -> Option; } impl HeaderDefMap for [MailHeader<'_>] { - fn get_header_value(&self, headerdef: HeaderDef) -> Result, MailParseError> { + fn get_header_value(&self, headerdef: HeaderDef) -> Option { self.get_first_value(headerdef.get_headername()) } } @@ -79,18 +79,13 @@ mod tests { let (headers, _) = mailparse::parse_headers(b"fRoM: Bob\naUtoCryPt-SeTup-MessAge: v99").unwrap(); assert_eq!( - headers - .get_header_value(HeaderDef::AutocryptSetupMessage) - .unwrap(), + headers.get_header_value(HeaderDef::AutocryptSetupMessage), Some("v99".to_string()) ); assert_eq!( - headers.get_header_value(HeaderDef::From_).unwrap(), + headers.get_header_value(HeaderDef::From_), Some("Bob".to_string()) ); - assert_eq!( - headers.get_header_value(HeaderDef::Autocrypt).unwrap(), - None - ); + assert_eq!(headers.get_header_value(HeaderDef::Autocrypt), None); } } diff --git a/src/imap/mod.rs b/src/imap/mod.rs index 7f1eaaf0e..3eb0c6dc2 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1338,30 +1338,27 @@ fn get_fetch_headers(prefetch_msg: &Fetch) -> Result> } fn prefetch_get_message_id(headers: &[mailparse::MailHeader]) -> Result { - if let Some(message_id) = headers.get_header_value(HeaderDef::MessageId)? { + if let Some(message_id) = headers.get_header_value(HeaderDef::MessageId) { Ok(crate::mimeparser::parse_message_id(&message_id)?) } else { Err(Error::Other("prefetch: No message ID found".to_string())) } } -fn prefetch_is_reply_to_chat_message( - context: &Context, - headers: &[mailparse::MailHeader], -) -> Result { - if let Some(value) = headers.get_header_value(HeaderDef::InReplyTo)? { +fn prefetch_is_reply_to_chat_message(context: &Context, headers: &[mailparse::MailHeader]) -> bool { + if let Some(value) = headers.get_header_value(HeaderDef::InReplyTo) { if is_msgrmsg_rfc724_mid_in_list(context, &value) { - return Ok(true); + return true; } } - if let Some(value) = headers.get_header_value(HeaderDef::References)? { + if let Some(value) = headers.get_header_value(HeaderDef::References) { if is_msgrmsg_rfc724_mid_in_list(context, &value) { - return Ok(true); + return true; } } - Ok(false) + false } fn prefetch_should_download( @@ -1369,16 +1366,16 @@ fn prefetch_should_download( headers: &[mailparse::MailHeader], show_emails: ShowEmails, ) -> Result { - 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)?; + 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); // 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)? + .get_header_value(HeaderDef::AutocryptSetupMessage) .is_some(); let from_field = headers - .get_header_value(HeaderDef::From_)? + .get_header_value(HeaderDef::From_) .unwrap_or_default(); let (_contact_id, blocked_contact, origin) = from_field_to_contact_id(context, &from_field)?; diff --git a/src/mimeparser.rs b/src/mimeparser.rs index e4ab0817c..597b5ef48 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -85,7 +85,7 @@ impl MimeMessage { let message_time = mail .headers - .get_header_value(HeaderDef::Date)? + .get_header_value(HeaderDef::Date) .and_then(|v| mailparse::dateparse(&v).ok()) .unwrap_or_default(); @@ -111,8 +111,7 @@ impl MimeMessage { // Handle any gossip headers if the mail was encrypted. See section // "3.6 Key Gossip" of https://autocrypt.org/autocrypt-spec-1.1.0.pdf - let gossip_headers = - decrypted_mail.headers.get_all_values("Autocrypt-Gossip")?; + let gossip_headers = decrypted_mail.headers.get_all_values("Autocrypt-Gossip"); gossipped_addr = update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; @@ -746,16 +745,13 @@ impl MimeMessage { fn merge_headers(headers: &mut HashMap, fields: &[mailparse::MailHeader<'_>]) { for field in fields { - if let Ok(key) = field.get_key() { - // lowercasing all headers is technically not correct, but makes things work better - let key = key.to_lowercase(); - if !headers.contains_key(&key) || // key already exists, only overwrite known types (protected headers) + // lowercasing all headers is technically not correct, but makes things work better + let key = field.get_key().to_lowercase(); + if !headers.contains_key(&key) || // key already exists, only overwrite known types (protected headers) is_known(&key) || key.starts_with("chat-") - { - if let Ok(value) = field.get_value() { - headers.insert(key, value); - } - } + { + let value = field.get_value(); + headers.insert(key.to_string(), value); } } } @@ -770,21 +766,13 @@ impl MimeMessage { let (report_fields, _) = mailparse::parse_headers(&report_body)?; // must be present - if let Some(_disposition) = report_fields - .get_header_value(HeaderDef::Disposition) - .ok() - .flatten() - { + if let Some(_disposition) = report_fields.get_header_value(HeaderDef::Disposition) { if let Some(original_message_id) = report_fields .get_header_value(HeaderDef::OriginalMessageId) - .ok() - .flatten() .and_then(|v| parse_message_id(&v).ok()) { let additional_message_ids = report_fields .get_header_value(HeaderDef::AdditionalMessageIds) - .ok() - .flatten() .map_or_else(Vec::new, |v| { v.split(' ') .filter_map(|s| parse_message_id(s).ok()) @@ -800,7 +788,7 @@ impl MimeMessage { warn!( context, "ignoring unknown disposition-notification, Message-Id: {:?}", - report_fields.get_header_value(HeaderDef::MessageId).ok() + report_fields.get_header_value(HeaderDef::MessageId) ); Ok(None) @@ -860,14 +848,9 @@ fn update_gossip_peerstates( if let Ok(ref header) = gossip_header { if recipients.is_none() { - recipients = Some(get_recipients(mail.headers.iter().filter_map(|v| { - let key = v.get_key(); - let value = v.get_value(); - if key.is_err() || value.is_err() { - return None; - } - Some((v.get_key().unwrap(), v.get_value().unwrap())) - }))); + recipients = Some(get_recipients( + mail.headers.iter().map(|v| (v.get_key(), v.get_value())), + )); } if recipients @@ -915,13 +898,8 @@ pub(crate) fn parse_message_id(value: &str) -> crate::error::Result { let ids = mailparse::msgidparse(value) .map_err(|err| format_err!("failed to parse message id {:?}", err))?; - if ids.len() == 1 { - let id = &ids[0]; - if id.starts_with('<') && id.ends_with('>') { - Ok(id.chars().skip(1).take(id.len() - 2).collect()) - } else { - bail!("message-ID {} is not enclosed in < and >", value); - } + if let Some(id) = ids.first() { + Ok(id.to_string()) } else { bail!("could not parse message_id: {}", value); } @@ -987,15 +965,12 @@ fn get_mime_type(mail: &mailparse::ParsedMail<'_>) -> Result<(Mime, Viewtype)> { } fn is_attachment_disposition(mail: &mailparse::ParsedMail<'_>) -> bool { - if let Ok(ct) = mail.get_content_disposition() { - return ct.disposition == DispositionType::Attachment - && ct - .params - .iter() - .any(|(key, _value)| key.starts_with("filename")); - } - - false + let ct = mail.get_content_disposition(); + ct.disposition == DispositionType::Attachment + && ct + .params + .iter() + .any(|(key, _value)| key.starts_with("filename")) } /// Tries to get attachment filename. @@ -1010,7 +985,7 @@ fn get_attachment_filename(mail: &mailparse::ParsedMail) -> Result = ct .params