melib/imap: add conf toggle flags for IMAP extensions

memfd
Manos Pitsidianakis 2020-07-27 14:59:49 +03:00
parent 7bbfd188ef
commit 8ec0da4fbd
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
3 changed files with 45 additions and 15 deletions

View File

@ -230,6 +230,11 @@ If port is 993 and use_starttls is unspecified, it becomes false by default.
Do not validate TLS certificates. Do not validate TLS certificates.
.\" default value .\" default value
.Pq Em false .Pq Em false
.It Ic use_idle Ar boolean
.Pq Em optional
Use IDLE extension.
.\" default value
.Pq Em true
.El .El
.Ss JMAP only .Ss JMAP only
JMAP specific options JMAP specific options

View File

@ -335,13 +335,20 @@ impl MailBackend for ImapType {
let main_conn = self.connection.clone(); let main_conn = self.connection.clone();
*self.uid_store.sender.write().unwrap() = Some(sender); *self.uid_store.sender.write().unwrap() = Some(sender);
let uid_store = self.uid_store.clone(); 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 { 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); debug!(has_idle);
let kit = ImapWatchKit { let kit = ImapWatchKit {
conn, conn,
@ -1071,7 +1078,11 @@ impl ImapType {
use_tls, use_tls,
use_starttls, use_starttls,
danger_accept_invalid_certs, 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 account_hash = {
let mut hasher = DefaultHasher::new(); let mut hasher = DefaultHasher::new();
@ -1257,6 +1268,7 @@ impl ImapType {
} }
get_conf_val!(s["danger_accept_invalid_certs"], false)?; get_conf_val!(s["danger_accept_invalid_certs"], false)?;
get_conf_val!(s["X_header_caching"], false)?; get_conf_val!(s["X_header_caching"], false)?;
get_conf_val!(s["use_idle"], true)?;
Ok(()) Ok(())
} }

View File

@ -38,12 +38,25 @@ use std::time::Instant;
use super::protocol_parser; use super::protocol_parser;
use super::{Capabilities, ImapServerConf, UIDStore}; use super::{Capabilities, ImapServerConf, UIDStore};
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy)]
pub enum ImapProtocol { pub enum ImapProtocol {
IMAP, IMAP { extension_use: ImapExtensionUse },
ManageSieve, ManageSieve,
} }
#[derive(Debug, Clone, Copy)]
pub struct ImapExtensionUse {
pub idle: bool,
}
impl Default for ImapExtensionUse {
fn default() -> Self {
Self {
idle: true,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct ImapStream { pub struct ImapStream {
pub cmd_id: usize, pub cmd_id: usize,
@ -116,7 +129,7 @@ impl ImapStream {
if server_conf.use_starttls { if server_conf.use_starttls {
let mut buf = vec![0; 1024]; let mut buf = vec![0; 1024];
match server_conf.protocol { match server_conf.protocol {
ImapProtocol::IMAP => socket ImapProtocol::IMAP { .. } => socket
.write_all(format!("M{} STARTTLS\r\n", cmd_id).as_bytes()) .write_all(format!("M{} STARTTLS\r\n", cmd_id).as_bytes())
.await .await
.chain_err_kind(crate::error::ErrorKind::Network)?, .chain_err_kind(crate::error::ErrorKind::Network)?,
@ -142,7 +155,7 @@ impl ImapStream {
.chain_err_kind(crate::error::ErrorKind::Network)?; .chain_err_kind(crate::error::ErrorKind::Network)?;
response.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..len]) }); response.push_str(unsafe { std::str::from_utf8_unchecked(&buf[0..len]) });
match server_conf.protocol { match server_conf.protocol {
ImapProtocol::IMAP => { ImapProtocol::IMAP { .. } => {
if response.starts_with("* OK ") && response.find("\r\n").is_some() { if response.starts_with("* OK ") && response.find("\r\n").is_some() {
if let Some(pos) = response.as_bytes().find(b"\r\n") { if let Some(pos) = response.as_bytes().find(b"\r\n") {
response.drain(0..pos + 2); response.drain(0..pos + 2);
@ -338,7 +351,7 @@ impl ImapStream {
pub async fn read_response(&mut self, ret: &mut String) -> Result<()> { pub async fn read_response(&mut self, ret: &mut String) -> Result<()> {
let id = match self.protocol { 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(), ImapProtocol::ManageSieve => String::new(),
}; };
self.read_lines(ret, &id, true).await?; self.read_lines(ret, &id, true).await?;
@ -408,7 +421,7 @@ impl ImapStream {
if let Err(err) = try_await(async move { if let Err(err) = try_await(async move {
let command = command.trim(); let command = command.trim();
match self.protocol { match self.protocol {
ImapProtocol::IMAP => { ImapProtocol::IMAP { .. } => {
self.stream.write_all(b"M").await?; self.stream.write_all(b"M").await?;
self.stream self.stream
.write_all(self.cmd_id.to_string().as_bytes()) .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(command).await?;
self.stream.write_all(b"\r\n").await?; self.stream.write_all(b"\r\n").await?;
match self.protocol { match self.protocol {
ImapProtocol::IMAP => { ImapProtocol::IMAP { .. } => {
debug!("sent: M{} {}", self.cmd_id - 1, unsafe { debug!("sent: M{} {}", self.cmd_id - 1, unsafe {
std::str::from_utf8_unchecked(command) std::str::from_utf8_unchecked(command)
}); });
@ -514,7 +527,7 @@ impl ImapConnection {
self.stream.as_mut()?.read_response(&mut response).await?; self.stream.as_mut()?.read_response(&mut response).await?;
match self.server_conf.protocol { match self.server_conf.protocol {
ImapProtocol::IMAP => { ImapProtocol::IMAP { .. } => {
let r: ImapResponse = ImapResponse::from(&response); let r: ImapResponse = ImapResponse::from(&response);
match r { match r {
ImapResponse::Bye(ref response_code) => { ImapResponse::Bye(ref response_code) => {