diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index d70fe9233..85d4d177f 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -2,10 +2,9 @@ use std::ffi::CString; use std::ptr; use itertools::join; -use libc::{free, strcmp, strlen}; +use libc::{free, strcmp}; use mmime::clist::*; use mmime::mailimf::types::*; -use mmime::mailimf::*; use mmime::mailmime::content::*; use mmime::mailmime::types::*; use mmime::mailmime::*; @@ -819,24 +818,16 @@ unsafe fn handle_reports( && !of_org_msgid.is_null() && !(*of_org_msgid).fld_value.is_null() { - let mut rfc724_mid_0 = std::ptr::null_mut(); - dummy = 0; - - if mailimf_msg_id_parse( + if let Ok(rfc724_mid) = wrapmime::parse_message_id(as_str( (*of_org_msgid).fld_value, - strlen((*of_org_msgid).fld_value), - &mut dummy, - &mut rfc724_mid_0, - ) == MAIL_NO_ERROR as libc::c_int - && !rfc724_mid_0.is_null() - { + )) { let mut chat_id_0 = 0; let mut msg_id = 0; if message::mdn_from_ext( context, from_id, - as_str(rfc724_mid_0), + &rfc724_mid, sent_timestamp, &mut chat_id_0, &mut msg_id, @@ -844,7 +835,6 @@ unsafe fn handle_reports( rr_event_to_send.push((chat_id_0, msg_id)); } mdn_consumed = (msg_id != 0) as libc::c_int; - free(rfc724_mid_0.cast()); } } } diff --git a/src/imap.rs b/src/imap.rs index cd9122eee..f449ad1c1 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -8,12 +8,14 @@ use std::time::{Duration, SystemTime}; use crate::constants::*; use crate::context::Context; use crate::dc_receive_imf::dc_receive_imf; +use crate::error::Error; use crate::events::Event; use crate::job::{job_add, Action}; use crate::login_param::LoginParam; use crate::message::{self, update_msg_move_state, update_server_uid}; use crate::oauth2::dc_get_oauth2_access_token; use crate::param::Params; +use crate::wrapmime; const DC_IMAP_SEEN: usize = 0x0001; @@ -815,11 +817,7 @@ impl Imap { if cur_uid > last_seen_uid { read_cnt += 1; - let message_id = msg - .envelope() - .expect("missing envelope") - .message_id - .expect("missing message id"); + let message_id = prefetch_get_message_id(msg).unwrap_or_default(); if !precheck_imf(context, &message_id, folder.as_ref(), cur_uid) { // check passed, go fetch the rest @@ -1322,25 +1320,31 @@ impl Imap { if let Some(ref mut session) = &mut *self.session.lock().unwrap() { match session.uid_fetch(set, PREFETCH_FLAGS) { Ok(msgs) => { - if msgs.is_empty() - || msgs - .first() - .unwrap() - .envelope() - .expect("missing envelope") - .message_id - .expect("missing message id") - != message_id.as_ref() - { + if msgs.is_empty() { warn!( context, - "Cannot delete on IMAP, {}/{} does not match {}.", + "Cannot delete on IMAP, {}/{}: message-id gone '{}'", folder.as_ref(), server_uid, message_id.as_ref(), ); - *server_uid = 0; + } else { + let remote_message_id = + prefetch_get_message_id(msgs.first().unwrap()) + .unwrap_or_default(); + + if remote_message_id != message_id.as_ref() { + warn!( + context, + "Cannot delete on IMAP, {}/{}: remote message-id '{}' != '{}'", + folder.as_ref(), + server_uid, + remote_message_id, + message_id.as_ref(), + ); + } } + *server_uid = 0; } Err(err) => { eprintln!("fetch error: {:?}", err); @@ -1555,3 +1559,8 @@ fn precheck_imf(context: &Context, rfc724_mid: &str, server_folder: &str, server false } } + +fn prefetch_get_message_id(prefetch_msg: &imap::types::Fetch) -> Result { + let message_id = prefetch_msg.envelope().unwrap().message_id.unwrap(); + wrapmime::parse_message_id(&message_id) +} diff --git a/src/wrapmime.rs b/src/wrapmime.rs index e0a3f5402..1b2582911 100644 --- a/src/wrapmime.rs +++ b/src/wrapmime.rs @@ -8,6 +8,7 @@ use crate::dc_tools::*; use crate::error::Error; use mmime::clist::*; // use mmime::display::*; +use mmime::mailimf::mailimf_msg_id_parse; use mmime::mailimf::types::*; use mmime::mailimf::types_helper::*; use mmime::mailmime::content::*; @@ -48,6 +49,23 @@ pub fn get_ct_subtype(mime: *mut Mailmime) -> Option { } } +pub fn parse_message_id(message_id: &str) -> Result { + let mut dummy = 0; + let c_message_id = CString::new(message_id).unwrap(); + let c_ptr = c_message_id.as_ptr(); + let mut rfc724_mid_c = std::ptr::null_mut(); + if unsafe { mailimf_msg_id_parse(c_ptr, libc::strlen(c_ptr), &mut dummy, &mut rfc724_mid_c) } + == MAIL_NO_ERROR as libc::c_int + && !rfc724_mid_c.is_null() + { + let res = to_string_lossy(rfc724_mid_c); + unsafe { libc::free(rfc724_mid_c.cast()) }; + Ok(res) + } else { + bail!("could not parse message_id: {}", message_id); + } +} + pub fn get_autocrypt_mime( mime_undetermined: *mut Mailmime, ) -> Result<(*mut Mailmime, *mut Mailmime), Error> { @@ -518,4 +536,16 @@ mod tests { new_content_type("application/pgp-encrypted").unwrap() )); } + + #[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" + ); + } }