diff --git a/python/tests/test_1_online.py b/python/tests/test_1_online.py index ee306275d..a52e3bfa2 100644 --- a/python/tests/test_1_online.py +++ b/python/tests/test_1_online.py @@ -308,7 +308,7 @@ def test_move_works(acfactory): def test_move_avoids_loop(acfactory): - """Test that the message is only moved once. + """Test that the message is only moved from INBOX to DeltaChat. This is to avoid busy loop if moved message reappears in the Inbox or some scanned folder later. @@ -319,6 +319,14 @@ def test_move_avoids_loop(acfactory): ac1 = acfactory.new_online_configuring_account() ac2 = acfactory.new_online_configuring_account(mvbox_move=True) acfactory.bring_accounts_online() + + # Create INBOX.DeltaChat folder and make sure + # it is detected by full folder scan. + ac2.direct_imap.create_folder("INBOX.DeltaChat") + ac2.stop_io() + ac2.start_io() + ac2._evtracker.get_info_contains("Found folders:") # Wait until the end of folder scan. + ac1_chat = acfactory.get_accepted_chat(ac1, ac2) ac1_chat.send_text("Message 1") @@ -326,20 +334,28 @@ def test_move_avoids_loop(acfactory): ac2_msg1 = ac2._evtracker.wait_next_incoming_message() assert ac2_msg1.text == "Message 1" - # Move the message to the INBOX again. + # Move the message to the INBOX.DeltaChat again. + # We assume that test server uses "." as the delimiter. ac2.direct_imap.select_folder("DeltaChat") - ac2.direct_imap.conn.move(["*"], "INBOX") + ac2.direct_imap.conn.move(["*"], "INBOX.DeltaChat") ac1_chat.send_text("Message 2") ac2_msg2 = ac2._evtracker.wait_next_incoming_message() assert ac2_msg2.text == "Message 2" - # Check that Message 1 is still in the INBOX folder + # Stop and start I/O to trigger folder scan. + ac2.stop_io() + ac2.start_io() + ac2._evtracker.get_info_contains("Found folders:") # Wait until the end of folder scan. + + # Check that Message 1 is still in the INBOX.DeltaChat folder # and Message 2 is in the DeltaChat folder. ac2.direct_imap.select_folder("INBOX") - assert len(ac2.direct_imap.get_all_messages()) == 1 + assert len(ac2.direct_imap.get_all_messages()) == 0 ac2.direct_imap.select_folder("DeltaChat") assert len(ac2.direct_imap.get_all_messages()) == 1 + ac2.direct_imap.select_folder("INBOX.DeltaChat") + assert len(ac2.direct_imap.get_all_messages()) == 1 def test_move_works_on_self_sent(acfactory): @@ -450,14 +466,19 @@ def test_resend_message(acfactory, lp): lp.sec("ac2: receive message") msg_in = ac2._evtracker.wait_next_incoming_message() assert msg_in.text == "message" - chat2 = msg_in.chat - chat2_msg_cnt = len(chat2.get_messages()) lp.sec("ac1: resend message") ac1.resend_messages([msg_in]) - lp.sec("ac2: check that message is deleted") - ac2._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED") + lp.sec("ac1: send another message") + chat1.send_text("another message") + + lp.sec("ac2: receive another message") + msg_in = ac2._evtracker.wait_next_incoming_message() + assert msg_in.text == "another message" + chat2 = msg_in.chat + chat2_msg_cnt = len(chat2.get_messages()) + assert len(chat2.get_messages()) == chat2_msg_cnt @@ -1757,10 +1778,10 @@ def test_group_quote(acfactory, lp): "xyz", ), # Test that emails aren't found in a random folder ( - "Spam", + "xyz", True, - "DeltaChat", - ), # ...emails are moved from the spam folder to "DeltaChat" + "xyz", + ), # ...emails are found in a random folder and downloaded without moving ( "Spam", False, diff --git a/src/config.rs b/src/config.rs index aabec2455..9f071c85d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -737,9 +737,6 @@ impl Context { stats::pre_sending_config_change(self, old_value, new_value).await?; } self.set_config_internal(key, value).await?; - if key == Config::SentboxWatch { - self.last_full_folder_scan.lock().await.take(); - } if key == Config::StatsSending { stats::maybe_send_stats(self).await?; } diff --git a/src/context.rs b/src/context.rs index 9dd664836..7edfd5b1c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -258,8 +258,6 @@ pub struct InnerContext { /// IMAP METADATA. pub(crate) metadata: RwLock>, - pub(crate) last_full_folder_scan: Mutex>, - /// ID for this `Context` in the current process. /// /// This allows for multiple `Context`s open in a single process where each context can @@ -468,7 +466,6 @@ impl Context { server_id: RwLock::new(None), metadata: RwLock::new(None), creation_time: tools::Time::now(), - last_full_folder_scan: Mutex::new(None), last_error: parking_lot::RwLock::new("".to_string()), migration_error: parking_lot::RwLock::new(None), debug_logging: std::sync::RwLock::new(None), diff --git a/src/download.rs b/src/download.rs index d4ad5ec1d..44e852021 100644 --- a/src/download.rs +++ b/src/download.rs @@ -157,30 +157,23 @@ pub(crate) async fn download_msg( let row = context .sql .query_row_optional( - "SELECT uid, folder, uidvalidity FROM imap WHERE rfc724_mid=? AND target!=''", + "SELECT uid, folder FROM imap WHERE rfc724_mid=? AND target!=''", (&msg.rfc724_mid,), |row| { let server_uid: u32 = row.get(0)?; let server_folder: String = row.get(1)?; - let uidvalidity: u32 = row.get(2)?; - Ok((server_uid, server_folder, uidvalidity)) + Ok((server_uid, server_folder)) }, ) .await?; - let Some((server_uid, server_folder, uidvalidity)) = row else { + let Some((server_uid, server_folder)) = row else { // No IMAP record found, we don't know the UID and folder. return Err(anyhow!("Call download_full() again to try over.")); }; session - .fetch_single_msg( - context, - &server_folder, - uidvalidity, - server_uid, - msg.rfc724_mid.clone(), - ) + .fetch_single_msg(context, &server_folder, server_uid, msg.rfc724_mid.clone()) .await?; Ok(()) } @@ -194,7 +187,6 @@ impl Session { &mut self, context: &Context, folder: &str, - uidvalidity: u32, uid: u32, rfc724_mid: String, ) -> Result<()> { @@ -214,16 +206,8 @@ impl Session { let mut uid_message_ids: BTreeMap = BTreeMap::new(); uid_message_ids.insert(uid, rfc724_mid); let (sender, receiver) = async_channel::unbounded(); - self.fetch_many_msgs( - context, - folder, - uidvalidity, - vec![uid], - &uid_message_ids, - false, - sender, - ) - .await?; + self.fetch_many_msgs(context, folder, vec![uid], &uid_message_ids, false, sender) + .await?; if receiver.recv().await.is_err() { bail!("Failed to fetch UID {uid}"); } diff --git a/src/imap.rs b/src/imap.rs index 5481d75b7..918184135 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -620,71 +620,38 @@ impl Imap { // Determine the target folder where the message should be moved to. // - // If we have seen the message on the IMAP server before, do not move it. + // We only move the messages from the INBOX and Spam folders. // This is required to avoid infinite MOVE loop on IMAP servers // that alias `DeltaChat` folder to other names. // For example, some Dovecot servers alias `DeltaChat` folder to `INBOX.DeltaChat`. - // In this case Delta Chat configured with `DeltaChat` as the destination folder - // would detect messages in the `INBOX.DeltaChat` folder - // and try to move them to the `DeltaChat` folder. - // Such move to the same folder results in the messages - // getting a new UID, so the messages will be detected as new + // In this case moving from `INBOX.DeltaChat` to `DeltaChat` + // results in the messages getting a new UID, + // so the messages will be detected as new // in the `INBOX.DeltaChat` folder again. - let _target; - let target = if let Some(message_id) = &message_id { - let msg_info = - message::rfc724_mid_exists_ex(context, message_id, "deleted=1").await?; - let delete = if let Some((_, _, true)) = msg_info { - info!(context, "Deleting locally deleted message {message_id}."); - true - } else if let Some((_, ts_sent_old, _)) = msg_info { - let is_chat_msg = headers.get_header_value(HeaderDef::ChatVersion).is_some(); - let ts_sent = headers - .get_header_value(HeaderDef::Date) - .and_then(|v| mailparse::dateparse(&v).ok()) - .unwrap_or_default(); - let is_dup = is_dup_msg(is_chat_msg, ts_sent, ts_sent_old); - if is_dup { - info!(context, "Deleting duplicate message {message_id}."); - } - is_dup - } else { - false - }; - if delete { - &delete_target - } else if context - .sql - .exists( - "SELECT COUNT (*) FROM imap WHERE rfc724_mid=?", - (message_id,), - ) + let delete = if let Some(message_id) = &message_id { + message::rfc724_mid_exists_ex(context, message_id, "deleted=1") .await? - { - info!( - context, - "Not moving the message {} that we have seen before.", &message_id - ); - folder - } else { - _target = target_folder(context, folder, folder_meaning, &headers).await?; - &_target - } + .is_some_and(|(_msg_id, deleted)| deleted) } else { - // Do not move the messages without Message-ID. - // We cannot reliably determine if we have seen them before, - // so it is safer not to move them. - warn!( - context, - "Not moving the message that does not have a Message-ID." - ); - folder + false }; // Generate a fake Message-ID to identify the message in the database // if the message has no real Message-ID. let message_id = message_id.unwrap_or_else(create_message_id); + if delete { + info!(context, "Deleting locally deleted message {message_id}."); + } + + let _target; + let target = if delete { + &delete_target + } else { + _target = target_folder(context, folder, folder_meaning, &headers).await?; + &_target + }; + context .sql .execute( @@ -768,7 +735,6 @@ impl Imap { .fetch_many_msgs( context, folder, - uid_validity, uids_fetch_in_batch.split_off(0), &uid_message_ids, fetch_partially, @@ -1383,12 +1349,10 @@ impl Session { /// /// If the message is incorrect or there is a failure to write a message to the database, /// it is skipped and the error is logged. - #[expect(clippy::too_many_arguments)] pub(crate) async fn fetch_many_msgs( &mut self, context: &Context, folder: &str, - uidvalidity: u32, request_uids: Vec, uid_message_ids: &BTreeMap, fetch_partially: bool, @@ -1514,9 +1478,6 @@ impl Session { ); let res = receive_imf_inner( context, - folder, - uidvalidity, - request_uid, rfc724_mid, body, is_seen, @@ -1530,9 +1491,6 @@ impl Session { } receive_imf_inner( context, - folder, - uidvalidity, - request_uid, rfc724_mid, body, is_seen, @@ -2112,7 +2070,9 @@ pub async fn target_folder_cfg( if folder_meaning == FolderMeaning::Spam { spam_target_folder_cfg(context, headers).await - } else if needs_move_to_mvbox(context, headers).await? { + } else if folder_meaning == FolderMeaning::Inbox + && needs_move_to_mvbox(context, headers).await? + { Ok(Some(Config::ConfiguredMvboxFolder)) } else { Ok(None) @@ -2260,7 +2220,9 @@ fn get_folder_meaning_by_name(folder_name: &str) -> FolderMeaning { ]; let lower = folder_name.to_lowercase(); - if SENT_NAMES.iter().any(|s| s.to_lowercase() == lower) { + if lower == "inbox" { + FolderMeaning::Inbox + } else if SENT_NAMES.iter().any(|s| s.to_lowercase() == lower) { FolderMeaning::Sent } else if SPAM_NAMES.iter().any(|s| s.to_lowercase() == lower) { FolderMeaning::Spam @@ -2416,15 +2378,6 @@ pub(crate) async fn prefetch_should_download( Ok(should_download) } -/// Returns whether a message is a duplicate (resent message). -pub(crate) fn is_dup_msg(is_chat_msg: bool, ts_sent: i64, ts_sent_old: i64) -> bool { - // If the existing message has timestamp_sent == 0, that means we don't know its actual sent - // timestamp, so don't delete the new message. E.g. outgoing messages have zero timestamp_sent - // because they are stored to the db before sending. Also consider as duplicates only messages - // with greater timestamp to avoid deleting both messages in a multi-device setting. - is_chat_msg && ts_sent_old != 0 && ts_sent > ts_sent_old -} - /// Marks messages in `msgs` table as seen, searching for them by UID. /// /// Returns updated chat ID if any message was marked as seen. diff --git a/src/imap/imap_tests.rs b/src/imap/imap_tests.rs index 60637045d..1aa746ea9 100644 --- a/src/imap/imap_tests.rs +++ b/src/imap/imap_tests.rs @@ -186,7 +186,7 @@ const COMBINATIONS_ACCEPTED_CHAT: &[(&str, bool, bool, &str)] = &[ ("Sent", false, false, "Sent"), ("Sent", false, true, "Sent"), ("Sent", true, false, "Sent"), - ("Sent", true, true, "DeltaChat"), + ("Sent", true, true, "Sent"), ("Spam", false, false, "INBOX"), // Move classical emails in accepted chats from Spam to Inbox, not 100% sure on this, we could also just never move non-chat-msgs ("Spam", false, true, "INBOX"), ("Spam", true, false, "INBOX"), // Move classical emails in accepted chats from Spam to Inbox, not 100% sure on this, we could also just never move non-chat-msgs @@ -202,7 +202,7 @@ const COMBINATIONS_REQUEST: &[(&str, bool, bool, &str)] = &[ ("Sent", false, false, "Sent"), ("Sent", false, true, "Sent"), ("Sent", true, false, "Sent"), - ("Sent", true, true, "DeltaChat"), + ("Sent", true, true, "Sent"), ("Spam", false, false, "Spam"), ("Spam", false, true, "INBOX"), ("Spam", true, false, "Spam"), diff --git a/src/imap/scan_folders.rs b/src/imap/scan_folders.rs index 9b22c613a..ed4b6f215 100644 --- a/src/imap/scan_folders.rs +++ b/src/imap/scan_folders.rs @@ -18,7 +18,7 @@ impl Imap { ) -> Result { // First of all, debounce to once per minute: { - let mut last_scan = context.last_full_folder_scan.lock().await; + let mut last_scan = session.last_full_folder_scan.lock().await; if let Some(last_scan) = *last_scan { let elapsed_secs = time_elapsed(&last_scan).as_secs(); let debounce_secs = context diff --git a/src/imap/session.rs b/src/imap/session.rs index 8588fbab8..a633974d4 100644 --- a/src/imap/session.rs +++ b/src/imap/session.rs @@ -5,9 +5,11 @@ use anyhow::{Context as _, Result}; use async_imap::Session as ImapSession; use async_imap::types::Mailbox; use futures::TryStreamExt; +use tokio::sync::Mutex; use crate::imap::capabilities::Capabilities; use crate::net::session::SessionStream; +use crate::tools; /// Prefetch: /// - Message-ID to check if we already have the message. @@ -40,6 +42,8 @@ pub(crate) struct Session { pub selected_folder_needs_expunge: bool, + pub(crate) last_full_folder_scan: Mutex>, + /// True if currently selected folder has new messages. /// /// Should be false if no folder is currently selected. @@ -71,6 +75,7 @@ impl Session { selected_folder: None, selected_mailbox: None, selected_folder_needs_expunge: false, + last_full_folder_scan: Mutex::new(None), new_mail: false, } } diff --git a/src/message.rs b/src/message.rs index 8ae88f6bb..04e4b1f6a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1234,7 +1234,7 @@ impl Message { /// `References` header is not taken into account. pub async fn parent(&self, context: &Context) -> Result> { if let Some(in_reply_to) = &self.in_reply_to { - if let Some((msg_id, _ts_sent)) = rfc724_mid_exists(context, in_reply_to).await? { + if let Some(msg_id) = rfc724_mid_exists(context, in_reply_to).await? { let msg = Message::load_from_db_optional(context, msg_id).await?; return Ok(msg); } @@ -2043,13 +2043,13 @@ pub async fn estimate_deletion_cnt( pub(crate) async fn rfc724_mid_exists( context: &Context, rfc724_mid: &str, -) -> Result> { +) -> Result> { Ok(rfc724_mid_exists_ex(context, rfc724_mid, "1") .await? - .map(|(id, ts_sent, _)| (id, ts_sent))) + .map(|(id, _)| id)) } -/// Returns [MsgId] and "sent" timestamp of the most recent message with given `rfc724_mid` +/// Returns [MsgId] of the most recent message with given `rfc724_mid` /// (Message-ID header) and bool `expr` result if such messages exists in the db. /// /// * `expr`: SQL expression additionally passed into `SELECT`. Evaluated to `true` iff it is true @@ -2058,7 +2058,7 @@ pub(crate) async fn rfc724_mid_exists_ex( context: &Context, rfc724_mid: &str, expr: &str, -) -> Result> { +) -> Result> { let rfc724_mid = rfc724_mid.trim_start_matches('<').trim_end_matches('>'); if rfc724_mid.is_empty() { warn!(context, "Empty rfc724_mid passed to rfc724_mid_exists"); @@ -2076,9 +2076,8 @@ pub(crate) async fn rfc724_mid_exists_ex( (rfc724_mid,), |row| { let msg_id: MsgId = row.get(0)?; - let timestamp_sent: i64 = row.get(1)?; let expr_res: bool = row.get(2)?; - Ok((msg_id, timestamp_sent, expr_res)) + Ok((msg_id, expr_res)) }, ) .await?; @@ -2098,7 +2097,7 @@ pub(crate) async fn get_by_rfc724_mids( ) -> Result> { let mut latest = None; for id in mids.iter().rev() { - let Some((msg_id, _)) = rfc724_mid_exists(context, id).await? else { + let Some(msg_id) = rfc724_mid_exists(context, id).await? else { continue; }; let Some(msg) = Message::load_from_db_optional(context, msg_id).await? else { diff --git a/src/reaction.rs b/src/reaction.rs index 6b90e0947..cdd7b4812 100644 --- a/src/reaction.rs +++ b/src/reaction.rs @@ -278,7 +278,7 @@ pub(crate) async fn set_msg_reaction( reaction: Reaction, is_incoming_fresh: bool, ) -> Result<()> { - if let Some((msg_id, _)) = rfc724_mid_exists(context, in_reply_to).await? { + if let Some(msg_id) = rfc724_mid_exists(context, in_reply_to).await? { set_msg_id_reaction(context, msg_id, chat_id, contact_id, timestamp, &reaction).await?; if is_incoming_fresh diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 11e74ab63..100c2874b 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -17,7 +17,7 @@ use regex::Regex; use crate::chat::{self, Chat, ChatId, ChatIdBlocked, remove_from_chat_contacts_table}; use crate::config::Config; use crate::constants::{self, Blocked, Chattype, DC_CHAT_ID_TRASH, EDITED_PREFIX, ShowEmails}; -use crate::contact::{Contact, ContactId, Origin, mark_contact_id_as_verified}; +use crate::contact::{self, Contact, ContactId, Origin, mark_contact_id_as_verified}; use crate::context::Context; use crate::debug_logging::maybe_set_logging_xdc_inner; use crate::download::DownloadState; @@ -45,7 +45,6 @@ use crate::stock_str; use crate::sync::Sync::*; use crate::tools::{self, buf_compress, remove_subject_prefix}; use crate::{chatlist_events, ensure_and_debug_assert, ensure_and_debug_assert_eq, location}; -use crate::{contact, imap}; /// This is the struct that is returned after receiving one email (aka MIME message). /// @@ -154,8 +153,8 @@ pub async fn receive_imf( seen: bool, ) -> Result> { let mail = mailparse::parse_mail(imf_raw).context("can't parse mail")?; - let rfc724_mid = - imap::prefetch_get_message_id(&mail.headers).unwrap_or_else(imap::create_message_id); + let rfc724_mid = crate::imap::prefetch_get_message_id(&mail.headers) + .unwrap_or_else(crate::imap::create_message_id); if let Some(download_limit) = context.download_limit().await? { let download_limit: usize = download_limit.try_into()?; if imf_raw.len() > download_limit { @@ -189,9 +188,6 @@ pub(crate) async fn receive_imf_from_inbox( ) -> Result> { receive_imf_inner( context, - "INBOX", - 0, - 0, rfc724_mid, imf_raw, seen, @@ -493,12 +489,8 @@ async fn get_to_and_past_contact_ids( /// /// If `partial` is set, it contains the full message size in bytes and an optional error text for /// the partially downloaded message. -#[expect(clippy::too_many_arguments)] pub(crate) async fn receive_imf_inner( context: &Context, - folder: &str, - uidvalidity: u32, - uid: u32, rfc724_mid: &str, imf_raw: &[u8], seen: bool, @@ -553,7 +545,7 @@ pub(crate) async fn receive_imf_inner( // check, if the mail is already in our database. // make sure, this check is done eg. before securejoin-processing. let (replace_msg_id, replace_chat_id); - if let Some((old_msg_id, _)) = message::rfc724_mid_exists(context, rfc724_mid).await? { + if let Some(old_msg_id) = message::rfc724_mid_exists(context, rfc724_mid).await? { replace_msg_id = Some(old_msg_id); replace_chat_id = if let Some(msg) = Message::load_from_db_optional(context, old_msg_id) .await? @@ -570,27 +562,8 @@ pub(crate) async fn receive_imf_inner( } else { replace_msg_id = if rfc724_mid_orig == rfc724_mid { None - } else if let Some((old_msg_id, old_ts_sent)) = - message::rfc724_mid_exists(context, rfc724_mid_orig).await? - { - if imap::is_dup_msg( - mime_parser.has_chat_version(), - mime_parser.timestamp_sent, - old_ts_sent, - ) { - info!(context, "Deleting duplicate message {rfc724_mid_orig}."); - let target = context.get_delete_msgs_target().await?; - context - .sql - .execute( - "UPDATE imap SET target=? WHERE folder=? AND uidvalidity=? AND uid=?", - (target, folder, uidvalidity, uid), - ) - .await?; - } - Some(old_msg_id) } else { - None + message::rfc724_mid_exists(context, rfc724_mid_orig).await? }; replace_chat_id = None; } @@ -1906,7 +1879,7 @@ async fn add_parts( if let Some(node_addr) = mime_parser.get_header(HeaderDef::IrohNodeAddr) { match mime_parser.get_header(HeaderDef::InReplyTo) { Some(in_reply_to) => match rfc724_mid_exists(context, in_reply_to).await? { - Some((instance_id, _ts_sent)) => { + Some(instance_id) => { if let Err(err) = add_gossip_peer_from_header(context, instance_id, node_addr).await { @@ -2220,7 +2193,7 @@ async fn handle_edit_delete( from_id: ContactId, ) -> Result<()> { if let Some(rfc724_mid) = mime_parser.get_header(HeaderDef::ChatEdit) { - if let Some((original_msg_id, _)) = rfc724_mid_exists(context, rfc724_mid).await? { + if let Some(original_msg_id) = rfc724_mid_exists(context, rfc724_mid).await? { if let Some(mut original_msg) = Message::load_from_db_optional(context, original_msg_id).await? { @@ -2261,9 +2234,7 @@ async fn handle_edit_delete( let rfc724_mid_vec: Vec<&str> = rfc724_mid_list.split_whitespace().collect(); for rfc724_mid in rfc724_mid_vec { - if let Some((msg_id, _)) = - message::rfc724_mid_exists(context, rfc724_mid).await? - { + if let Some(msg_id) = message::rfc724_mid_exists(context, rfc724_mid).await? { if let Some(msg) = Message::load_from_db_optional(context, msg_id).await? { if msg.from_id == from_id { message::delete_msg_locally(context, &msg).await?; @@ -3626,7 +3597,7 @@ async fn get_previous_message( ) -> Result> { if let Some(field) = mime_parser.get_header(HeaderDef::References) { if let Some(rfc724mid) = parse_message_ids(field).last() { - if let Some((msg_id, _)) = rfc724_mid_exists(context, rfc724mid).await? { + if let Some(msg_id) = rfc724_mid_exists(context, rfc724mid).await? { return Message::load_from_db_optional(context, msg_id).await; } } diff --git a/src/receive_imf/receive_imf_tests.rs b/src/receive_imf/receive_imf_tests.rs index b347a73a4..f70c9fc81 100644 --- a/src/receive_imf/receive_imf_tests.rs +++ b/src/receive_imf/receive_imf_tests.rs @@ -1759,7 +1759,7 @@ async fn check_alias_reply(from_dc: bool, chat_request: bool, group_request: boo .await .unwrap(); - let (msg_id, _) = rfc724_mid_exists(&claire, "non-dc-1@example.org") + let msg_id = rfc724_mid_exists(&claire, "non-dc-1@example.org") .await .unwrap() .unwrap(); diff --git a/src/scheduler.rs b/src/scheduler.rs index 0c1134e43..db20a2051 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -618,7 +618,7 @@ async fn fetch_idle( .await .context("delete_expired_imap_messages")?; } else if folder_config == Config::ConfiguredInboxFolder { - ctx.last_full_folder_scan.lock().await.take(); + session.last_full_folder_scan.lock().await.take(); } // Scan additional folders only after finishing fetching the watched folder. diff --git a/src/sync.rs b/src/sync.rs index 26ff54050..d2eb52774 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -318,7 +318,7 @@ impl Context { } async fn save_message(&self, src_rfc724_mid: &str, dest_rfc724_mid: &String) -> Result<()> { - if let Some((src_msg_id, _)) = message::rfc724_mid_exists(self, src_rfc724_mid).await? { + if let Some(src_msg_id) = message::rfc724_mid_exists(self, src_rfc724_mid).await? { chat::save_copy_in_self_talk(self, src_msg_id, dest_rfc724_mid).await?; } Ok(()) @@ -328,7 +328,7 @@ impl Context { let mut modified_chat_ids = HashSet::new(); let mut msg_ids = Vec::new(); for rfc724_mid in msgs { - if let Some((msg_id, _)) = message::rfc724_mid_exists(self, rfc724_mid).await? { + if let Some(msg_id) = message::rfc724_mid_exists(self, rfc724_mid).await? { if let Some(msg) = Message::load_from_db_optional(self, msg_id).await? { message::delete_msg_locally(self, &msg).await?; msg_ids.push(msg.id);