mirror of
https://github.com/chatmail/core.git
synced 2026-09-22 13:01:21 +03:00
api!: remove is_chatmail and the XCHATMAIL capability
This removes the last usages of the deprecated `is_chatmail` and no `XCHATMAIL` IMAP capability is read anymore. UIs are not using it for a longer time anymore. The self-reporting statistics now set `is_chatmail` field to `true`: all transports have relay-typical metadata `false`: at least one doesn't `null`: we don't know BREAKING CHANGE: `is_chatmail` is no longer a known config key.
This commit is contained in:
@@ -461,10 +461,6 @@ char* dc_get_blobdir (const dc_context_t* context);
|
|||||||
* - `gossip_period` = How often to gossip Autocrypt keys in chats with multiple recipients, in
|
* - `gossip_period` = How often to gossip Autocrypt keys in chats with multiple recipients, in
|
||||||
* seconds. 2 days by default.
|
* seconds. 2 days by default.
|
||||||
* This is not supposed to be changed by UIs and only used for testing.
|
* This is not supposed to be changed by UIs and only used for testing.
|
||||||
* - `is_chatmail` = (deprecated) 1 if the the server is a chatmail server, 0 otherwise.
|
|
||||||
* This is deprecated, UIs should not behave differently
|
|
||||||
* for chatmail relays and classical email servers.
|
|
||||||
* Most usages in UIs can be replaced by `force_encryption`.
|
|
||||||
* - `is_muted` = Whether a context is muted by the user.
|
* - `is_muted` = Whether a context is muted by the user.
|
||||||
* Muted contexts should not sound, vibrate or show notifications.
|
* Muted contexts should not sound, vibrate or show notifications.
|
||||||
* In contrast to `dc_set_chat_mute_duration()`,
|
* In contrast to `dc_set_chat_mute_duration()`,
|
||||||
|
|||||||
@@ -421,7 +421,6 @@ def test_dont_move_sync_msgs(acf, direct_imap):
|
|||||||
addr, password = acf.get_credentials()
|
addr, password = acf.get_credentials()
|
||||||
ac1 = acf.get_unconfigured_account()
|
ac1 = acf.get_unconfigured_account()
|
||||||
ac1.set_config("bcc_self", "1")
|
ac1.set_config("bcc_self", "1")
|
||||||
ac1.set_config("fix_is_chatmail", "1")
|
|
||||||
ac1.add_or_update_transport({"addr": addr, "password": password})
|
ac1.add_or_update_transport({"addr": addr, "password": password})
|
||||||
ac1.start_io()
|
ac1.start_io()
|
||||||
ac1_direct_imap = direct_imap(ac1)
|
ac1_direct_imap = direct_imap(ac1)
|
||||||
|
|||||||
@@ -305,18 +305,6 @@ pub enum Config {
|
|||||||
/// True if account is configured.
|
/// True if account is configured.
|
||||||
Configured,
|
Configured,
|
||||||
|
|
||||||
/// Deprecated, we are trying to get rid of this global setting.
|
|
||||||
/// It is possible to configure a profile with both chatmail relays
|
|
||||||
/// and classical email servers.
|
|
||||||
///
|
|
||||||
/// Most usages in UIs can be replaced by `force_encryption`.
|
|
||||||
///
|
|
||||||
/// True if account is a chatmail account.
|
|
||||||
IsChatmail,
|
|
||||||
|
|
||||||
/// True if `IsChatmail` mustn't be autoconfigured. For tests.
|
|
||||||
FixIsChatmail,
|
|
||||||
|
|
||||||
/// True if account is muted.
|
/// True if account is muted.
|
||||||
IsMuted,
|
IsMuted,
|
||||||
|
|
||||||
|
|||||||
@@ -490,17 +490,6 @@ pub(crate) async fn configure(
|
|||||||
|
|
||||||
progress!(ctx, 900);
|
progress!(ctx, 900);
|
||||||
|
|
||||||
let is_configured = ctx.is_configured().await?;
|
|
||||||
if !ctx.get_config_bool(Config::FixIsChatmail).await? {
|
|
||||||
if imap_session.is_chatmail() {
|
|
||||||
ctx.sql.set_raw_config("is_chatmail", Some("1")).await?;
|
|
||||||
} else if !is_configured {
|
|
||||||
// Reset the setting that may have been set
|
|
||||||
// during failed configuration.
|
|
||||||
ctx.sql.set_raw_config("is_chatmail", Some("0")).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drop the imap connection explicitly
|
// Drop the imap connection explicitly
|
||||||
// to make sure that it's not forgotten in a future refactoring
|
// to make sure that it's not forgotten in a future refactoring
|
||||||
drop(imap_session);
|
drop(imap_session);
|
||||||
|
|||||||
@@ -568,15 +568,6 @@ impl Context {
|
|||||||
self.scheduler.maybe_network().await;
|
self.scheduler.maybe_network().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated, we are trying to get rid of this global setting.
|
|
||||||
/// It is possible to configure a profile with both chatmail relays
|
|
||||||
/// and classical email servers.
|
|
||||||
///
|
|
||||||
/// Returns true if an account is on a chatmail server.
|
|
||||||
pub async fn is_chatmail(&self) -> Result<bool> {
|
|
||||||
self.get_config_bool(Config::IsChatmail).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns maximum number of recipients a single email can be sent to.
|
/// Returns maximum number of recipients a single email can be sent to.
|
||||||
pub(crate) async fn get_max_smtp_rcpt_to(&self) -> Result<u32> {
|
pub(crate) async fn get_max_smtp_rcpt_to(&self) -> Result<u32> {
|
||||||
let Some((transport_id, param)) = ConfiguredLoginParam::load(self).await? else {
|
let Some((transport_id, param)) = ConfiguredLoginParam::load(self).await? else {
|
||||||
@@ -885,13 +876,6 @@ impl Context {
|
|||||||
res.insert("imap_server_id", format!("{server_id:?}"));
|
res.insert("imap_server_id", format!("{server_id:?}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.insert("is_chatmail", self.is_chatmail().await?.to_string());
|
|
||||||
res.insert(
|
|
||||||
"fix_is_chatmail",
|
|
||||||
self.get_config_bool(Config::FixIsChatmail)
|
|
||||||
.await?
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
res.insert(
|
res.insert(
|
||||||
"is_muted",
|
"is_muted",
|
||||||
self.get_config_bool(Config::IsMuted).await?.to_string(),
|
self.get_config_bool(Config::IsMuted).await?.to_string(),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ mod tests {
|
|||||||
|
|
||||||
use crate::chat;
|
use crate::chat;
|
||||||
use crate::chat::send_text_msg;
|
use crate::chat::send_text_msg;
|
||||||
use crate::config::Config;
|
|
||||||
use crate::message::Message;
|
use crate::message::Message;
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
use crate::receive_imf::receive_imf;
|
use crate::receive_imf::receive_imf;
|
||||||
@@ -61,7 +60,6 @@ Sent with my Delta Chat Messenger: https://delta.chat";
|
|||||||
async fn test_chatmail_can_send_unencrypted() -> Result<()> {
|
async fn test_chatmail_can_send_unencrypted() -> Result<()> {
|
||||||
let mut tcm = TestContextManager::new();
|
let mut tcm = TestContextManager::new();
|
||||||
let bob = &tcm.bob().await;
|
let bob = &tcm.bob().await;
|
||||||
bob.set_config_bool(Config::IsChatmail, true).await?;
|
|
||||||
bob.allow_unencrypted().await?;
|
bob.allow_unencrypted().await?;
|
||||||
let bob_chat_id = receive_imf(
|
let bob_chat_id = receive_imf(
|
||||||
bob,
|
bob,
|
||||||
|
|||||||
@@ -25,14 +25,6 @@ pub(crate) struct Capabilities {
|
|||||||
/// <https://tools.ietf.org/html/rfc4978>
|
/// <https://tools.ietf.org/html/rfc4978>
|
||||||
pub can_compress: bool,
|
pub can_compress: bool,
|
||||||
|
|
||||||
/// True if the server has an XCHATMAIL capability
|
|
||||||
/// indicating that it is a <https://github.com/deltachat/chatmail> 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.
|
/// Server ID if the server supports ID capability.
|
||||||
pub server_id: Option<HashMap<String, String>>,
|
pub server_id: Option<HashMap<String, String>>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ pub(crate) async fn identify_server(
|
|||||||
can_check_quota: caps.has_str("QUOTA"),
|
can_check_quota: caps.has_str("QUOTA"),
|
||||||
can_metadata: caps.has_str("METADATA"),
|
can_metadata: caps.has_str("METADATA"),
|
||||||
can_compress: caps.has_str("COMPRESS=DEFLATE"),
|
can_compress: caps.has_str("COMPRESS=DEFLATE"),
|
||||||
is_chatmail: caps.has_str("XCHATMAIL"),
|
|
||||||
server_id,
|
server_id,
|
||||||
};
|
};
|
||||||
Ok(capabilities)
|
Ok(capabilities)
|
||||||
|
|||||||
@@ -111,11 +111,6 @@ impl Session {
|
|||||||
self.capabilities.can_metadata
|
self.capabilities.can_metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if IMAP server has `XCHATMAIL` capability.
|
|
||||||
pub(crate) fn is_chatmail(&self) -> bool {
|
|
||||||
self.capabilities.is_chatmail
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prefetch `n_uids` messages starting from `uid_next`. Returns a list of fetch results in the
|
/// Prefetch `n_uids` messages starting from `uid_next`. Returns a list of fetch results in the
|
||||||
/// order of ascending UIDs.
|
/// order of ascending UIDs.
|
||||||
#[expect(clippy::arithmetic_side_effects)]
|
#[expect(clippy::arithmetic_side_effects)]
|
||||||
|
|||||||
@@ -981,7 +981,6 @@ mod tests {
|
|||||||
context1.get_config(Config::BccSelf).await?,
|
context1.get_config(Config::BccSelf).await?,
|
||||||
Some("0".to_string())
|
Some("0".to_string())
|
||||||
);
|
);
|
||||||
context1.set_config_bool(Config::IsChatmail, true).await?;
|
|
||||||
|
|
||||||
assert_eq!(context1.get_config_bool(Config::IsMuted).await?, false);
|
assert_eq!(context1.get_config_bool(Config::IsMuted).await?, false);
|
||||||
context1.set_config_bool(Config::IsMuted, true).await?;
|
context1.set_config_bool(Config::IsMuted, true).await?;
|
||||||
@@ -1001,7 +1000,6 @@ mod tests {
|
|||||||
.get_matching(|evt| matches!(evt, EventType::ImexProgress(1000)))
|
.get_matching(|evt| matches!(evt, EventType::ImexProgress(1000)))
|
||||||
.await;
|
.await;
|
||||||
assert!(context2.is_configured().await?);
|
assert!(context2.is_configured().await?);
|
||||||
assert!(context2.is_chatmail().await?);
|
|
||||||
for ctx in [context1, context2] {
|
for ctx in [context1, context2] {
|
||||||
// BccSelf should be enabled automatically when exporting a backup
|
// BccSelf should be enabled automatically when exporting a backup
|
||||||
assert_eq!(ctx.get_config_bool(Config::BccSelf).await?, true);
|
assert_eq!(ctx.get_config_bool(Config::BccSelf).await?, true);
|
||||||
|
|||||||
@@ -521,7 +521,6 @@ async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session)
|
|||||||
};
|
};
|
||||||
|
|
||||||
maybe_broadcast_reactions(ctx).await.log_err(ctx).ok();
|
maybe_broadcast_reactions(ctx).await.log_err(ctx).ok();
|
||||||
maybe_send_stats(ctx).await.log_err(ctx).ok();
|
|
||||||
|
|
||||||
session
|
session
|
||||||
.update_metadata(ctx)
|
.update_metadata(ctx)
|
||||||
@@ -534,6 +533,8 @@ async fn inbox_fetch_idle(ctx: &Context, imap: &mut Imap, mut session: Session)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_send_stats(ctx).await.log_err(ctx).ok();
|
||||||
|
|
||||||
let session = fetch_idle(ctx, imap, session).await?;
|
let session = fetch_idle(ctx, imap, session).await?;
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,15 +16,15 @@ async fn test_clear_config_cache() -> anyhow::Result<()> {
|
|||||||
// This test checks that the config cache is invalidated in `execute_migration()`.
|
// This test checks that the config cache is invalidated in `execute_migration()`.
|
||||||
|
|
||||||
let t = TestContext::new().await;
|
let t = TestContext::new().await;
|
||||||
assert_eq!(t.get_config_bool(Config::IsChatmail).await?, false);
|
assert_eq!(t.sql.get_raw_config_bool("cached_key").await?, false);
|
||||||
|
|
||||||
t.sql
|
t.sql
|
||||||
.execute_migration(
|
.execute_migration(
|
||||||
"INSERT INTO config (keyname, value) VALUES ('is_chatmail', '1')",
|
"INSERT INTO config (keyname, value) VALUES ('cached_key', '1')",
|
||||||
1000,
|
1000,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(t.get_config_bool(Config::IsChatmail).await?, true);
|
assert_eq!(t.sql.get_raw_config_bool("cached_key").await?, true);
|
||||||
assert_eq!(t.sql.get_raw_config_int(VERSION_CFG).await?.unwrap(), 1000);
|
assert_eq!(t.sql.get_raw_config_int(VERSION_CFG).await?.unwrap(), 1000);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
13
src/stats.rs
13
src/stats.rs
@@ -42,7 +42,8 @@ struct Statistics {
|
|||||||
/// Size of the public key in bytes (encoded in binary, not base64).
|
/// Size of the public key in bytes (encoded in binary, not base64).
|
||||||
pubkey_size: usize,
|
pubkey_size: usize,
|
||||||
stats_id: String,
|
stats_id: String,
|
||||||
is_chatmail: bool,
|
/// Whether all transports are chatmail relays, `None` if not known for all of them.
|
||||||
|
is_chatmail: Option<bool>,
|
||||||
contact_stats: Vec<ContactStat>,
|
contact_stats: Vec<ContactStat>,
|
||||||
message_stats: BTreeMap<Chattype, MessageStats>,
|
message_stats: BTreeMap<Chattype, MessageStats>,
|
||||||
securejoin_sources: SecurejoinSources,
|
securejoin_sources: SecurejoinSources,
|
||||||
@@ -350,16 +351,22 @@ async fn get_stats(context: &Context) -> Result<String> {
|
|||||||
let sending_disabled_timestamps =
|
let sending_disabled_timestamps =
|
||||||
get_timestamps(context, "stats_sending_disabled_events").await?;
|
get_timestamps(context, "stats_sending_disabled_events").await?;
|
||||||
|
|
||||||
|
let number_of_transports = context.count_transports().await?;
|
||||||
|
let metadata = context.metadata.read().await;
|
||||||
|
let is_chatmail = (!metadata.is_empty() && metadata.len() == number_of_transports)
|
||||||
|
.then(|| metadata.values().all(|m| m.supports_push));
|
||||||
|
drop(metadata);
|
||||||
|
|
||||||
let stats = Statistics {
|
let stats = Statistics {
|
||||||
core_version: DC_VERSION_STR.to_string(),
|
core_version: DC_VERSION_STR.to_string(),
|
||||||
number_of_transports: context.count_transports().await?,
|
number_of_transports,
|
||||||
key_create_timestamps,
|
key_create_timestamps,
|
||||||
number_of_keys,
|
number_of_keys,
|
||||||
key_version: self_public_key.primary_key.version().into(),
|
key_version: self_public_key.primary_key.version().into(),
|
||||||
key_algorithm: format!("{:?}", self_public_key.algorithm()),
|
key_algorithm: format!("{:?}", self_public_key.algorithm()),
|
||||||
pubkey_size: DcKey::to_bytes(&self_public_key).len(),
|
pubkey_size: DcKey::to_bytes(&self_public_key).len(),
|
||||||
stats_id: stats_id(context).await?,
|
stats_id: stats_id(context).await?,
|
||||||
is_chatmail: context.is_chatmail().await?,
|
is_chatmail,
|
||||||
contact_stats: get_contact_stats(context, last_old_contact).await?,
|
contact_stats: get_contact_stats(context, last_old_contact).await?,
|
||||||
message_stats: get_message_stats(context).await?,
|
message_stats: get_message_stats(context).await?,
|
||||||
securejoin_sources: get_securejoin_source_stats(context).await?,
|
securejoin_sources: get_securejoin_source_stats(context).await?,
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ use super::*;
|
|||||||
use crate::chat::{
|
use crate::chat::{
|
||||||
Chat, create_broadcast, create_group, create_group_unencrypted, get_chat_contacts,
|
Chat, create_broadcast, create_group, create_group_unencrypted, get_chat_contacts,
|
||||||
};
|
};
|
||||||
|
use crate::imap::ServerMetadata;
|
||||||
use crate::mimeparser::SystemMessage;
|
use crate::mimeparser::SystemMessage;
|
||||||
use crate::qr::check_qr;
|
use crate::qr::check_qr;
|
||||||
use crate::securejoin::{get_securejoin_qr, join_securejoin, join_securejoin_with_ux_info};
|
use crate::securejoin::{get_securejoin_qr, join_securejoin, join_securejoin_with_ux_info};
|
||||||
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg};
|
use crate::test_utils::{TestContext, TestContextManager, get_chat_msg};
|
||||||
use crate::tools::SystemTime;
|
use crate::tools::SystemTime;
|
||||||
|
use crate::transport::add_pseudo_transport;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use serde_json::{Number, Value};
|
use serde_json::{Number, Value};
|
||||||
|
|
||||||
@@ -463,18 +465,33 @@ async fn test_stats_securejoin_invites() -> Result<()> {
|
|||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_stats_is_chatmail() -> Result<()> {
|
async fn test_stats_is_chatmail() -> Result<()> {
|
||||||
|
async fn is_chatmail(context: &TestContext) -> Result<Value> {
|
||||||
|
let stats: Value = serde_json::from_str(&get_stats(context).await?)?;
|
||||||
|
Ok(stats.get("is_chatmail").unwrap().clone())
|
||||||
|
}
|
||||||
|
|
||||||
let alice = &TestContext::new_alice().await;
|
let alice = &TestContext::new_alice().await;
|
||||||
alice.set_config_bool(Config::StatsSending, true).await?;
|
alice.set_config_bool(Config::StatsSending, true).await?;
|
||||||
|
assert!(is_chatmail(alice).await?.is_null());
|
||||||
|
|
||||||
let r = get_stats(alice).await?;
|
alice.metadata.write().await.insert(
|
||||||
let r: serde_json::Value = serde_json::from_str(&r)?;
|
0,
|
||||||
assert_eq!(r.get("is_chatmail").unwrap().as_bool().unwrap(), false);
|
ServerMetadata {
|
||||||
|
supports_push: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(is_chatmail(alice).await?, Value::Bool(true));
|
||||||
|
|
||||||
alice.set_config_bool(Config::IsChatmail, true).await?;
|
add_pseudo_transport(alice, "alice@example.net").await?;
|
||||||
|
assert!(is_chatmail(alice).await?.is_null());
|
||||||
|
|
||||||
let r = get_stats(alice).await?;
|
alice
|
||||||
let r: serde_json::Value = serde_json::from_str(&r)?;
|
.metadata
|
||||||
assert_eq!(r.get("is_chatmail").unwrap().as_bool().unwrap(), true);
|
.write()
|
||||||
|
.await
|
||||||
|
.insert(1, ServerMetadata::default());
|
||||||
|
assert_eq!(is_chatmail(alice).await?, Value::Bool(false));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -703,9 +703,7 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_send_sync_msg_enables_bccself() -> Result<()> {
|
async fn test_send_sync_msg_enables_bccself() -> Result<()> {
|
||||||
for (chatmail, sync_message_sent) in
|
for sync_message_sent in [false, true] {
|
||||||
[(false, false), (false, true), (true, false), (true, true)]
|
|
||||||
{
|
|
||||||
let alice1 = TestContext::new_alice().await;
|
let alice1 = TestContext::new_alice().await;
|
||||||
let alice2 = TestContext::new_alice().await;
|
let alice2 = TestContext::new_alice().await;
|
||||||
|
|
||||||
@@ -714,9 +712,6 @@ mod tests {
|
|||||||
alice1.set_config_bool(Config::SyncMsgs, true).await?;
|
alice1.set_config_bool(Config::SyncMsgs, true).await?;
|
||||||
alice2.set_config_bool(Config::SyncMsgs, true).await?;
|
alice2.set_config_bool(Config::SyncMsgs, true).await?;
|
||||||
|
|
||||||
alice1.set_config_bool(Config::IsChatmail, chatmail).await?;
|
|
||||||
alice2.set_config_bool(Config::IsChatmail, chatmail).await?;
|
|
||||||
|
|
||||||
alice1.set_config_bool(Config::BccSelf, true).await?;
|
alice1.set_config_bool(Config::BccSelf, true).await?;
|
||||||
alice2.set_config_bool(Config::BccSelf, false).await?;
|
alice2.set_config_bool(Config::BccSelf, false).await?;
|
||||||
|
|
||||||
@@ -735,7 +730,7 @@ mod tests {
|
|||||||
alice1.send_text(chat.id, "Hi").await
|
alice1.send_text(chat.id, "Hi").await
|
||||||
};
|
};
|
||||||
|
|
||||||
// On chatmail accounts, BccSelf defaults to false.
|
// BccSelf defaults to false.
|
||||||
// When receiving a sync message from another device,
|
// When receiving a sync message from another device,
|
||||||
// there obviously is a multi-device-setup, and BccSelf
|
// there obviously is a multi-device-setup, and BccSelf
|
||||||
// should be enabled.
|
// should be enabled.
|
||||||
|
|||||||
Reference in New Issue
Block a user