From d9441a6bdd8a718f504e50e8f606fa642fe89e17 Mon Sep 17 00:00:00 2001 From: Hocuri Date: Thu, 10 Mar 2022 16:12:24 +0100 Subject: [PATCH] Also resync UIDs in folders that are not configured (#2289) --- CHANGELOG.md | 1 + src/imap/scan_folders.rs | 32 +++++++++++++++++++------------- src/job.rs | 37 +++++++++++++++++++++++-------------- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f1a1bd9f..d13d2defb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ ### Fixes - avoid archived, fresh chats #3053 +- Also resync UIDs in folders that are not configured #2289 - treat "NO" IMAP response to MOVE and COPY commands as an error #3058 - Fix a bug where messages in the Spam folder created contact requests #3015 - Fix a bug where drafts disappeared after some days #3067 diff --git a/src/imap/scan_folders.rs b/src/imap/scan_folders.rs index 221943f65..176a17519 100644 --- a/src/imap/scan_folders.rs +++ b/src/imap/scan_folders.rs @@ -2,10 +2,12 @@ use std::{collections::BTreeMap, time::Instant}; use anyhow::{Context as _, Result}; +use crate::config::Config; use crate::imap::Imap; -use crate::{config::Config, log::LogExt}; +use crate::log::LogExt; use crate::{context::Context, imap::FolderMeaning}; -use async_std::prelude::*; + +use async_std::stream::StreamExt; use super::{get_folder_meaning, get_folder_meaning_by_name}; @@ -27,22 +29,12 @@ impl Imap { info!(context, "Starting full folder scan"); self.prepare(context).await?; - let session = self.session.as_mut(); - let session = session.context("scan_folders(): IMAP No Connection established")?; - let folders: Vec<_> = session.list(Some(""), Some("*")).await?.collect().await; + let folders = self.list_folders(context).await?; let watched_folders = get_watched_folders(context).await?; let mut folder_configs = BTreeMap::new(); for folder in folders { - let folder = match folder { - Ok(f) => f, - Err(e) => { - warn!(context, "Can't get folder: {}", e); - continue; - } - }; - // Gmail labels are not folders and should be skipped. For example, // emails appear in the inbox and under "All Mail" as soon as it is // received. The code used to wrongly conclude that the email had @@ -101,6 +93,20 @@ impl Imap { last_scan.replace(Instant::now()); Ok(true) } + + /// Returns the names of all folders on the IMAP server. + pub async fn list_folders( + self: &mut Imap, + context: &Context, + ) -> Result> { + let session = self.session.as_mut(); + let session = session.context("No IMAP connection")?; + let list = session + .list(Some(""), Some("*")) + .await? + .filter_map(|f| f.ok_or_log_msg(context, "list_folders() can't get folder")); + Ok(list.collect().await) + } } pub(crate) async fn get_watched_folder_configs(context: &Context) -> Result> { diff --git a/src/job.rs b/src/job.rs index c06258c50..9fd1216a4 100644 --- a/src/job.rs +++ b/src/job.rs @@ -365,29 +365,38 @@ impl Job { Status::Finished(Ok(())) } - /// Synchronizes UIDs for sentbox, inbox and mvbox. + /// Synchronizes UIDs for all folders. async fn resync_folders(&mut self, context: &Context, imap: &mut Imap) -> Status { if let Err(err) = imap.prepare(context).await { warn!(context, "could not connect: {:?}", err); return Status::RetryLater; } - let sentbox_folder = job_try!(context.get_config(Config::ConfiguredSentboxFolder).await); - if let Some(sentbox_folder) = sentbox_folder { - job_try!(imap.resync_folder_uids(context, sentbox_folder).await); + let all_folders = match imap.list_folders(context).await { + Ok(v) => v, + Err(e) => { + warn!(context, "Listing folders for resync failed: {:#}", e); + return Status::RetryLater; + } + }; + + let mut any_failed = false; + + for folder in all_folders { + if let Err(e) = imap + .resync_folder_uids(context, folder.name().to_string()) + .await + { + warn!(context, "{:#}", e); + any_failed = true; + } } - let inbox_folder = job_try!(context.get_config(Config::ConfiguredInboxFolder).await); - if let Some(inbox_folder) = inbox_folder { - job_try!(imap.resync_folder_uids(context, inbox_folder).await); + if any_failed { + Status::RetryLater + } else { + Status::Finished(Ok(())) } - - let mvbox_folder = job_try!(context.get_config(Config::ConfiguredMvboxFolder).await); - if let Some(mvbox_folder) = mvbox_folder { - job_try!(imap.resync_folder_uids(context, mvbox_folder).await); - } - - Status::Finished(Ok(())) } async fn markseen_msg_on_imap(&mut self, context: &Context, imap: &mut Imap) -> Status {