From 8ec0da4fbd14eee7d71994940d43b199c4dc9e47 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Mon, 27 Jul 2020 14:59:49 +0300 Subject: [PATCH] melib/imap: add conf toggle flags for IMAP extensions --- meli.conf.5 | 5 +++++ melib/src/backends/imap.rs | 26 +++++++++++++++++------- melib/src/backends/imap/connection.rs | 29 +++++++++++++++++++-------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/meli.conf.5 b/meli.conf.5 index 4ec93c49..370762c0 100644 --- a/meli.conf.5 +++ b/meli.conf.5 @@ -230,6 +230,11 @@ If port is 993 and use_starttls is unspecified, it becomes false by default. Do not validate TLS certificates. .\" default value .Pq Em false +.It Ic use_idle Ar boolean +.Pq Em optional +Use IDLE extension. +.\" default value +.Pq Em true .El .Ss JMAP only JMAP specific options diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index 5b125868..4923859e 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -335,13 +335,20 @@ impl MailBackend for ImapType { let main_conn = self.connection.clone(); *self.uid_store.sender.write().unwrap() = Some(sender); let uid_store = self.uid_store.clone(); + let has_idle: bool = match self.server_conf.protocol { + ImapProtocol::IMAP { + extension_use: ImapExtensionUse { idle, .. }, + } => { + idle && uid_store + .capabilities + .lock() + .unwrap() + .iter() + .any(|cap| cap.eq_ignore_ascii_case(b"IDLE")) + } + _ => false, + }; Ok(Box::pin(async move { - let has_idle: bool = uid_store - .capabilities - .lock() - .unwrap() - .iter() - .any(|cap| cap.eq_ignore_ascii_case(b"IDLE")); debug!(has_idle); let kit = ImapWatchKit { conn, @@ -1071,7 +1078,11 @@ impl ImapType { use_tls, use_starttls, danger_accept_invalid_certs, - protocol: ImapProtocol::IMAP, + protocol: ImapProtocol::IMAP { + extension_use: ImapExtensionUse { + idle: get_conf_val!(s["use_idle"], true)?, + }, + }, }; let account_hash = { let mut hasher = DefaultHasher::new(); @@ -1257,6 +1268,7 @@ impl ImapType { } get_conf_val!(s["danger_accept_invalid_certs"], false)?; get_conf_val!(s["X_header_caching"], false)?; + get_conf_val!(s["use_idle"], true)?; Ok(()) } diff --git a/melib/src/backends/imap/connection.rs b/melib/src/backends/imap/connection.rs index aa268562..e8f65744 100644 --- a/melib/src/backends/imap/connection.rs +++ b/melib/src/backends/imap/connection.rs @@ -38,12 +38,25 @@ use std::time::Instant; use super::protocol_parser; use super::{Capabilities, ImapServerConf, UIDStore}; -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy)] pub enum ImapProtocol { - IMAP, + IMAP { extension_use: ImapExtensionUse }, ManageSieve, } +#[derive(Debug, Clone, Copy)] +pub struct ImapExtensionUse { + pub idle: bool, +} + +impl Default for ImapExtensionUse { + fn default() -> Self { + Self { + idle: true, + } + } +} + #[derive(Debug)] pub struct ImapStream { pub cmd_id: usize, @@ -116,7 +129,7 @@ impl ImapStream { if server_conf.use_starttls { let mut buf = vec![0; 1024]; match server_conf.protocol { - ImapProtocol::IMAP => socket + ImapProtocol::IMAP { .. } => socket .write_all(format!("M{} STARTTLS\r\n", cmd_id).as_bytes()) .await .chain_err_kind(crate::error::ErrorKind::Network)?, @@ -142,7 +155,7 @@ impl ImapStream { .chain_err_kind(crate::error::ErrorKind::Network)?; response.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..len]) }); match server_conf.protocol { - ImapProtocol::IMAP => { + ImapProtocol::IMAP { .. } => { if response.starts_with("* OK ") && response.find("\r\n").is_some() { if let Some(pos) = response.as_bytes().find(b"\r\n") { response.drain(0..pos + 2); @@ -338,7 +351,7 @@ impl ImapStream { pub async fn read_response(&mut self, ret: &mut String) -> Result<()> { let id = match self.protocol { - ImapProtocol::IMAP => format!("M{} ", self.cmd_id - 1), + ImapProtocol::IMAP { .. } => format!("M{} ", self.cmd_id - 1), ImapProtocol::ManageSieve => String::new(), }; self.read_lines(ret, &id, true).await?; @@ -408,7 +421,7 @@ impl ImapStream { if let Err(err) = try_await(async move { let command = command.trim(); match self.protocol { - ImapProtocol::IMAP => { + ImapProtocol::IMAP { .. } => { self.stream.write_all(b"M").await?; self.stream .write_all(self.cmd_id.to_string().as_bytes()) @@ -422,7 +435,7 @@ impl ImapStream { self.stream.write_all(command).await?; self.stream.write_all(b"\r\n").await?; match self.protocol { - ImapProtocol::IMAP => { + ImapProtocol::IMAP { .. } => { debug!("sent: M{} {}", self.cmd_id - 1, unsafe { std::str::from_utf8_unchecked(command) }); @@ -514,7 +527,7 @@ impl ImapConnection { self.stream.as_mut()?.read_response(&mut response).await?; match self.server_conf.protocol { - ImapProtocol::IMAP => { + ImapProtocol::IMAP { .. } => { let r: ImapResponse = ImapResponse::from(&response); match r { ImapResponse::Bye(ref response_code) => {