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 })
}
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 {
if !self.can_idle() {
return Err(Error::IdleAbilityMissing);
@@ -67,7 +67,7 @@ impl Imap {
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 timeout = Duration::from_secs(23 * 60);

View File

@@ -476,7 +476,7 @@ impl Imap {
folder: &str,
) -> Result<(u32, u32)> {
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
let (uid_validity, last_seen_uid) = self.get_config_last_seen_uid(context, &folder);
@@ -912,7 +912,7 @@ impl Imap {
return Some(ImapActionResult::RetryLater);
}
}
match self.select_folder(context, Some(&folder)).await {
match self.select_folder(context, &folder).await {
Ok(()) => None,
Err(select_folder::Error::ConnectionLost) => {
warn!(context, "Lost imap connection");
@@ -1183,7 +1183,7 @@ impl Imap {
error!(context, "could not setup imap connection: {}", err);
return;
}
if let Err(err) = self.select_folder(context, Some(&folder)).await {
if let Err(err) = self.select_folder(context, &folder).await {
error!(
context,
"Could not select {} for expunging: {}", folder, err
@@ -1201,7 +1201,7 @@ impl Imap {
// we now trigger expunge to actually delete messages
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(()) => {
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>>(
&self,
context: &Context,
folder: Option<S>,
folder: S,
) -> Result<()> {
if self.session.lock().await.is_none() {
let mut cfg = self.config.write().await;
@@ -71,46 +71,41 @@ impl Imap {
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() == folder_str {
if self.config.read().await.selected_folder.as_deref() == Some(folder.as_ref()) {
return Ok(());
}
// select new folder
if let Some(ref folder) = folder {
if let Some(ref mut session) = &mut *self.session.lock().await {
let res = session.select(folder).await;
if let Some(ref mut session) = &mut *self.session.lock().await {
let res = session.select(&folder).await;
// https://tools.ietf.org/html/rfc3501#section-6.3.1
// says that if the server reports select failure we are in
// authenticated (not-select) state.
// https://tools.ietf.org/html/rfc3501#section-6.3.1
// says that if the server reports select failure we are in
// authenticated (not-select) state.
match res {
Ok(mailbox) => {
let mut config = self.config.write().await;
config.selected_folder = Some(folder.as_ref().to_string());
config.selected_mailbox = Some(mailbox);
Ok(())
}
Err(async_imap::error::Error::ConnectionLost) => {
self.trigger_reconnect();
self.config.write().await.selected_folder = None;
Err(Error::ConnectionLost)
}
Err(async_imap::error::Error::Validate(_)) => {
Err(Error::BadFolderName(folder.as_ref().to_string()))
}
Err(err) => {
self.config.write().await.selected_folder = None;
self.trigger_reconnect();
Err(Error::Other(err.to_string()))
}
match res {
Ok(mailbox) => {
let mut config = self.config.write().await;
config.selected_folder = Some(folder.as_ref().to_string());
config.selected_mailbox = Some(mailbox);
Ok(())
}
Err(async_imap::error::Error::ConnectionLost) => {
self.trigger_reconnect();
self.config.write().await.selected_folder = None;
Err(Error::ConnectionLost)
}
Err(async_imap::error::Error::Validate(_)) => {
Err(Error::BadFolderName(folder.as_ref().to_string()))
}
Err(err) => {
self.config.write().await.selected_folder = None;
self.trigger_reconnect();
Err(Error::Other(err.to_string()))
}
} else {
Err(Error::NoSession)
}
} else {
Ok(())
Err(Error::NoSession)
}
}
}

View File

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