refine uid_next handling and rename and resultify configure_folder to ensure_configurer_folders

This commit is contained in:
holger krekel
2019-11-30 12:17:55 +01:00
committed by Floris Bruynooghe
parent 7be5fe925a
commit d14c6ea202
3 changed files with 92 additions and 91 deletions

View File

@@ -355,14 +355,15 @@ pub fn JobConfigureImap(context: &Context) {
progress!(context, 900); progress!(context, 900);
let create_mvbox = context.get_config_bool(Config::MvboxWatch) let create_mvbox = context.get_config_bool(Config::MvboxWatch)
|| context.get_config_bool(Config::MvboxMove); || context.get_config_bool(Config::MvboxMove);
context let imap = &context.inbox_thread.read().unwrap().imap;
.inbox_thread if let Err(err) = imap.ensure_configured_folders(context, create_mvbox) {
.read() error!(context, "configuring folders failed: {:?}", err);
.unwrap() false
.imap } else {
.configure_folders(context, create_mvbox); // XXX call fetch_from_single_folder to set last_seen_uid
true true
} }
}
17 => { 17 => {
progress!(context, 910); progress!(context, 910);
/* configuration success - write back the configured parameters with the "configured_" prefix; also write the "configured"-flag */ /* configuration success - write back the configured parameters with the "configured_" prefix; also write the "configured"-flag */

View File

@@ -318,19 +318,12 @@ impl Imap {
// the trailing underscore is correct // the trailing underscore is correct
if self.connect(context, &param) { if self.connect(context, &param) {
if context self.ensure_configured_folders(context, true)
.sql } else {
.get_raw_config_int(context, "folders_configured") Err(Error::ImapConnectionFailed(
.unwrap_or_default()
< 3
{
self.configure_folders(context, true);
}
return Ok(());
}
return Err(Error::ImapConnectionFailed(
format!("{}", param).to_string(), format!("{}", param).to_string(),
)); ))
}
} }
/// tries connecting to imap account using the specific login /// tries connecting to imap account using the specific login
@@ -558,13 +551,11 @@ impl Imap {
let config = self.config.read().await; let config = self.config.read().await;
let mailbox = config.selected_mailbox.as_ref().expect("just selected"); let mailbox = config.selected_mailbox.as_ref().expect("just selected");
ensure!( let new_uid_validity = match mailbox.uid_validity {
mailbox.uid_validity.is_some(), Some(v) => v,
"Cannot get UIDVALIDITY for folder {:?}", None => bail!("Cannot get UIDVALIDITY for folder {:?}", folder.as_ref()),
folder.as_ref() };
);
let new_uid_validity = mailbox.uid_validity.unwrap();
if new_uid_validity != uid_validity { if new_uid_validity != uid_validity {
if mailbox.exists == 0 { if mailbox.exists == 0 {
info!(context, "Folder \"{}\" is empty.", folder.as_ref()); info!(context, "Folder \"{}\" is empty.", folder.as_ref());
@@ -579,20 +570,22 @@ impl Imap {
// uid_validity has changed or is being set the first time. // uid_validity has changed or is being set the first time.
// find the last seen uid within the new uid_validity scope. // find the last seen uid within the new uid_validity scope.
let new_last_seen_uid = match mailbox.uid_next {
let new_last_seen_uid = if mailbox.uid_next.is_none() { Some(uid_next) => {
uid_next - 1 // XXX could uid_next be 0?
}
None => {
warn!( warn!(
context, context,
"IMAP folder did not report uid_next, falling back to fetching" "IMAP folder has no uid_next, fall back to fetching"
); );
if let Some(ref mut session) = &mut *self.session.lock().await { if let Some(ref mut session) = &mut *self.session.lock().await {
// `FETCH <message sequence number> (UID)`
// note that we use fetch by sequence number // note that we use fetch by sequence number
// and thus we only need to get exactly the // and thus we only need to get exactly the
// last-index message. // last-index message.
let set = format!("{}", mailbox.exists); let set = format!("{}", mailbox.exists);
match session.fetch(set, JUST_UID).await { match session.fetch(set, JUST_UID).await {
Ok(list) => list[0].uid.unwrap_or_else(|| 0), Ok(list) => list[0].uid.unwrap_or_default(),
Err(err) => { Err(err) => {
bail!("fetch failed: {:?}", err); bail!("fetch failed: {:?}", err);
} }
@@ -600,14 +593,13 @@ impl Imap {
} else { } else {
return Err(Error::ImapNoConnection); return Err(Error::ImapNoConnection);
} }
} else { }
max(0, mailbox.uid_next.unwrap() - 1)
}; };
self.set_config_last_seen_uid(context, &folder, new_uid_validity, new_last_seen_uid); self.set_config_last_seen_uid(context, &folder, new_uid_validity, new_last_seen_uid);
info!( info!(
context, context,
"uid change: new {}/{} current {}/{}", "uid/validity change: new {}/{} current {}/{}",
new_last_seen_uid, new_last_seen_uid,
new_uid_validity, new_uid_validity,
uid_validity, uid_validity,
@@ -635,9 +627,9 @@ impl Imap {
return Err(Error::ImapNoConnection); return Err(Error::ImapNoConnection);
}; };
// go through all mails in folder (this is typically _fast_ as we already have the whole list) // prefetch info from all unknown mails in the folder
for msg in &list { for msg in &list {
let cur_uid = msg.uid.unwrap_or_else(|| 0); let cur_uid = msg.uid.unwrap_or_default();
if cur_uid > last_seen_uid { if cur_uid > last_seen_uid {
read_cnt += 1; read_cnt += 1;
@@ -1239,19 +1231,35 @@ impl Imap {
}) })
} }
pub fn configure_folders(&self, context: &Context, create_mvbox: bool) { pub fn ensure_configured_folders(
task::block_on(async move { &self,
if !self.is_connected().await { context: &Context,
return; create_mvbox: bool,
) -> Result<(), Error> {
let folders_configured = context
.sql
.get_raw_config_int(context, "folders_configured");
if folders_configured.unwrap_or_default() >= 3 {
// the "3" here we increase if we have future updates to
// to folder configuration
return Ok(());
} }
task::block_on(async move {
ensure!(
self.is_connected().await,
"cannot configure folders: not connected"
);
info!(context, "Configuring IMAP-folders."); info!(context, "Configuring IMAP-folders.");
if let Some(ref mut session) = &mut *self.session.lock().await { if let Some(ref mut session) = &mut *self.session.lock().await {
let folders = self let folders = match self.list_folders(session, context).await {
.list_folders(session, context) Some(f) => f,
.await None => {
.expect("no folders found"); bail!("could not obtain list of imap folders");
}
};
let sentbox_folder = let sentbox_folder =
folders folders
@@ -1282,7 +1290,7 @@ impl Imap {
Err(err) => { Err(err) => {
warn!( warn!(
context, context,
"Cannot create MVBOX-folder, using trying INBOX subfolder. ({})", "Cannot create MVBOX-folder, trying to create INBOX subfolder. ({})",
err err
); );
@@ -1304,36 +1312,34 @@ impl Imap {
// that may be used by other MUAs to list folders. // that may be used by other MUAs to list folders.
// for the LIST command, the folder is always visible. // for the LIST command, the folder is always visible.
if let Some(ref mvbox) = mvbox_folder { if let Some(ref mvbox) = mvbox_folder {
// TODO: better error handling if let Err(err) = session.subscribe(mvbox).await {
session.subscribe(mvbox).await.expect("failed to subscribe"); warn!(context, "could not subscribe to {:?}: {:?}", mvbox, err);
}
} }
} }
context context
.sql .sql
.set_raw_config(context, "configured_inbox_folder", Some("INBOX")) .set_raw_config(context, "configured_inbox_folder", Some("INBOX"))?;
.ok();
if let Some(ref mvbox_folder) = mvbox_folder { if let Some(ref mvbox_folder) = mvbox_folder {
context context.sql.set_raw_config(
.sql context,
.set_raw_config(context, "configured_mvbox_folder", Some(mvbox_folder)) "configured_mvbox_folder",
.ok(); Some(mvbox_folder),
)?;
} }
if let Some(ref sentbox_folder) = sentbox_folder { if let Some(ref sentbox_folder) = sentbox_folder {
context context.sql.set_raw_config(
.sql
.set_raw_config(
context, context,
"configured_sentbox_folder", "configured_sentbox_folder",
Some(sentbox_folder.name()), Some(sentbox_folder.name()),
) )?;
.ok();
} }
context context
.sql .sql
.set_raw_config_int(context, "folders_configured", 3) .set_raw_config_int(context, "folders_configured", 3)?;
.ok();
} }
info!(context, "FINISHED configuring IMAP-folders."); info!(context, "FINISHED configuring IMAP-folders.");
Ok(())
}) })
} }

View File

@@ -228,13 +228,10 @@ impl Job {
let imap_inbox = &context.inbox_thread.read().unwrap().imap; let imap_inbox = &context.inbox_thread.read().unwrap().imap;
if let Ok(msg) = Message::load_from_db(context, MsgId::new(self.foreign_id)) { if let Ok(msg) = Message::load_from_db(context, MsgId::new(self.foreign_id)) {
if context if let Err(err) = imap_inbox.ensure_configured_folders(context, true) {
.sql self.try_again_later(TryAgain::StandardDelay, None);
.get_raw_config_int(context, "folders_configured") warn!(context, "could not configure folders: {:?}", err);
.unwrap_or_default() return;
< 3
{
imap_inbox.configure_folders(context, true);
} }
let dest_folder = context let dest_folder = context
.sql .sql
@@ -355,13 +352,10 @@ impl Job {
return; return;
} }
if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() { if 0 != self.param.get_int(Param::AlsoMove).unwrap_or_default() {
if context if let Err(err) = imap_inbox.ensure_configured_folders(context, true) {
.sql self.try_again_later(TryAgain::StandardDelay, None);
.get_raw_config_int(context, "folders_configured") warn!(context, "configuring folders failed: {:?}", err);
.unwrap_or_default() return;
< 3
{
imap_inbox.configure_folders(context, true);
} }
let dest_folder = context let dest_folder = context
.sql .sql