Skip to content
Draft
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,6 @@ char* dc_get_blobdir (const dc_context_t* context);
* Messages in the "saved messages" chat (see dc_chat_is_self_talk()) are skipped.
* Messages are deleted whether they were seen or not, the UI should clearly point that out.
* See also dc_estimate_deletion_cnt().
* - `delete_server_after` = 0=do not delete messages from server automatically (default),
* 1=delete messages directly after receiving from server, mvbox is skipped.
* >1=seconds, after which messages are deleted automatically from the server, mvbox is used as defined.
* "Saved messages" are deleted from the server as well as emails, the UI should clearly point that out.
* See also dc_estimate_deletion_cnt().
* - `media_quality` = DC_MEDIA_QUALITY_BALANCED (0) =
* good outgoing images/videos/voice quality at reasonable sizes (default)
* DC_MEDIA_QUALITY_WORSE (1)
Expand Down Expand Up @@ -1461,13 +1456,13 @@ dc_chatlist_t* dc_get_similar_chatlist (dc_context_t* context, uint32_t ch

/**
* Estimate the number of messages that will be deleted
* by the dc_set_config()-options `delete_device_after` or `delete_server_after`.
* by the dc_set_config()-option `delete_device_after`.
* This is typically used to show the estimated impact to the user
* before actually enabling deletion of old messages.
*
* @memberof dc_context_t
* @param context The context object as returned from dc_context_new().
* @param from_server 1=Estimate deletion count for server, 0=Estimate deletion count for device
* @param from_server Deprecated, pass 0 here
* @param seconds Count messages older than the given number of seconds.
* @return Number of messages that are older than the given number of seconds.
* Messages in the "saved messages" folder are not counted as they will not be deleted automatically.
Expand Down
13 changes: 11 additions & 2 deletions deltachat-jsonrpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,10 +735,19 @@ impl CommandApi {
Ok(msg_ids)
}

/// Estimate the number of messages that will be deleted
/// by the set_config()-options `delete_device_after` or `delete_server_after`.
/// Estimates the number of messages that will be deleted
/// by the `set_config()`-option `delete_device_after`.
///
/// This is typically used to show the estimated impact to the user
/// before actually enabling deletion of old messages.
///
/// Messages in the "saved messages" folder are not counted as they will not be deleted automatically.
Comment thread
Hocuri marked this conversation as resolved.
Outdated
///
/// Parameters:
/// - `from_server`: Deprecated, pass `false` here
/// - `seconds`: Count messages older than the given number of seconds.
///
/// Returns the number of messages that are older than the given number of seconds.
async fn estimate_auto_deletion_count(
&self,
account_id: u32,
Expand Down
22 changes: 11 additions & 11 deletions deltachat-rpc-client/tests/test_folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ def test_moved_markseen(acfactory, direct_imap, log):
ac2.add_or_update_transport({"addr": addr, "password": password})
ac2.bring_online()

# Make sure that messages are not immediately auto-deleted on the server:
ac1.set_config("bcc_self", "1")
ac2.set_config("bcc_self", "1")

log.section("ac2: creating DeltaChat folder")
ac2_direct_imap = direct_imap(ac2)
ac2_direct_imap.create_folder("DeltaChat")
ac2.set_config("delete_server_after", "0")
ac2.set_config("sync_msgs", "0") # Do not send a sync message when accepting a contact request.

ac2.add_or_update_transport({"addr": addr, "password": password, "imapFolder": "DeltaChat"})
Expand Down Expand Up @@ -57,11 +60,9 @@ def test_moved_markseen(acfactory, direct_imap, log):
def test_markseen_message_and_mdn(acfactory, direct_imap):
ac1, ac2 = acfactory.get_online_accounts(2)

for ac in ac1, ac2:
ac.set_config("delete_server_after", "0")

# Do not send BCC to self, we only want to test MDN on ac1.
ac1.set_config("bcc_self", "0")
# Make sure that messages are not immediately auto-deleted on the server:
ac1.set_config("bcc_self", "1")
ac2.set_config("bcc_self", "1")

acfactory.get_accepted_chat(ac1, ac2).send_text("hi")
msg = ac2.wait_for_incoming_msg()
Expand All @@ -81,17 +82,16 @@ def test_markseen_message_and_mdn(acfactory, direct_imap):
ac1_direct_imap.select_folder("INBOX")
ac2_direct_imap.select_folder("INBOX")

# Check that the mdn is marked as seen
assert len(list(ac1_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 1
# Check original message is marked as seen
assert len(list(ac2_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 1
# Check that the mdn and original message is marked as seen
assert len(list(ac1_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 2
assert len(list(ac2_direct_imap.conn.fetch(AND(seen=True), mark_seen=False))) == 2


def test_trash_multiple_messages(acfactory, direct_imap, log):
ac1, ac2 = acfactory.get_online_accounts(2)
ac2.stop_io()

ac2.set_config("delete_server_after", "0")
ac2.set_config("bcc_self", "1") # Make sure that messages are not immediately auto-deleted
ac2.set_config("sync_msgs", "0")

ac2.start_io()
Expand Down
35 changes: 0 additions & 35 deletions deltachat-rpc-client/tests/test_multidevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,6 @@
from deltachat_rpc_client.const import MessageState


def test_bcc_self_delete_server_after_defaults(acfactory):
"""Test default values for bcc_self and delete_server_after."""
ac = acfactory.get_online_account()

# Initially after getting online
# the setting bcc_self is set to 0 because there is only one device
# and delete_server_after is "1", meaning immediate deletion.
assert ac.get_config("bcc_self") == "0"
assert ac.get_config("delete_server_after") == "1"

# Setup a second device.
ac_clone = ac.clone()
ac_clone.bring_online()

# Second device setup
# enables bcc_self and changes default delete_server_after.
assert ac.get_config("bcc_self") == "1"
assert ac.get_config("delete_server_after") == "0"

assert ac_clone.get_config("bcc_self") == "1"
assert ac_clone.get_config("delete_server_after") == "0"

# Manually disabling bcc_self
# also restores the default for delete_server_after.
ac.set_config("bcc_self", "0")
assert ac.get_config("bcc_self") == "0"
assert ac.get_config("delete_server_after") == "1"

# Cloning the account again enables bcc_self
# even though it was manually disabled.
ac_clone = ac.clone()
assert ac.get_config("bcc_self") == "1"
assert ac.get_config("delete_server_after") == "0"


def test_one_account_send_bcc_setting(acfactory, log, direct_imap):
ac1, ac2 = acfactory.get_online_accounts(2)
ac1_clone = ac1.clone()
Expand Down
6 changes: 5 additions & 1 deletion deltachat-rpc-client/tests/test_something.py
Original file line number Diff line number Diff line change
Expand Up @@ -1232,10 +1232,14 @@ def test_leave_and_delete_group(acfactory, log):


def test_immediate_autodelete(acfactory, direct_imap, log):
"""
`bcc_self` is off by default,
so that messages are supposed to be immediately autodeleted
"""
ac1, ac2 = acfactory.get_online_accounts(2)

# "1" means delete immediately, while "0" means do not delete
ac2.set_config("delete_server_after", "1")
# TODO check if this causes a test failure: ac2.set_config("delete_server_after", "1")

log.section("ac1: create chat with ac2")
chat1 = ac1.create_chat(ac2)
Expand Down
1 change: 0 additions & 1 deletion python/src/deltachat/testplugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,6 @@ def prepare_account_from_liveconfig(self, configdict) -> Account:
assert "addr" in configdict and "mail_pw" in configdict, configdict
configdict.setdefault("bcc_self", False)
configdict.setdefault("sync_msgs", False)
configdict.setdefault("delete_server_after", 0)
ac.update_config(configdict)
self._acsetup._account2config[ac] = configdict
self._preconfigure_key(ac)
Expand Down
67 changes: 0 additions & 67 deletions python/tests/test_0_complex_or_slow.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,73 +298,6 @@ def test_use_new_verified_group_after_going_online(acfactory, data, tmp_path, lp
assert msg_in.text == msg_out.text


def test_verified_group_vs_delete_server_after(acfactory, tmp_path, lp):
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test tested how delete_server_after interacted with verified groups. We removed both features.

"""Test for the issue #4346:
- User is added to a verified group.
- First device of the user downloads "member added" from the group.
- First device removes "member added" from the server.
- Some new messages are sent to the group.
- Second device comes online, receives these new messages.
The result is an unverified group with unverified members.
- First device re-gossips Autocrypt keys to the group.
- Now the second device has all members and group verified.
"""
ac1, ac2 = acfactory.get_online_accounts(2)
acfactory.remove_preconfigured_keys()
ac2_offl = acfactory.new_online_configuring_account(cloned_from=ac2)
for ac in [ac2, ac2_offl]:
ac.set_config("bcc_self", "1")
ac2.set_config("delete_server_after", "1")
ac2.set_config("gossip_period", "0") # Re-gossip in every message
acfactory.bring_accounts_online()
dir = tmp_path / "exportdir"
dir.mkdir()
ac2.export_self_keys(str(dir))
ac2_offl.import_self_keys(str(dir))
ac2_offl.stop_io()

lp.sec("ac1: create verified-group QR, ac2 scans and joins")
chat1 = ac1.create_group_chat("hello")
qr = chat1.get_join_qr()
lp.sec("ac2: start QR-code based join-group protocol")
chat2 = ac2.qr_join_chat(qr)
ac1._evtracker.wait_securejoin_inviter_progress(1000)
# Wait for "Member Me (<addr>) added by <addr>." message.
msg_in = ac2._evtracker.wait_next_incoming_message()
assert msg_in.is_system_message()

lp.sec("ac2: waiting for 'member added' to be deleted on the server")
ac2._evtracker.get_matching("DC_EVENT_IMAP_MESSAGE_DELETED")

lp.sec("ac1: sending 'hi' to the group")
ac2.set_config("delete_server_after", "0")
chat1.send_text("hi")

lp.sec("ac2_offl: going online, checking the 'hi' message")
ac2_offl.start_io()
msg_in = ac2_offl._evtracker.wait_next_incoming_message()
assert not msg_in.is_system_message()
assert msg_in.text == "hi"
ac2_offl_ac1_contact = msg_in.get_sender_contact()
assert ac2_offl_ac1_contact.addr == ac1.get_config("addr")
assert not ac2_offl_ac1_contact.is_verified()
chat2_offl = msg_in.chat

lp.sec("ac2: sending message re-gossiping Autocrypt keys")
chat2.send_text("hi2")

lp.sec("ac2_offl: receiving message")
ev = ac2_offl._evtracker.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED")
msg_in = ac2_offl.get_message_by_id(ev.data2)
assert not msg_in.is_system_message()
assert msg_in.text == "hi2"
assert msg_in.chat == chat2_offl
assert msg_in.get_sender_contact().addr == ac2.get_config("addr")
# Until we reset verifications and then send the _verified header,
# verification is not gossiped here:
assert not ac2_offl_ac1_contact.is_verified()


def test_deleted_msgs_dont_reappear(acfactory):
ac1 = acfactory.new_online_configuring_account()
acfactory.bring_accounts_online()
Expand Down
20 changes: 19 additions & 1 deletion python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ def test_basic_imap_api(acfactory, tmp_path):
ac1, ac2 = acfactory.get_online_accounts(2)
chat12 = acfactory.get_accepted_chat(ac1, ac2)

# Make sure that messages are not immediately auto-deleted on the server:
ac2.set_config("bcc_self", "1")

Comment thread
iequidoo marked this conversation as resolved.
imap2 = ac2.direct_imap

with imap2.idle() as idle2:
Expand Down Expand Up @@ -162,6 +165,9 @@ def test_webxdc_message(acfactory, data, lp):
ac1, ac2 = acfactory.get_online_accounts(2)
chat = acfactory.get_accepted_chat(ac1, ac2)

# Make sure that messages are not immediately auto-deleted on the server:
ac2.set_config("bcc_self", "1")

lp.sec("ac1: prepare and send text message to ac2")
msg1 = chat.send_text("message0")
assert not msg1.is_webxdc()
Expand Down Expand Up @@ -362,6 +368,10 @@ def test_send_and_receive_message_markseen(acfactory, lp):
# make DC's life harder wrt to encodings
ac1.set_config("displayname", "ä name")

# Make sure that messages are not immediately auto-deleted on the server:
ac1.set_config("bcc_self", "1")
ac2.set_config("bcc_self", "1")

# clear any fresh device messages
ac1.get_device_chat().mark_noticed()
ac2.get_device_chat().mark_noticed()
Expand Down Expand Up @@ -506,9 +516,15 @@ def test_mdn_asymmetric(acfactory, lp):
ac1.set_config("mdns_enabled", "1")
ac2.set_config("mdns_enabled", "1")

# Make sure that the mdn is not immediately auto-deleted on the server:
ac1.set_config("bcc_self", "1")

lp.sec("sending text message from ac1 to ac2")
msg_out = chat.send_text("message1")

# Wait for the message to be marked as seen on IMAP.
ac1._evtracker.get_info_contains("Marked messages [0-9]+ in folder INBOX as seen.")

assert len(chat.get_messages()) == 1 + E2EE_INFO_MSGS

lp.sec("disable ac1 MDNs")
Expand All @@ -525,7 +541,7 @@ def test_mdn_asymmetric(acfactory, lp):
lp.sec("ac1: waiting for incoming activity")
assert len(chat.get_messages()) == 1 + E2EE_INFO_MSGS

# Wait for the message to be marked as seen on IMAP.
# Wait for the mdn to be marked as seen on IMAP.
ac1._evtracker.get_info_contains("Marked messages [0-9]+ in folder INBOX as seen.")

# MDN is received even though MDNs are already disabled
Expand Down Expand Up @@ -1073,6 +1089,8 @@ def test_send_receive_locations(acfactory, lp):

def test_delete_multiple_messages(acfactory, lp):
ac1, ac2 = acfactory.get_online_accounts(2)
# Make sure that messages are not immediately auto-deleted on the server:
ac2.set_config("bcc_self", "1")
chat12 = acfactory.get_accepted_chat(ac1, ac2)

lp.sec("ac1: sending seven messages")
Expand Down
36 changes: 0 additions & 36 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,6 @@ pub enum Config {
#[strum(props(default = "0"))] // also change MediaQuality.default() on changes
MediaQuality,

/// Timer in seconds after which the message is deleted from the
/// server.
///
/// 0 means messages are never deleted by Delta Chat.
///
/// Value 1 is treated as "delete at once": messages are deleted
/// immediately, without moving to DeltaChat folder.
///
/// Default is 1 for chatmail accounts without `BccSelf`, 0 otherwise.
DeleteServerAfter,

/// Timer in seconds after which the message is deleted from the
/// device.
///
Expand Down Expand Up @@ -554,14 +543,6 @@ impl Context {
// Default values
let val = match key {
Config::ConfiguredInboxFolder => Some("INBOX".to_string()),
Config::DeleteServerAfter => {
match !Box::pin(self.get_config_bool(Config::BccSelf)).await?
&& Box::pin(self.is_chatmail()).await?
{
true => Some("1".to_string()),
false => Some("0".to_string()),
}
}
Config::Addr => self.get_config_opt(Config::ConfiguredAddr).await?,
_ => key.get_str("default").map(|s| s.to_string()),
};
Expand Down Expand Up @@ -642,23 +623,6 @@ impl Context {
self.get_config_bool(Config::MdnsEnabled).await
}

/// Gets configured "delete_server_after" value.
///
/// `None` means never delete the message, `Some(0)` means delete
/// at once, `Some(x)` means delete after `x` seconds.
pub async fn get_config_delete_server_after(&self) -> Result<Option<i64>> {
let val = match self
.get_config_parsed::<i64>(Config::DeleteServerAfter)
.await?
.unwrap_or(0)
{
0 => None,
1 => Some(0),
x => Some(x),
};
Ok(val)
}

/// Gets the configured provider.
///
/// The provider is determined by the current primary transport.
Expand Down
22 changes: 0 additions & 22 deletions src/config/config_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,28 +142,6 @@ async fn test_mdns_default_behaviour() -> Result<()> {
Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_delete_server_after_default() -> Result<()> {
let t = &TestContext::new_alice().await;

// Check that the settings are displayed correctly.
assert_eq!(t.get_config(Config::BccSelf).await?, Some("1".to_string()));
assert_eq!(
t.get_config(Config::DeleteServerAfter).await?,
Some("0".to_string())
);

// Leaving emails on the server even w/o `BccSelf` is a good default at least because other
// MUAs do so even if the server doesn't save sent messages to some sentbox (like Gmail
// does).
t.set_config_bool(Config::BccSelf, false).await?;
assert_eq!(
t.get_config(Config::DeleteServerAfter).await?,
Some("0".to_string())
);
Ok(())
}

const SAVED_MESSAGES_DEDUPLICATED_FILE: &str = "969142cb84015bc135767bc2370934a.png";

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
Expand Down
Loading
Loading