From e9a80b32ac791b459192f71f5f1cfb6861babd95 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Wed, 26 Aug 2020 20:06:06 +0300 Subject: [PATCH] melib/imap: small cleanups --- melib/src/backends/imap.rs | 23 +++---- melib/src/backends/imap/watch.rs | 108 ++++++++++++------------------- 2 files changed, 50 insertions(+), 81 deletions(-) diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index 55c261651..b923136d9 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -466,6 +466,10 @@ impl MailBackend for ImapType { let uid_store = self.uid_store.clone(); let connection = self.connection.clone(); Ok(Box::pin(async move { + let mut response = String::with_capacity(8 * 1024); + let mut conn = connection.lock().await; + conn.select_mailbox(mailbox_hash, &mut response, true) + .await?; let path = { let mailboxes = uid_store.mailboxes.lock().await; @@ -481,8 +485,6 @@ impl MailBackend for ImapType { mailbox.imap_path().to_string() }; - let mut response = String::with_capacity(8 * 1024); - let mut conn = connection.lock().await; let flags = flags.unwrap_or_else(Flag::empty); let has_literal_plus: bool = uid_store .capabilities @@ -556,7 +558,7 @@ impl MailBackend for ImapType { .ok_or_else(|| MeliError::new("Destination mailbox not found"))?; if !mailbox.permissions.lock().unwrap().create_messages { return Err(MeliError::new(format!( - "You are not allowed to delete messages from mailbox {}", + "You are not allowed to create messages in mailbox {}", mailbox.path() ))); } @@ -804,6 +806,7 @@ impl MailBackend for ImapType { let mut response = String::with_capacity(8 * 1024); { let mut conn_lck = connection.lock().await; + conn_lck.unselect().await?; conn_lck .send_command(format!("CREATE \"{}\"", path,).as_bytes()) @@ -835,11 +838,9 @@ impl MailBackend for ImapType { let new_mailbox_fut = self.mailboxes(); Ok(Box::pin(async move { let imap_path: String; - let no_select: bool; let is_subscribed: bool; { let mailboxes = uid_store.mailboxes.lock().await; - no_select = mailboxes[&mailbox_hash].no_select; is_subscribed = mailboxes[&mailbox_hash].is_subscribed(); imap_path = mailboxes[&mailbox_hash].imap_path().to_string(); let permissions = mailboxes[&mailbox_hash].permissions(); @@ -850,15 +851,9 @@ impl MailBackend for ImapType { let mut response = String::with_capacity(8 * 1024); { let mut conn_lck = connection.lock().await; - let current_mailbox = conn_lck.stream.as_ref()?.current_mailbox; - if !no_select - && (current_mailbox == MailboxSelection::Examine(mailbox_hash) - || current_mailbox == MailboxSelection::Select(mailbox_hash)) - { - /* make sure mailbox is not selected before it gets deleted, otherwise - * connection gets dropped by server */ - conn_lck.unselect().await?; - } + /* make sure mailbox is not selected before it gets deleted, otherwise + * connection gets dropped by server */ + conn_lck.unselect().await?; if is_subscribed { conn_lck .send_command(format!("UNSUBSCRIBE \"{}\"", &imap_path).as_bytes()) diff --git a/melib/src/backends/imap/watch.rs b/melib/src/backends/imap/watch.rs index 367a10b7b..0ec0b233b 100644 --- a/melib/src/backends/imap/watch.rs +++ b/melib/src/backends/imap/watch.rs @@ -33,11 +33,10 @@ pub async fn poll_with_examine(kit: ImapWatchKit) -> Result<()> { debug!("poll with examine"); let ImapWatchKit { mut conn, - main_conn, + main_conn: _, uid_store, } = kit; conn.connect().await?; - let mut response = String::with_capacity(8 * 1024); loop { let mailboxes: HashMap = { let mailboxes_lck = timeout(Duration::from_secs(3), uid_store.mailboxes.lock()).await?; @@ -46,11 +45,6 @@ pub async fn poll_with_examine(kit: ImapWatchKit) -> Result<()> { for (_, mailbox) in mailboxes { examine_updates(mailbox, &mut conn, &uid_store).await?; } - let mut main_conn = timeout(Duration::from_secs(3), main_conn.lock()).await?; - main_conn.send_command(b"NOOP").await?; - main_conn - .read_response(&mut response, RequiredResponses::empty()) - .await?; } } @@ -79,52 +73,36 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> { }; let mailbox_hash = mailbox.hash(); let mut response = String::with_capacity(8 * 1024); - conn.send_command(format!("SELECT \"{}\"", mailbox.imap_path()).as_bytes()) - .await?; - conn.read_response(&mut response, RequiredResponses::SELECT_REQUIRED) - .await?; + let select_response = conn + .select_mailbox(mailbox_hash, &mut response, true) + .await? + .unwrap(); debug!("select response {}", &response); { - let mut prev_exists = mailbox.exists.lock().unwrap(); - match protocol_parser::select_response(&response) { - Ok(ok) => { - { - let uidvalidities = uid_store.uidvalidity.lock().unwrap(); + let mut uidvalidities = uid_store.uidvalidity.lock().unwrap(); - if let Some(v) = uidvalidities.get(&mailbox_hash) { - if *v != ok.uidvalidity { - conn.add_refresh_event(RefreshEvent { - account_hash: uid_store.account_hash, - mailbox_hash, - kind: RefreshEventKind::Rescan, - }); - prev_exists.clear(); - /* - uid_store.uid_index.lock().unwrap().clear(); - uid_store.hash_index.lock().unwrap().clear(); - uid_store.byte_cache.lock().unwrap().clear(); - */ - } - } else { - conn.add_refresh_event(RefreshEvent { - account_hash: uid_store.account_hash, - mailbox_hash, - kind: RefreshEventKind::Rescan, - }); - return Err(MeliError::new(format!( - "Unknown mailbox: {} {}", - mailbox.path(), - mailbox_hash - ))); - } - } - debug!(&ok); + if let Some(v) = uidvalidities.get(&mailbox_hash) { + if *v != select_response.uidvalidity { + let cache_handle = cache::CacheHandle::get(uid_store.clone())?; + cache_handle.clear( + mailbox_hash, + select_response.uidvalidity, + select_response.highestmodseq.and_then(|i| i.ok()), + )?; + conn.add_refresh_event(RefreshEvent { + account_hash: uid_store.account_hash, + mailbox_hash, + kind: RefreshEventKind::Rescan, + }); + /* + uid_store.uid_index.lock().unwrap().clear(); + uid_store.hash_index.lock().unwrap().clear(); + uid_store.byte_cache.lock().unwrap().clear(); + */ } - Err(e) => { - debug!("{:?}", e); - return Err(e).chain_err_summary(|| "could not select mailbox"); - } - }; + } else { + uidvalidities.insert(mailbox_hash, select_response.uidvalidity); + } } conn.send_command(b"IDLE").await?; let mut blockn = ImapBlockingConnection::from(conn); @@ -134,7 +112,7 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> { const _26_MINS: std::time::Duration = std::time::Duration::from_secs(26 * 60); /* duration interval to check other mailboxes for changes */ const _5_MINS: std::time::Duration = std::time::Duration::from_secs(5 * 60); - while let Some(line) = blockn.as_stream().await { + while let Some(line) = timeout(Duration::from_secs(35 * 60), blockn.as_stream()).await? { let now = std::time::Instant::now(); if now.duration_since(beat) >= _26_MINS { let mut main_conn_lck = timeout(Duration::from_secs(3), main_conn.lock()).await?; @@ -158,13 +136,18 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> { timeout(Duration::from_secs(3), uid_store.mailboxes.lock()).await?; mailboxes_lck.clone() }; - for (_, mailbox) in mailboxes { + for (h, mailbox) in mailboxes { + if mailbox_hash == h { + continue; + } examine_updates(mailbox, &mut conn, &uid_store).await?; } watch = now; } { - let mut conn = timeout(Duration::from_secs(3), main_conn.lock()).await?; + let mut conn = timeout(Duration::from_secs(10), main_conn.lock()).await?; + conn.examine_mailbox(mailbox_hash, &mut response, false) + .await?; conn.process_untagged(to_str!(&line)).await?; } *uid_store.is_online.lock().unwrap() = (Instant::now(), Ok(())); @@ -201,14 +184,14 @@ pub async fn examine_updates( } } else { let mut response = String::with_capacity(8 * 1024); - conn.examine_mailbox(mailbox_hash, &mut response, true) - .await?; + let select_response = conn + .examine_mailbox(mailbox_hash, &mut response, true) + .await? + .unwrap(); *uid_store.is_online.lock().unwrap() = (Instant::now(), Ok(())); - let select_response = protocol_parser::select_response(&response) - .chain_err_summary(|| "could not select mailbox")?; debug!(&select_response); { - let uidvalidities = uid_store.uidvalidity.lock().unwrap(); + let mut uidvalidities = uid_store.uidvalidity.lock().unwrap(); if let Some(v) = uidvalidities.get(&mailbox_hash) { if *v != select_response.uidvalidity { @@ -231,16 +214,7 @@ pub async fn examine_updates( return Ok(()); } } else { - conn.add_refresh_event(RefreshEvent { - account_hash: uid_store.account_hash, - mailbox_hash, - kind: RefreshEventKind::Rescan, - }); - return Err(MeliError::new(format!( - "Unknown mailbox: {} {}", - mailbox.path(), - mailbox_hash - ))); + uidvalidities.insert(mailbox_hash, select_response.uidvalidity); } } let mut cache_handle = cache::CacheHandle::get(uid_store.clone())?;