diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs index a68ca3ae..e349b2c8 100644 --- a/melib/src/backends/imap.rs +++ b/melib/src/backends/imap.rs @@ -41,7 +41,7 @@ use crate::conf::AccountSettings; use crate::email::*; use crate::error::{MeliError, Result}; use fnv::{FnvHashMap, FnvHashSet}; -use std::collections::hash_map::DefaultHasher; +use std::collections::{hash_map::DefaultHasher, BTreeMap}; use std::hash::Hasher; use std::str::FromStr; use std::sync::{Arc, Mutex, RwLock}; @@ -128,6 +128,8 @@ pub struct ImapType { connection: Arc>, server_conf: ImapServerConf, uid_store: Arc, + can_create_flags: Arc>, + tag_index: Arc>>, folders: Arc>>, } @@ -151,6 +153,7 @@ impl MailBackend for ImapType { let handle = { let tx = w.tx(); let uid_store = self.uid_store.clone(); + let can_create_flags = self.can_create_flags.clone(); let folder_path = folder.path().to_string(); let folder_hash = folder.hash(); let (permissions, folder_exists) = { @@ -176,6 +179,7 @@ impl MailBackend for ImapType { let examine_response = protocol_parser::select_response(&response); exit_on_error!(&tx, examine_response); let examine_response = examine_response.unwrap(); + *can_create_flags.lock().unwrap() = examine_response.can_create_flags; debug!( "folder: {} examine_response: {:?}", folder_path, examine_response @@ -445,6 +449,14 @@ impl MailBackend for ImapType { fn as_any(&self) -> &dyn::std::any::Any { self } + + fn tags(&self) -> Option>>> { + if *self.can_create_flags.lock().unwrap() { + Some(self.tag_index.clone()) + } else { + None + } + } } impl ImapType { @@ -481,6 +493,8 @@ impl ImapType { server_conf, is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)), + can_create_flags: Arc::new(Mutex::new(false)), + tag_index: Arc::new(RwLock::new(Default::default())), folders: Arc::new(RwLock::new(Default::default())), connection: Arc::new(Mutex::new(connection)), uid_store: Arc::new(UIDStore { diff --git a/melib/src/backends/imap/protocol_parser.rs b/melib/src/backends/imap/protocol_parser.rs index 6bfd7263..dd8cfdaa 100644 --- a/melib/src/backends/imap/protocol_parser.rs +++ b/melib/src/backends/imap/protocol_parser.rs @@ -302,6 +302,8 @@ pub struct SelectResponse { pub uidvalidity: usize, pub uidnext: usize, pub permanentflags: Flag, + /// if SELECT returns \* we can set arbritary flags permanently. + pub can_create_flags: bool, pub read_only: bool, } @@ -332,27 +334,23 @@ pub fn select_response(input: &str) -> Result { let mut ret = SelectResponse::default(); for l in input.split("\r\n") { if l.starts_with("* ") && l.ends_with(" EXISTS") { - ret.exists = usize::from_str(&l["* ".len()..l.len() - " EXISTS".len()]).unwrap(); + ret.exists = usize::from_str(&l["* ".len()..l.len() - " EXISTS".len()])?; } else if l.starts_with("* ") && l.ends_with(" RECENT") { - ret.recent = usize::from_str(&l["* ".len()..l.len() - " RECENT".len()]).unwrap(); + ret.recent = usize::from_str(&l["* ".len()..l.len() - " RECENT".len()])?; } else if l.starts_with("* FLAGS (") { - ret.flags = flags(&l["* FLAGS (".len()..l.len() - ")".len()]) - .to_full_result() - .unwrap(); + ret.flags = flags(&l["* FLAGS (".len()..l.len() - ")".len()]).to_full_result()?; } else if l.starts_with("* OK [UNSEEN ") { - ret.unseen = - usize::from_str(&l["* OK [UNSEEN ".len()..l.find(']').unwrap()]).unwrap(); + ret.unseen = usize::from_str(&l["* OK [UNSEEN ".len()..l.find(']').unwrap()])?; } else if l.starts_with("* OK [UIDVALIDITY ") { ret.uidvalidity = - usize::from_str(&l["* OK [UIDVALIDITY ".len()..l.find(']').unwrap()]).unwrap(); + usize::from_str(&l["* OK [UIDVALIDITY ".len()..l.find(']').unwrap()])?; } else if l.starts_with("* OK [UIDNEXT ") { - ret.uidnext = - usize::from_str(&l["* OK [UIDNEXT ".len()..l.find(']').unwrap()]).unwrap(); + ret.uidnext = usize::from_str(&l["* OK [UIDNEXT ".len()..l.find(']').unwrap()])?; } else if l.starts_with("* OK [PERMANENTFLAGS (") { ret.permanentflags = flags(&l["* OK [PERMANENTFLAGS (".len()..l.find(')').unwrap()]) - .to_full_result() - .unwrap(); + .to_full_result()?; + ret.can_create_flags = l.contains("\\*"); } else if l.contains("OK [READ-WRITE]") { ret.read_only = false; } else if l.contains("OK [READ-ONLY]") { diff --git a/melib/src/error.rs b/melib/src/error.rs index fca37b08..25182a65 100644 --- a/melib/src/error.rs +++ b/melib/src/error.rs @@ -144,6 +144,13 @@ impl From for MeliError { } } +impl From for MeliError { + #[inline] + fn from(kind: std::num::ParseIntError) -> MeliError { + MeliError::new(format!("{}", kind)) + } +} + impl From<&str> for MeliError { #[inline] fn from(kind: &str) -> MeliError {