Also resync UIDs in folders that are not configured (#2289)

This commit is contained in:
Hocuri
2022-03-10 16:12:24 +01:00
committed by GitHub
parent 332cb0896b
commit d9441a6bdd
3 changed files with 43 additions and 27 deletions

View File

@@ -26,6 +26,7 @@
### Fixes ### Fixes
- avoid archived, fresh chats #3053 - 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 - 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 messages in the Spam folder created contact requests #3015
- Fix a bug where drafts disappeared after some days #3067 - Fix a bug where drafts disappeared after some days #3067

View File

@@ -2,10 +2,12 @@ use std::{collections::BTreeMap, time::Instant};
use anyhow::{Context as _, Result}; use anyhow::{Context as _, Result};
use crate::config::Config;
use crate::imap::Imap; use crate::imap::Imap;
use crate::{config::Config, log::LogExt}; use crate::log::LogExt;
use crate::{context::Context, imap::FolderMeaning}; 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}; use super::{get_folder_meaning, get_folder_meaning_by_name};
@@ -27,22 +29,12 @@ impl Imap {
info!(context, "Starting full folder scan"); info!(context, "Starting full folder scan");
self.prepare(context).await?; self.prepare(context).await?;
let session = self.session.as_mut(); let folders = self.list_folders(context).await?;
let session = session.context("scan_folders(): IMAP No Connection established")?;
let folders: Vec<_> = session.list(Some(""), Some("*")).await?.collect().await;
let watched_folders = get_watched_folders(context).await?; let watched_folders = get_watched_folders(context).await?;
let mut folder_configs = BTreeMap::new(); let mut folder_configs = BTreeMap::new();
for folder in folders { 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, // 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 // 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 // received. The code used to wrongly conclude that the email had
@@ -101,6 +93,20 @@ impl Imap {
last_scan.replace(Instant::now()); last_scan.replace(Instant::now());
Ok(true) Ok(true)
} }
/// Returns the names of all folders on the IMAP server.
pub async fn list_folders(
self: &mut Imap,
context: &Context,
) -> Result<Vec<async_imap::types::Name>> {
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<Vec<Config>> { pub(crate) async fn get_watched_folder_configs(context: &Context) -> Result<Vec<Config>> {

View File

@@ -365,29 +365,38 @@ impl Job {
Status::Finished(Ok(())) 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 { async fn resync_folders(&mut self, context: &Context, imap: &mut Imap) -> Status {
if let Err(err) = imap.prepare(context).await { if let Err(err) = imap.prepare(context).await {
warn!(context, "could not connect: {:?}", err); warn!(context, "could not connect: {:?}", err);
return Status::RetryLater; return Status::RetryLater;
} }
let sentbox_folder = job_try!(context.get_config(Config::ConfiguredSentboxFolder).await); let all_folders = match imap.list_folders(context).await {
if let Some(sentbox_folder) = sentbox_folder { Ok(v) => v,
job_try!(imap.resync_folder_uids(context, sentbox_folder).await); 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 any_failed {
if let Some(inbox_folder) = inbox_folder { Status::RetryLater
job_try!(imap.resync_folder_uids(context, inbox_folder).await); } 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 { async fn markseen_msg_on_imap(&mut self, context: &Context, imap: &mut Imap) -> Status {