melib/jmap: add some connection status messages and errors

jmap-status-and-connect-retry-wip
Manos Pitsidianakis 2022-10-06 16:44:40 +03:00
parent 659a34bf21
commit a05f36341b
3 changed files with 41 additions and 6 deletions

View File

@ -105,6 +105,12 @@ impl Default for Backends {
}
}
#[cfg(feature = "jmap_backend")]
pub const JMAP_ERROR_MSG: &str = "";
#[cfg(not(feature = "jmap_backend"))]
pub const JMAP_ERROR_MSG: &str = "This library build lacks JMAP support. JMAP requires an HTTP client dependency and thus is turned off by default when compiling.";
#[cfg(feature = "notmuch_backend")]
pub const NOTMUCH_ERROR_MSG: &str =
"libnotmuch5 was not found in your system. Make sure it is installed and in the library paths. For a custom file path, use `library_file_path` setting in your notmuch account.\n";
@ -219,6 +225,11 @@ impl Backends {
{
eprint!("{}", NOTMUCH_ERROR_DETAILS);
}
} else if key == "jmap" {
#[cfg(not(feature = "jmap_backend"))]
{
eprintln!("{}", JMAP_ERROR_MSG);
}
}
panic!("{} is not a valid mail backend", key);
}
@ -247,6 +258,8 @@ impl Backends {
key,
if cfg!(feature = "notmuch_backend") && key == "notmuch" {
NOTMUCH_ERROR_DETAILS
} else if !cfg!(feature = "jmap_backend") && key == "jmap" {
JMAP_ERROR_MSG
} else {
""
},

View File

@ -20,6 +20,7 @@
*/
use super::*;
use crate::error::IntoMeliError;
use isahc::config::Configurable;
use std::sync::MutexGuard;
@ -34,6 +35,12 @@ pub struct JmapConnection {
impl JmapConnection {
pub fn new(server_conf: &JmapServerConf, store: Arc<Store>) -> Result<Self> {
(store.event_consumer)(
store.account_hash,
crate::backends::BackendEvent::AccountStateChange {
message: "Creating connection.".into(),
},
);
let client = HttpClient::builder()
.timeout(std::time::Duration::from_secs(10))
.redirect_policy(RedirectPolicy::Limit(10))
@ -53,6 +60,15 @@ impl JmapConnection {
})
}
#[inline(always)]
pub(crate) fn account_state_change(&self, message: impl Into<std::borrow::Cow<'static, str>>) {
let message = message.into();
(self.store.event_consumer)(
self.store.account_hash,
crate::backends::BackendEvent::AccountStateChange { message },
);
}
pub async fn connect(&mut self) -> Result<()> {
if self.store.online_status.lock().await.1.is_ok() {
return Ok(());
@ -63,12 +79,16 @@ impl JmapConnection {
jmap_session_resource_url.push_str(&self.server_conf.server_port.to_string());
}
jmap_session_resource_url.push_str("/.well-known/jmap");
self.account_state_change(format!("Requesting {}", &jmap_session_resource_url));
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
})?;
let mut req = match self.client.get_async(&jmap_session_resource_url).await {
Err(err) => {
let err = err.set_err_summary(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));
*self.store.online_status.lock().await = (Instant::now(), Err(err.clone()));
return Err(err);
}
Ok(r) => r,
};
if !req.status().is_success() {
let kind: crate::error::NetworkErrorKind = req.status().into();
@ -86,7 +106,7 @@ impl JmapConnection {
let session: JmapSession = match serde_json::from_str(&res_text) {
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.)\nReply from server: {}", &self.server_conf.server_hostname, &res_text)).set_source(Some(Arc::new(err)));
let err = err.set_err_summary(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.)\nReply from server: {}", &self.server_conf.server_hostname, &res_text));
*self.store.online_status.lock().await = (Instant::now(), Err(err.clone()));
return Err(err);
}

View File

@ -85,6 +85,7 @@ pub struct JsonResponse<'a> {
}
pub async fn get_mailboxes(conn: &JmapConnection) -> Result<HashMap<MailboxHash, JmapMailbox>> {
conn.account_state_change("Fetching mailbox list…");
let seq = get_request_no!(conn.request_no);
let api_url = conn.session.lock().unwrap().api_url.clone();
let mut res = conn
@ -180,6 +181,7 @@ pub async fn get_message_list(
conn: &JmapConnection,
mailbox: &JmapMailbox,
) -> Result<Vec<Id<EmailObject>>> {
conn.account_state_change(format!("Fetching email list for {}", mailbox.name()));
let email_call: EmailQuery = EmailQuery::new(
Query::new()
.account_id(conn.mail_account_id().clone())