diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 64b5964d8..59732c18c 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -517,6 +517,7 @@ char* dc_get_blobdir (const dc_context_t* context); * 0=Nothing else happens when the key changes. * 1=After the key changed, `dc_chat_can_send()` returns false and `dc_chat_is_protection_broken()` returns true * until `dc_accept_chat()` is called. + * - `is_chatmail` = 1 if the the server is a chatmail server, 0 otherwise. * - `ui.*` = All keys prefixed by `ui.` can be used by the user-interfaces for system-specific purposes. * The prefix should be followed by the system and maybe subsystem, * e.g. `ui.desktop.foo`, `ui.desktop.linux.bar`, `ui.android.foo`, `ui.dc40.bar`, `ui.bot.simplebot.baz`. diff --git a/src/config.rs b/src/config.rs index a367494aa..1c516e825 100644 --- a/src/config.rs +++ b/src/config.rs @@ -254,6 +254,9 @@ pub enum Config { /// True if account is configured. Configured, + /// True if account is a chatmail account. + IsChatmail, + /// All secondary self addresses separated by spaces /// (`addr1@example.org addr2@example.org addr3@example.org`) SecondaryAddrs, diff --git a/src/configure.rs b/src/configure.rs index baf6bd7f6..f1ce89060 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -112,6 +112,11 @@ impl Context { let mut param = LoginParam::load_candidate_params(self).await?; let old_addr = self.get_config(Config::ConfiguredAddr).await?; + + // Reset our knowledge about whether the server is a chatmail server. + // We will update it when we connect to IMAP. + self.set_config_internal(Config::IsChatmail, None).await?; + let success = configure(self, &mut param).await; self.set_config_internal(Config::NotifyAboutWrongPw, None) .await?; @@ -453,6 +458,10 @@ async fn configure(ctx: &Context, param: &mut LoginParam) -> Result<()> { progress!(ctx, 900); + if imap_session.is_chatmail() { + ctx.set_config(Config::MvboxMove, Some("0")).await?; + } + let create_mvbox = ctx.should_watch_mvbox().await?; imap.configure_folders(ctx, &mut imap_session, create_mvbox) diff --git a/src/context.rs b/src/context.rs index 5586c4c7f..98f232249 100644 --- a/src/context.rs +++ b/src/context.rs @@ -461,18 +461,10 @@ impl Context { return; } - { - if self - .get_config(Config::ConfiguredAddr) - .await - .unwrap_or_default() - .filter(|s| s.ends_with(".testrun.org")) - .is_some() - { - let mut lock = self.ratelimit.write().await; - // Allow at least 1 message every second + a burst of 3. - *lock = Ratelimit::new(Duration::new(3, 0), 3.0); - } + if self.is_chatmail().await.unwrap_or_default() { + let mut lock = self.ratelimit.write().await; + // Allow at least 1 message every second + a burst of 3. + *lock = Ratelimit::new(Duration::new(3, 0), 3.0); } self.scheduler.start(self.clone()).await; } @@ -493,6 +485,11 @@ impl Context { self.scheduler.maybe_network().await; } + /// Returns true if an account is on a chatmail server. + pub async fn is_chatmail(&self) -> Result { + self.get_config_bool(Config::IsChatmail).await + } + /// Does a background fetch /// pauses the scheduler and does one imap fetch, then unpauses and returns pub async fn background_fetch(&self) -> Result<()> { @@ -799,6 +796,8 @@ impl Context { res.insert("imap_server_id", format!("{server_id:?}")); } + res.insert("is_chatmail", self.is_chatmail().await?.to_string()); + if let Some(metadata) = &*self.metadata.read().await { if let Some(comment) = &metadata.comment { res.insert("imap_server_comment", format!("{comment:?}")); diff --git a/src/imap/capabilities.rs b/src/imap/capabilities.rs index af1996baa..160b1e138 100644 --- a/src/imap/capabilities.rs +++ b/src/imap/capabilities.rs @@ -32,6 +32,14 @@ pub(crate) struct Capabilities { /// This is supported by pub can_push: bool, + /// True if the server has an XCHATMAIL capability + /// indicating that it is a server. + /// + /// This can be used to hide some advanced settings in the UI + /// that are only interesting for normal email accounts, + /// e.g. the ability to move messages to Delta Chat folder. + pub is_chatmail: bool, + /// Server ID if the server supports ID capability. pub server_id: Option>, } diff --git a/src/imap/client.rs b/src/imap/client.rs index aff54f5e5..1bd546e74 100644 --- a/src/imap/client.rs +++ b/src/imap/client.rs @@ -61,6 +61,7 @@ async fn determine_capabilities( can_condstore: caps.has_str("CONDSTORE"), can_metadata: caps.has_str("METADATA"), can_push: caps.has_str("XDELTAPUSH"), + is_chatmail: caps.has_str("XCHATMAIL"), server_id, }; Ok(capabilities) diff --git a/src/imap/session.rs b/src/imap/session.rs index 1c541aaf0..b3f09af27 100644 --- a/src/imap/session.rs +++ b/src/imap/session.rs @@ -94,6 +94,11 @@ impl Session { self.capabilities.can_push } + // Returns true if IMAP server has `XCHATMAIL` capability. + pub fn is_chatmail(&self) -> bool { + self.capabilities.is_chatmail + } + /// Returns the names of all folders on the IMAP server. pub async fn list_folders(&mut self) -> Result> { let list = self.list(Some(""), Some("*")).await?.try_collect().await?; diff --git a/src/scheduler.rs b/src/scheduler.rs index a621f960c..5df9a53a1 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -466,6 +466,12 @@ pub async fn convert_folder_meaning( } async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session) -> Result { + ctx.set_config_internal( + Config::IsChatmail, + crate::config::from_bool(session.is_chatmail()), + ) + .await?; + // Update quota no more than once a minute. let quota_needs_update = { let quota = ctx.quota.read().await;