diff --git a/src/imap/mod.rs b/src/imap/mod.rs index 686d6cd1f..c89f60c64 100644 --- a/src/imap/mod.rs +++ b/src/imap/mod.rs @@ -1306,17 +1306,6 @@ fn precheck_imf(context: &Context, rfc724_mid: &str, server_folder: &str, server } } -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 { - Ok(ids[0].clone()) - } else { - bail!("could not parse message_id: {}", value); - } -} - fn get_fetch_headers(prefetch_msg: &Fetch) -> Result> { let header_bytes = match prefetch_msg.header() { Some(header_bytes) => header_bytes, @@ -1328,7 +1317,7 @@ 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)? { - Ok(parse_message_id(&message_id)?) + Ok(crate::mimeparser::parse_message_id(&message_id)?) } else { Err(Error::Other("prefetch: No message ID found".to_string())) } @@ -1384,20 +1373,3 @@ fn prefetch_should_download( let show = show && !blocked_contact; Ok(show) } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_parse_message_id() { - assert_eq!( - parse_message_id("Mr.PRUe8HJBoaO.3whNvLCMFU0@testrun.org").unwrap(), - "Mr.PRUe8HJBoaO.3whNvLCMFU0@testrun.org" - ); - assert_eq!( - parse_message_id("").unwrap(), - "Mr.PRUe8HJBoaO.3whNvLCMFU0@testrun.org" - ); - } -} diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 0a4e1bac7..e4ab0817c 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -741,7 +741,7 @@ impl MimeMessage { pub fn get_rfc724_mid(&self) -> Option { self.get(HeaderDef::MessageId) - .and_then(|msgid| parse_message_id(msgid)) + .and_then(|msgid| parse_message_id(msgid).ok()) } fn merge_headers(headers: &mut HashMap, fields: &[mailparse::MailHeader<'_>]) { @@ -779,14 +779,16 @@ impl MimeMessage { .get_header_value(HeaderDef::OriginalMessageId) .ok() .flatten() - .and_then(|v| parse_message_id(&v)) + .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(parse_message_id).collect() + v.split(' ') + .filter_map(|s| parse_message_id(s).ok()) + .collect() }); return Ok(Some(Report { @@ -909,14 +911,20 @@ pub(crate) struct Report { additional_message_ids: Vec, } -fn parse_message_id(field: &str) -> Option { - if let Ok(addrs) = mailparse::addrparse(field) { - // Assume the message id is a single id in the form of - if let mailparse::MailAddr::Single(mailparse::SingleInfo { ref addr, .. }) = addrs[0] { - return Some(addr.clone()); +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); } + } else { + bail!("could not parse message_id: {}", value); } - None } fn is_known(key: &str) -> bool {