imap: simplify select_folder() interface

Accept AsRef<str> instead of Option<impl AsRef<str>>.

There is no need to pass None to force expunge anymore.
This commit is contained in:
Alexander Krotov
2020-04-30 22:33:55 +03:00
committed by link2xt
parent c41a6b87b8
commit e8763e936d
4 changed files with 42 additions and 46 deletions

View File

@@ -59,7 +59,7 @@ impl Imap {
task::block_on(async move { self.config.read().await.can_idle }) task::block_on(async move { self.config.read().await.can_idle })
} }
pub fn idle(&self, context: &Context, watch_folder: Option<String>) -> Result<()> { pub fn idle(&self, context: &Context, watch_folder: String) -> Result<()> {
task::block_on(async move { task::block_on(async move {
if !self.can_idle() { if !self.can_idle() {
return Err(Error::IdleAbilityMissing); return Err(Error::IdleAbilityMissing);
@@ -67,7 +67,7 @@ impl Imap {
self.setup_handle_if_needed(context).await?; self.setup_handle_if_needed(context).await?;
self.select_folder(context, watch_folder.clone()).await?; self.select_folder(context, watch_folder).await?;
let session = self.session.lock().await.take(); let session = self.session.lock().await.take();
let timeout = Duration::from_secs(23 * 60); let timeout = Duration::from_secs(23 * 60);

View File

@@ -476,7 +476,7 @@ impl Imap {
folder: &str, folder: &str,
) -> Result<(u32, u32)> { ) -> Result<(u32, u32)> {
task::block_on(async move { task::block_on(async move {
self.select_folder(context, Some(folder)).await?; self.select_folder(context, folder).await?;
// compare last seen UIDVALIDITY against the current one // compare last seen UIDVALIDITY against the current one
let (uid_validity, last_seen_uid) = self.get_config_last_seen_uid(context, &folder); let (uid_validity, last_seen_uid) = self.get_config_last_seen_uid(context, &folder);
@@ -912,7 +912,7 @@ impl Imap {
return Some(ImapActionResult::RetryLater); return Some(ImapActionResult::RetryLater);
} }
} }
match self.select_folder(context, Some(&folder)).await { match self.select_folder(context, &folder).await {
Ok(()) => None, Ok(()) => None,
Err(select_folder::Error::ConnectionLost) => { Err(select_folder::Error::ConnectionLost) => {
warn!(context, "Lost imap connection"); warn!(context, "Lost imap connection");
@@ -1183,7 +1183,7 @@ impl Imap {
error!(context, "could not setup imap connection: {}", err); error!(context, "could not setup imap connection: {}", err);
return; return;
} }
if let Err(err) = self.select_folder(context, Some(&folder)).await { if let Err(err) = self.select_folder(context, &folder).await {
error!( error!(
context, context,
"Could not select {} for expunging: {}", folder, err "Could not select {} for expunging: {}", folder, err
@@ -1201,7 +1201,7 @@ impl Imap {
// we now trigger expunge to actually delete messages // we now trigger expunge to actually delete messages
self.config.write().await.selected_folder_needs_expunge = true; self.config.write().await.selected_folder_needs_expunge = true;
match self.select_folder::<String>(context, None).await { match self.select_folder(context, &folder).await {
Ok(()) => { Ok(()) => {
emit_event!(context, Event::ImapFolderEmptied(folder.to_string())); emit_event!(context, Event::ImapFolderEmptied(folder.to_string()));
} }

View File

@@ -56,7 +56,7 @@ impl Imap {
pub(super) async fn select_folder<S: AsRef<str>>( pub(super) async fn select_folder<S: AsRef<str>>(
&self, &self,
context: &Context, context: &Context,
folder: Option<S>, folder: S,
) -> Result<()> { ) -> Result<()> {
if self.session.lock().await.is_none() { if self.session.lock().await.is_none() {
let mut cfg = self.config.write().await; let mut cfg = self.config.write().await;
@@ -71,46 +71,41 @@ impl Imap {
self.close_folder(context).await?; self.close_folder(context).await?;
} }
let folder_str: Option<&str> = folder.as_ref().map(|x| x.as_ref()); if self.config.read().await.selected_folder.as_deref() == Some(folder.as_ref()) {
if self.config.read().await.selected_folder.as_deref() == folder_str {
return Ok(()); return Ok(());
} }
// select new folder // select new folder
if let Some(ref folder) = folder { if let Some(ref mut session) = &mut *self.session.lock().await {
if let Some(ref mut session) = &mut *self.session.lock().await { let res = session.select(&folder).await;
let res = session.select(folder).await;
// https://tools.ietf.org/html/rfc3501#section-6.3.1 // https://tools.ietf.org/html/rfc3501#section-6.3.1
// says that if the server reports select failure we are in // says that if the server reports select failure we are in
// authenticated (not-select) state. // authenticated (not-select) state.
match res { match res {
Ok(mailbox) => { Ok(mailbox) => {
let mut config = self.config.write().await; let mut config = self.config.write().await;
config.selected_folder = Some(folder.as_ref().to_string()); config.selected_folder = Some(folder.as_ref().to_string());
config.selected_mailbox = Some(mailbox); config.selected_mailbox = Some(mailbox);
Ok(()) Ok(())
} }
Err(async_imap::error::Error::ConnectionLost) => { Err(async_imap::error::Error::ConnectionLost) => {
self.trigger_reconnect(); self.trigger_reconnect();
self.config.write().await.selected_folder = None; self.config.write().await.selected_folder = None;
Err(Error::ConnectionLost) Err(Error::ConnectionLost)
} }
Err(async_imap::error::Error::Validate(_)) => { Err(async_imap::error::Error::Validate(_)) => {
Err(Error::BadFolderName(folder.as_ref().to_string())) Err(Error::BadFolderName(folder.as_ref().to_string()))
} }
Err(err) => { Err(err) => {
self.config.write().await.selected_folder = None; self.config.write().await.selected_folder = None;
self.trigger_reconnect(); self.trigger_reconnect();
Err(Error::Other(err.to_string())) Err(Error::Other(err.to_string()))
}
} }
} else {
Err(Error::NoSession)
} }
} else { } else {
Ok(()) Err(Error::NoSession)
} }
} }
} }

View File

@@ -173,14 +173,15 @@ impl JobThread {
if !self.imap.can_idle() { if !self.imap.can_idle() {
true // we have to do fake_idle true // we have to do fake_idle
} else { } else {
let watch_folder = self.get_watch_folder(context); if let Some(watch_folder) = self.get_watch_folder(context) {
info!(context, "{} started...", prefix); info!(context, "{} started...", prefix);
let res = self.imap.idle(context, watch_folder); let res = self.imap.idle(context, watch_folder);
info!(context, "{} ended...", prefix); info!(context, "{} ended...", prefix);
if let Err(err) = res { if let Err(err) = res {
warn!(context, "{} failed: {} -> reconnecting", prefix, err); warn!(context, "{} failed: {} -> reconnecting", prefix, err);
// something is borked, let's start afresh on the next occassion // something is Label { Label }orked, let's start afresh on the next occassion
self.imap.disconnect(context); self.imap.disconnect(context);
}
} }
false false
} }