Don't fetch messages that arrived in the meantime if InboxWatch is

disabled and re-enabled

That's another narrow-stitching patch for a scenario where many emails could
be deleted all at once and surprisingly: user disables inbox-watch, enables delete-from-server, after a moth enables inbox-watch again -> currently all emails that arrived in the meantime will be deleted (if emails are not fetched, they won't be deleted)
This commit is contained in:
Hocuri
2020-11-17 13:17:04 +01:00
parent c8d4eee794
commit 3a7bd8b49d
2 changed files with 44 additions and 42 deletions

View File

@@ -253,6 +253,16 @@ impl Context {
job::schedule_resync(self).await;
ret
}
Config::InboxWatch => {
if self.get_config(Config::InboxWatch).await.as_deref() != value {
// If Inbox-watch is disabled and then enabled again, we don't want
// emails that arrived in the meantime to be fetched
if let Some(inbox) = self.get_config(Config::ConfiguredInboxFolder).await {
crate::imap::set_config_last_seen_uid(self, inbox, 0, 0).await;
}
}
self.sql.set_raw_config(self, key, value).await
}
_ => self.sql.set_raw_config(self, key, value).await,
}
}

View File

@@ -457,24 +457,6 @@ impl Imap {
Ok(())
}
async fn get_config_last_seen_uid<S: AsRef<str>>(
&self,
context: &Context,
folder: S,
) -> (u32, u32) {
let key = format!("imap.mailbox.{}", folder.as_ref());
if let Some(entry) = context.sql.get_raw_config(context, &key).await {
// the entry has the format `imap.mailbox.<folder>=<uidvalidity>:<lastseenuid>`
let mut parts = entry.split(':');
(
parts.next().unwrap_or_default().parse().unwrap_or(0),
parts.next().unwrap_or_default().parse().unwrap_or(0),
)
} else {
(0, 0)
}
}
/// Synchronizes UIDs in the database with UIDs on the server.
///
/// It is assumed that no operations are taking place on the same
@@ -559,7 +541,7 @@ impl Imap {
self.select_folder(context, Some(folder)).await?;
// compare last seen UIDVALIDITY against the current one
let (uid_validity, last_seen_uid) = self.get_config_last_seen_uid(context, &folder).await;
let (uid_validity, last_seen_uid) = get_config_last_seen_uid(context, &folder).await;
let config = &mut self.config;
let mailbox = config
@@ -585,8 +567,7 @@ impl Imap {
// id we do not do this here, we'll miss the first message
// as we will get in here again and fetch from lastseenuid+1 then
self.set_config_last_seen_uid(context, &folder, new_uid_validity, 0)
.await;
set_config_last_seen_uid(context, &folder, new_uid_validity, 0).await;
return Ok((new_uid_validity, 0));
}
@@ -630,8 +611,7 @@ impl Imap {
}
};
self.set_config_last_seen_uid(context, &folder, new_uid_validity, new_last_seen_uid)
.await;
set_config_last_seen_uid(context, &folder, new_uid_validity, new_last_seen_uid).await;
if uid_validity != 0 || last_seen_uid != 0 {
job::schedule_resync(context).await;
}
@@ -714,8 +694,7 @@ impl Imap {
let last_one = new_last_seen_uid.max(new_last_seen_uid_processed);
if last_one > last_seen_uid {
self.set_config_last_seen_uid(context, &folder, uid_validity, last_one)
.await;
set_config_last_seen_uid(context, &folder, uid_validity, last_one).await;
}
if read_errors == 0 {
@@ -861,23 +840,6 @@ impl Imap {
Ok(msgs)
}
async fn set_config_last_seen_uid<S: AsRef<str>>(
&self,
context: &Context,
folder: S,
uidvalidity: u32,
lastseenuid: u32,
) {
let key = format!("imap.mailbox.{}", folder.as_ref());
let val = format!("{}:{}", uidvalidity, lastseenuid);
context
.sql
.set_raw_config(context, &key, Some(&val))
.await
.ok();
}
/// Fetches a list of messages by server UID.
/// The passed in list of uids must be sorted.
///
@@ -1711,6 +1673,36 @@ fn get_fallback_folder(delimiter: &str) -> String {
format!("INBOX{}DeltaChat", delimiter)
}
pub async fn set_config_last_seen_uid<S: AsRef<str>>(
context: &Context,
folder: S,
uidvalidity: u32,
lastseenuid: u32,
) {
let key = format!("imap.mailbox.{}", folder.as_ref());
let val = format!("{}:{}", uidvalidity, lastseenuid);
context
.sql
.set_raw_config(context, &key, Some(&val))
.await
.ok();
}
async fn get_config_last_seen_uid<S: AsRef<str>>(context: &Context, folder: S) -> (u32, u32) {
let key = format!("imap.mailbox.{}", folder.as_ref());
if let Some(entry) = context.sql.get_raw_config(context, &key).await {
// the entry has the format `imap.mailbox.<folder>=<uidvalidity>:<lastseenuid>`
let mut parts = entry.split(':');
(
parts.next().unwrap_or_default().parse().unwrap_or(0),
parts.next().unwrap_or_default().parse().unwrap_or(0),
)
} else {
(0, 0)
}
}
#[cfg(test)]
mod tests {
use super::*;