From 0c08cb737ceaa5c738712905c7d57f956d449ed0 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Tue, 4 Oct 2022 15:53:01 +0300 Subject: [PATCH] melib/jmap: mark mailboxes as subscribed on personal accounts The spec https://jmap.io/spec-mail.html#mailboxes says a mailbox property `isSubscribed` should be considered true if the account is marked as `isPersonal`. Closes #157 JMAP incompatible with Stalwart server #157 https://git.meli.delivery/meli/meli/issues/157 --- melib/src/backends/jmap/connection.rs | 31 +++++++++++++++++++++------ melib/src/backends/jmap/mailbox.rs | 2 ++ melib/src/backends/jmap/protocol.rs | 12 ++++++++++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/melib/src/backends/jmap/connection.rs b/melib/src/backends/jmap/connection.rs index aaaf3a5a8..1cff3a957 100644 --- a/melib/src/backends/jmap/connection.rs +++ b/melib/src/backends/jmap/connection.rs @@ -21,6 +21,7 @@ use super::*; use isahc::config::Configurable; +use std::sync::MutexGuard; #[derive(Debug)] pub struct JmapConnection { @@ -56,19 +57,31 @@ impl JmapConnection { if self.store.online_status.lock().await.1.is_ok() { return Ok(()); } - let mut jmap_session_resource_url = - if self.server_conf.server_hostname.starts_with("https://") { - self.server_conf.server_hostname.to_string() - } else { - format!("https://{}", &self.server_conf.server_hostname) - }; + let mut jmap_session_resource_url = self.server_conf.server_hostname.to_string(); if self.server_conf.server_port != 443 { jmap_session_resource_url.push(':'); jmap_session_resource_url.push_str(&self.server_conf.server_port.to_string()); } jmap_session_resource_url.push_str("/.well-known/jmap"); - let mut req = self.client.get_async(&jmap_session_resource_url).await?; + let mut req = self.client.get_async(&jmap_session_resource_url).await.map_err(|err| { + let err = MeliError::new(format!("Could not connect to JMAP server endpoint for {}. Is your server hostname setting correct? (i.e. \"jmap.mailserver.org\") (Note: only session resource discovery via /.well-known/jmap is supported. DNS SRV records are not suppported.)\nError connecting to server: {}", &self.server_conf.server_hostname, &err)).set_source(Some(Arc::new(err))); + //*self.store.online_status.lock().await = (Instant::now(), Err(err.clone())); + err + })?; + + if !req.status().is_success() { + let kind: crate::error::NetworkErrorKind = req.status().into(); + let res_text = req.text().await.unwrap_or_default(); + let err = MeliError::new(format!( + "Could not connect to JMAP server endpoint for {}. Reply from server: {}", + &self.server_conf.server_hostname, res_text + )) + .set_kind(kind.into()); + *self.store.online_status.lock().await = (Instant::now(), Err(err.clone())); + return Err(err); + } + let res_text = req.text().await?; let session: JmapSession = match serde_json::from_str(&res_text) { @@ -105,6 +118,10 @@ impl JmapConnection { self.session.lock().unwrap().primary_accounts["urn:ietf:params:jmap:mail"].clone() } + pub fn session_guard(&'_ self) -> MutexGuard<'_, JmapSession> { + self.session.lock().unwrap() + } + pub fn add_refresh_event(&self, event: RefreshEvent) { (self.store.event_consumer)(self.store.account_hash, BackendEvent::Refresh(event)); } diff --git a/melib/src/backends/jmap/mailbox.rs b/melib/src/backends/jmap/mailbox.rs index f20b2ed77..abeae0bf1 100644 --- a/melib/src/backends/jmap/mailbox.rs +++ b/melib/src/backends/jmap/mailbox.rs @@ -95,9 +95,11 @@ impl BackendMailbox for JmapMailbox { None => SpecialUsageMailbox::Normal, } } + fn is_subscribed(&self) -> bool { self.is_subscribed } + fn set_is_subscribed(&mut self, new_val: bool) -> Result<()> { self.is_subscribed = new_val; // FIXME: jmap subscribe diff --git a/melib/src/backends/jmap/protocol.rs b/melib/src/backends/jmap/protocol.rs index 90033c8fc..a8bd2ff4d 100644 --- a/melib/src/backends/jmap/protocol.rs +++ b/melib/src/backends/jmap/protocol.rs @@ -108,6 +108,16 @@ pub async fn get_mailboxes(conn: &JmapConnection) -> Result { list, account_id, .. } = m; + // Is account set as `personal`? (`isPersonal` property). Then, even if `isSubscribed` is false + // on a mailbox, it should be regarded as subscribed. + let is_personal: bool = { + let session = conn.session_guard(); + session + .accounts + .get(&account_id) + .map(|acc| acc.is_personal) + .unwrap_or(false) + }; *conn.store.account_id.lock().unwrap() = account_id; let mut ret: HashMap = list .into_iter() @@ -141,7 +151,7 @@ pub async fn get_mailboxes(conn: &JmapConnection) -> Result