Update mailparse to 0.12

This commit is contained in:
Alexander Krotov
2020-03-22 19:51:59 +03:00
committed by holger krekel
parent 958802a233
commit d78ea882c8
7 changed files with 45 additions and 78 deletions

6
Cargo.lock generated
View File

@@ -651,7 +651,7 @@ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "lettre_email 0.9.2 (git+https://github.com/deltachat/lettre)",
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-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)", "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]] [[package]]
name = "mailparse" name = "mailparse"
version = "0.10.4" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "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 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 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 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 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 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" "checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"

View File

@@ -53,7 +53,7 @@ bitflags = "1.1.0"
debug_stub_derive = "0.3.0" debug_stub_derive = "0.3.0"
sanitize-filename = "0.2.1" sanitize-filename = "0.2.1"
stop-token = { version = "0.1.1", features = ["unstable"] } 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" } encoded-words = { git = "https://github.com/async-email/encoded-words", branch="master" }
native-tls = "0.2.3" native-tls = "0.2.3"
image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] } image = { version = "0.22.4", default-features=false, features = ["gif_codec", "jpeg", "ico", "png_codec", "pnm", "webp", "bmp"] }

View File

@@ -75,7 +75,7 @@ impl Aheader {
wanted_from: &str, wanted_from: &str,
headers: &[mailparse::MailHeader<'_>], headers: &[mailparse::MailHeader<'_>],
) -> Option<Self> { ) -> Option<Self> {
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) { match Self::from_str(&value) {
Ok(header) => { Ok(header) => {
if addr_cmp(&header.addr, wanted_from) { if addr_cmp(&header.addr, wanted_from) {

View File

@@ -126,7 +126,7 @@ pub fn try_decrypt(
) -> Result<(Option<Vec<u8>>, HashSet<String>)> { ) -> Result<(Option<Vec<u8>>, HashSet<String>)> {
let from = mail let from = mail
.headers .headers
.get_header_value(HeaderDef::From_)? .get_header_value(HeaderDef::From_)
.and_then(|from_addr| mailparse::addrparse(&from_addr).ok()) .and_then(|from_addr| mailparse::addrparse(&from_addr).ok())
.and_then(|from| from.extract_single_info()) .and_then(|from| from.extract_single_info())
.map(|from| from.addr) .map(|from| from.addr)

View File

@@ -1,5 +1,5 @@
use crate::strum::AsStaticRef; use crate::strum::AsStaticRef;
use mailparse::{MailHeader, MailHeaderMap, MailParseError}; use mailparse::{MailHeader, MailHeaderMap};
#[derive(Debug, Display, Clone, PartialEq, Eq, EnumVariantNames, AsStaticStr)] #[derive(Debug, Display, Clone, PartialEq, Eq, EnumVariantNames, AsStaticStr)]
#[strum(serialize_all = "kebab_case")] #[strum(serialize_all = "kebab_case")]
@@ -52,11 +52,11 @@ impl HeaderDef {
} }
pub trait HeaderDefMap { pub trait HeaderDefMap {
fn get_header_value(&self, headerdef: HeaderDef) -> Result<Option<String>, MailParseError>; fn get_header_value(&self, headerdef: HeaderDef) -> Option<String>;
} }
impl HeaderDefMap for [MailHeader<'_>] { impl HeaderDefMap for [MailHeader<'_>] {
fn get_header_value(&self, headerdef: HeaderDef) -> Result<Option<String>, MailParseError> { fn get_header_value(&self, headerdef: HeaderDef) -> Option<String> {
self.get_first_value(headerdef.get_headername()) self.get_first_value(headerdef.get_headername())
} }
} }
@@ -79,18 +79,13 @@ mod tests {
let (headers, _) = let (headers, _) =
mailparse::parse_headers(b"fRoM: Bob\naUtoCryPt-SeTup-MessAge: v99").unwrap(); mailparse::parse_headers(b"fRoM: Bob\naUtoCryPt-SeTup-MessAge: v99").unwrap();
assert_eq!( assert_eq!(
headers headers.get_header_value(HeaderDef::AutocryptSetupMessage),
.get_header_value(HeaderDef::AutocryptSetupMessage)
.unwrap(),
Some("v99".to_string()) Some("v99".to_string())
); );
assert_eq!( assert_eq!(
headers.get_header_value(HeaderDef::From_).unwrap(), headers.get_header_value(HeaderDef::From_),
Some("Bob".to_string()) Some("Bob".to_string())
); );
assert_eq!( assert_eq!(headers.get_header_value(HeaderDef::Autocrypt), None);
headers.get_header_value(HeaderDef::Autocrypt).unwrap(),
None
);
} }
} }

View File

@@ -1338,30 +1338,27 @@ fn get_fetch_headers(prefetch_msg: &Fetch) -> Result<Vec<mailparse::MailHeader>>
} }
fn prefetch_get_message_id(headers: &[mailparse::MailHeader]) -> Result<String> { fn prefetch_get_message_id(headers: &[mailparse::MailHeader]) -> Result<String> {
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)?) Ok(crate::mimeparser::parse_message_id(&message_id)?)
} else { } else {
Err(Error::Other("prefetch: No message ID found".to_string())) Err(Error::Other("prefetch: No message ID found".to_string()))
} }
} }
fn prefetch_is_reply_to_chat_message( fn prefetch_is_reply_to_chat_message(context: &Context, headers: &[mailparse::MailHeader]) -> bool {
context: &Context, if let Some(value) = headers.get_header_value(HeaderDef::InReplyTo) {
headers: &[mailparse::MailHeader],
) -> Result<bool> {
if let Some(value) = headers.get_header_value(HeaderDef::InReplyTo)? {
if is_msgrmsg_rfc724_mid_in_list(context, &value) { 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) { if is_msgrmsg_rfc724_mid_in_list(context, &value) {
return Ok(true); return true;
} }
} }
Ok(false) false
} }
fn prefetch_should_download( fn prefetch_should_download(
@@ -1369,16 +1366,16 @@ fn prefetch_should_download(
headers: &[mailparse::MailHeader], headers: &[mailparse::MailHeader],
show_emails: ShowEmails, show_emails: ShowEmails,
) -> Result<bool> { ) -> Result<bool> {
let is_chat_message = headers.get_header_value(HeaderDef::ChatVersion)?.is_some(); 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_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. // Autocrypt Setup Message should be shown even if it is from non-chat client.
let is_autocrypt_setup_message = headers let is_autocrypt_setup_message = headers
.get_header_value(HeaderDef::AutocryptSetupMessage)? .get_header_value(HeaderDef::AutocryptSetupMessage)
.is_some(); .is_some();
let from_field = headers let from_field = headers
.get_header_value(HeaderDef::From_)? .get_header_value(HeaderDef::From_)
.unwrap_or_default(); .unwrap_or_default();
let (_contact_id, blocked_contact, origin) = from_field_to_contact_id(context, &from_field)?; let (_contact_id, blocked_contact, origin) = from_field_to_contact_id(context, &from_field)?;

View File

@@ -85,7 +85,7 @@ impl MimeMessage {
let message_time = mail let message_time = mail
.headers .headers
.get_header_value(HeaderDef::Date)? .get_header_value(HeaderDef::Date)
.and_then(|v| mailparse::dateparse(&v).ok()) .and_then(|v| mailparse::dateparse(&v).ok())
.unwrap_or_default(); .unwrap_or_default();
@@ -111,8 +111,7 @@ impl MimeMessage {
// Handle any gossip headers if the mail was encrypted. See section // 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 // "3.6 Key Gossip" of https://autocrypt.org/autocrypt-spec-1.1.0.pdf
let gossip_headers = let gossip_headers = decrypted_mail.headers.get_all_values("Autocrypt-Gossip");
decrypted_mail.headers.get_all_values("Autocrypt-Gossip")?;
gossipped_addr = gossipped_addr =
update_gossip_peerstates(context, message_time, &mail, gossip_headers)?; update_gossip_peerstates(context, message_time, &mail, gossip_headers)?;
@@ -746,16 +745,13 @@ impl MimeMessage {
fn merge_headers(headers: &mut HashMap<String, String>, fields: &[mailparse::MailHeader<'_>]) { fn merge_headers(headers: &mut HashMap<String, String>, fields: &[mailparse::MailHeader<'_>]) {
for field in fields { for field in fields {
if let Ok(key) = field.get_key() {
// lowercasing all headers is technically not correct, but makes things work better // lowercasing all headers is technically not correct, but makes things work better
let key = key.to_lowercase(); let key = field.get_key().to_lowercase();
if !headers.contains_key(&key) || // key already exists, only overwrite known types (protected headers) if !headers.contains_key(&key) || // key already exists, only overwrite known types (protected headers)
is_known(&key) || key.starts_with("chat-") is_known(&key) || key.starts_with("chat-")
{ {
if let Ok(value) = field.get_value() { let value = field.get_value();
headers.insert(key, value); headers.insert(key.to_string(), value);
}
}
} }
} }
} }
@@ -770,21 +766,13 @@ impl MimeMessage {
let (report_fields, _) = mailparse::parse_headers(&report_body)?; let (report_fields, _) = mailparse::parse_headers(&report_body)?;
// must be present // must be present
if let Some(_disposition) = report_fields if let Some(_disposition) = report_fields.get_header_value(HeaderDef::Disposition) {
.get_header_value(HeaderDef::Disposition)
.ok()
.flatten()
{
if let Some(original_message_id) = report_fields if let Some(original_message_id) = report_fields
.get_header_value(HeaderDef::OriginalMessageId) .get_header_value(HeaderDef::OriginalMessageId)
.ok()
.flatten()
.and_then(|v| parse_message_id(&v).ok()) .and_then(|v| parse_message_id(&v).ok())
{ {
let additional_message_ids = report_fields let additional_message_ids = report_fields
.get_header_value(HeaderDef::AdditionalMessageIds) .get_header_value(HeaderDef::AdditionalMessageIds)
.ok()
.flatten()
.map_or_else(Vec::new, |v| { .map_or_else(Vec::new, |v| {
v.split(' ') v.split(' ')
.filter_map(|s| parse_message_id(s).ok()) .filter_map(|s| parse_message_id(s).ok())
@@ -800,7 +788,7 @@ impl MimeMessage {
warn!( warn!(
context, context,
"ignoring unknown disposition-notification, Message-Id: {:?}", "ignoring unknown disposition-notification, Message-Id: {:?}",
report_fields.get_header_value(HeaderDef::MessageId).ok() report_fields.get_header_value(HeaderDef::MessageId)
); );
Ok(None) Ok(None)
@@ -860,14 +848,9 @@ fn update_gossip_peerstates(
if let Ok(ref header) = gossip_header { if let Ok(ref header) = gossip_header {
if recipients.is_none() { if recipients.is_none() {
recipients = Some(get_recipients(mail.headers.iter().filter_map(|v| { recipients = Some(get_recipients(
let key = v.get_key(); mail.headers.iter().map(|v| (v.get_key(), v.get_value())),
let value = v.get_value(); ));
if key.is_err() || value.is_err() {
return None;
}
Some((v.get_key().unwrap(), v.get_value().unwrap()))
})));
} }
if recipients if recipients
@@ -915,13 +898,8 @@ pub(crate) fn parse_message_id(value: &str) -> crate::error::Result<String> {
let ids = mailparse::msgidparse(value) let ids = mailparse::msgidparse(value)
.map_err(|err| format_err!("failed to parse message id {:?}", err))?; .map_err(|err| format_err!("failed to parse message id {:?}", err))?;
if ids.len() == 1 { if let Some(id) = ids.first() {
let id = &ids[0]; Ok(id.to_string())
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);
}
} else { } else {
bail!("could not parse message_id: {}", value); 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 { fn is_attachment_disposition(mail: &mailparse::ParsedMail<'_>) -> bool {
if let Ok(ct) = mail.get_content_disposition() { let ct = mail.get_content_disposition();
return ct.disposition == DispositionType::Attachment ct.disposition == DispositionType::Attachment
&& ct && ct
.params .params
.iter() .iter()
.any(|(key, _value)| key.starts_with("filename")); .any(|(key, _value)| key.starts_with("filename"))
}
false
} }
/// Tries to get attachment filename. /// Tries to get attachment filename.
@@ -1010,7 +985,7 @@ fn get_attachment_filename(mail: &mailparse::ParsedMail) -> Result<Option<String
// or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...` // or `Content-Disposition: ... filename*0*=... filename*1*=... filename*2*=...`
// or `Content-Disposition: ... filename=...` // or `Content-Disposition: ... filename=...`
let ct = mail.get_content_disposition()?; let ct = mail.get_content_disposition();
let desired_filename: Option<String> = ct let desired_filename: Option<String> = ct
.params .params