From 352f7505fcbcb92581124dcfdff4a30e7c274fe4 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sun, 13 Sep 2020 00:24:26 +0300 Subject: [PATCH] melib/imap: don't poll \Noselect mailboxes for updates --- melib/src/backends/imap/connection.rs | 40 +++++++++++++++++++-------- melib/src/backends/imap/watch.rs | 26 +++++++++-------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs index 6a205bef8..5c17a9163 100644 --- a/melib/src/backends/imap/connection.rs +++ b/melib/src/backends/imap/connection.rs @@ -781,10 +781,21 @@ impl ImapConnection { { return Ok(None); } - let (imap_path, permissions) = { + let (imap_path, no_select, permissions) = { let m = &self.uid_store.mailboxes.lock().await[&mailbox_hash]; - (m.imap_path().to_string(), m.permissions.clone()) + ( + m.imap_path().to_string(), + m.no_select, + m.permissions.clone(), + ) }; + if no_select { + return Err(MeliError::new(format!( + "Trying to select a \\NoSelect mailbox: {}", + &imap_path + )) + .set_kind(crate::error::ErrorKind::Bug)); + } self.send_command(format!("SELECT \"{}\"", imap_path).as_bytes()) .await?; self.read_response(ret, RequiredResponses::SELECT_REQUIRED) @@ -856,18 +867,25 @@ impl ImapConnection { { return Ok(None); } - self.send_command( - format!( - "EXAMINE \"{}\"", - self.uid_store.mailboxes.lock().await[&mailbox_hash].imap_path() - ) - .as_bytes(), - ) - .await?; + let (imap_path, no_select) = { + let m = &self.uid_store.mailboxes.lock().await[&mailbox_hash]; + (m.imap_path().to_string(), m.no_select) + }; + if no_select { + return Err(MeliError::new(format!( + "Trying to examine a \\NoSelect mailbox: {}", + &imap_path + )) + .set_kind(crate::error::ErrorKind::Bug)); + } + self.send_command(format!("EXAMINE \"{}\"", &imap_path).as_bytes()) + .await?; self.read_response(ret, RequiredResponses::EXAMINE_REQUIRED) .await?; debug!("examine response {}", ret); - let select_response = protocol_parser::select_response(&ret)?; + let select_response = protocol_parser::select_response(&ret).chain_err_summary(|| { + format!("Could not parse select response for mailbox {}", imap_path) + })?; self.stream.as_mut()?.current_mailbox = MailboxSelection::Examine(mailbox_hash); if !self .uid_store diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs index 786b32c70..aaba948ff 100644 --- a/melib/src/backends/imap/watch.rs +++ b/melib/src/backends/imap/watch.rs @@ -37,14 +37,16 @@ pub async fn poll_with_examine(kit: ImapWatchKit) -> Result<()> { uid_store, } = kit; conn.connect().await?; + let mailboxes: HashMap = { + let mailboxes_lck = timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?; + mailboxes_lck.clone() + }; loop { - let mailboxes: HashMap = { - let mailboxes_lck = timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?; - mailboxes_lck.clone() - }; - for (_, mailbox) in mailboxes { + for (_, mailbox) in mailboxes.clone() { examine_updates(mailbox, &mut conn, &uid_store).await?; } + //FIXME: make sleep duration configurable + smol::Timer::after(std::time::Duration::from_secs(3 * 60)).await; } } @@ -105,6 +107,10 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> { uidvalidities.insert(mailbox_hash, select_response.uidvalidity); } } + let mailboxes: HashMap = { + let mailboxes_lck = timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?; + mailboxes_lck.clone() + }; conn.send_command(b"IDLE").await?; let mut blockn = ImapBlockingConnection::from(conn); let mut beat = std::time::Instant::now(); @@ -134,12 +140,7 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> { if now.duration_since(watch) >= _5_MINS { /* Time to poll all inboxes */ let mut conn = timeout(uid_store.timeout, main_conn.lock()).await?; - let mailboxes: HashMap = { - let mailboxes_lck = - timeout(uid_store.timeout, uid_store.mailboxes.lock()).await?; - mailboxes_lck.clone() - }; - for (h, mailbox) in mailboxes { + for (h, mailbox) in mailboxes.clone() { if mailbox_hash == h { continue; } @@ -193,6 +194,9 @@ pub async fn examine_updates( conn: &mut ImapConnection, uid_store: &Arc, ) -> Result<()> { + if mailbox.no_select { + return Ok(()); + } let mailbox_hash = mailbox.hash(); debug!("examining mailbox {} {}", mailbox_hash, mailbox.path()); if let Some(new_envelopes) = conn.resync(mailbox_hash).await? {