From d9467d5fcd9543611ec8a034eb7e25d12a3dcc45 Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Mon, 28 Aug 2023 14:25:21 +0300 Subject: [PATCH] melib/jmap: save all core capabilities to session store We will need this in the future when we're going to support extra extensions like Blob and also now to support server submission. Signed-off-by: Manos Pitsidianakis --- melib/src/jmap/connection.rs | 3 +-- melib/src/jmap/mod.rs | 24 +++++++++++++++++------- melib/src/jmap/protocol.rs | 22 ++++++++++------------ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/melib/src/jmap/connection.rs b/melib/src/jmap/connection.rs index 5ba81cce..cce66eb0 100644 --- a/melib/src/jmap/connection.rs +++ b/melib/src/jmap/connection.rs @@ -184,8 +184,6 @@ impl JmapConnection { *self.store.online_status.lock().await = (Instant::now(), Err(err.clone())); return Err(err); } - *self.store.core_capabilities.lock().unwrap() = - session.capabilities[JMAP_CORE_CAPABILITY].clone(); if !session.capabilities.contains_key(JMAP_MAIL_CAPABILITY) { let err = Error::new(format!( "Server {} does not support JMAP Mail capability ({mail_capability}). Returned \ @@ -202,6 +200,7 @@ impl JmapConnection { *self.store.online_status.lock().await = (Instant::now(), Err(err.clone())); return Err(err); } + *self.store.core_capabilities.lock().unwrap() = session.capabilities.clone(); *self.store.online_status.lock().await = (Instant::now(), Ok(())); *self.session.lock().unwrap() = session; diff --git a/melib/src/jmap/mod.rs b/melib/src/jmap/mod.rs index 9fac1407..8e477ae6 100644 --- a/melib/src/jmap/mod.rs +++ b/melib/src/jmap/mod.rs @@ -68,6 +68,7 @@ macro_rules! _impl { pub const JMAP_CORE_CAPABILITY: &str = "urn:ietf:params:jmap:core"; pub const JMAP_MAIL_CAPABILITY: &str = "urn:ietf:params:jmap:mail"; +pub const JMAP_SUBMISSION_CAPABILITY: &str = "urn:ietf:params:jmap:submission"; pub mod operations; use operations::*; @@ -196,7 +197,7 @@ pub struct Store { pub mailbox_state: Arc>>, pub online_status: Arc)>>, pub is_subscribed: Arc, - pub core_capabilities: Arc>, + pub core_capabilities: Arc>>, pub event_consumer: BackendEventConsumer, } @@ -292,9 +293,18 @@ impl MailBackend for JmapType { supports_search: true, extensions: None, supports_tags: true, - supports_submission: false, + supports_submission: true, }; - CAPABILITIES + let supports_submission: bool = self + .store + .core_capabilities + .lock() + .map(|c| c.contains_key(JMAP_SUBMISSION_CAPABILITY)) + .unwrap_or(false); + MailBackendCapabilities { + supports_submission: CAPABILITIES.supports_submission || supports_submission, + ..CAPABILITIES + } } fn is_online(&self) -> ResultFuture<()> { @@ -322,7 +332,7 @@ impl MailBackend for JmapType { Ok(Box::pin(async_stream::try_stream! { let mut conn = connection.lock().await; conn.connect().await?; - let batch_size: u64 = conn.store.core_capabilities.lock().unwrap().max_objects_in_get; + let batch_size: u64 = conn.store.core_capabilities.lock().unwrap()[JMAP_CORE_CAPABILITY].max_objects_in_get; let mut fetch_state = protocol::EmailFetchState::Start { batch_size }; loop { let res = fetch_state.fetch( @@ -384,7 +394,7 @@ impl MailBackend for JmapType { let mut conn = connection.lock().await; conn.connect().await?; if store.mailboxes.read().unwrap().is_empty() { - let new_mailboxes = debug!(protocol::get_mailboxes(&mut conn).await)?; + let new_mailboxes = debug!(protocol::get_mailboxes(&mut conn, None).await)?; *store.mailboxes.write().unwrap() = new_mailboxes; } @@ -488,7 +498,7 @@ impl MailBackend for JmapType { } })?; - if let Some(err) = m.not_created.get(&creation_id) { + if let Some(err) = m.not_created.and_then(|m| m.get(&creation_id).cloned()) { return Err(Error::new(format!("Could not save message: {:?}", err))); } Ok(()) @@ -894,7 +904,7 @@ impl JmapType { event_consumer, is_subscribed: Arc::new(IsSubscribedFn(is_subscribed)), collection: Collection::default(), - core_capabilities: Arc::new(Mutex::new(rfc8620::CapabilitiesObject::default())), + core_capabilities: Arc::new(Mutex::new(IndexMap::default())), byte_cache: Default::default(), id_store: Default::default(), reverse_id_store: Default::default(), diff --git a/melib/src/jmap/protocol.rs b/melib/src/jmap/protocol.rs index 841d6559..2df3e755 100644 --- a/melib/src/jmap/protocol.rs +++ b/melib/src/jmap/protocol.rs @@ -22,7 +22,7 @@ use std::convert::{TryFrom, TryInto}; use serde::Serialize; -use serde_json::{json, Value}; +use serde_json::Value; use super::{mailbox::JmapMailbox, *}; @@ -78,17 +78,15 @@ impl Request { } } -pub async fn get_mailboxes(conn: &mut JmapConnection) -> Result> { - let seq = get_request_no!(conn.request_no); - let res_text = conn - .send_request(serde_json::to_string(&json!({ - "using": [JMAP_CORE_CAPABILITY, JMAP_MAIL_CAPABILITY], - "methodCalls": [["Mailbox/get", { - "accountId": conn.mail_account_id() - }, - format!("#m{}",seq).as_str()]], - }))?) - .await?; +pub async fn get_mailboxes( + conn: &mut JmapConnection, + request: Option, +) -> Result> { + let mut req = request.unwrap_or_else(|| Request::new(conn.request_no.clone())); + let mailbox_get: MailboxGet = + MailboxGet::new(Get::::new().account_id(conn.mail_account_id())); + req.add_call(&mailbox_get); + let res_text = conn.send_request(serde_json::to_string(&req)?).await?; let mut v: MethodResponse = deserialize_from_str(&res_text)?; *conn.store.online_status.lock().await = (std::time::Instant::now(), Ok(()));