Compare commits

...

3 Commits

Author SHA1 Message Date
iequidoo
8c95336c89 feat: Enable OnlyFetchMvbox by default (#7190)
This is a replacement for 2260156c40 "feat: Don't fetch messages from
unknown folders", but limited to the case with `MvboxMove` enabled. It's enabled by default, so most
users still gain from not fetching messages from unknown folders.
2025-10-24 16:11:20 -03:00
iequidoo
1cf067c045 feat: Always watch Inbox if MvboxMove is set (#7187)
If `OnlyFetchMvbox` is enabled, `MvboxMove` ("Move automatically to DeltaChat folder") makes no
sense: useful messages from "Spam" are moved anyway to "DeltaChat" (see
`imap::spam_target_folder_cfg()`) and Inbox messages aren't fetched and moved. Then `MvboxMove` can
mean "Move Inbox and all scanned folders' messages to DeltaChat", so if it's enabled, Inbox is
watched too, so the user can configure fetching only from "Inbox", "DeltaChat" and "Spam" which was
unachievable before and helps e.g. for the Gmail case which has many virtual folders and the whole
folder scanning process is really slow (and useless for most users):
https://github.com/chatmail/core/issues/7178#issuecomment-3266343253. This may also be useful if the
user has another messenger, e.g. a Delta Chat fork who moves messages to "ZetaChat": this folder
shouldn't be scanned, but Inbox should be. Mvbox is watched anyway, this should just be made clear
to users (if not already).

For existing users accidentally having both options enabled "MvboxMove" is disabled in a migration
to not cause watching Inbox.

Having both options disabled means that we don't separate chat messages from non-chat ones, scanning
all folders is fine in this case.
2025-10-24 16:03:20 -03:00
iequidoo
275630d7c3 feat: Revert "Don't fetch messages from unknown folders (#7190)"
This reverts commit 2260156c40. Some users still want to get messages
from all folders as reported by @gerryfrancis.
2025-10-24 15:53:09 -03:00
6 changed files with 50 additions and 25 deletions

View File

@@ -1776,7 +1776,7 @@ def test_group_quote(acfactory, lp):
"xyz",
False,
"xyz",
), # Test that emails aren't found in a random folder
), # Test that emails are recognized in a random folder but not moved
(
"xyz",
True,
@@ -1806,7 +1806,7 @@ def test_scan_folders(acfactory, lp, folder, move, expected_destination):
ac1.stop_io()
assert folder in ac1.direct_imap.list_folders()
lp.sec("Send a message to from ac2 to ac1 and manually move it to `folder`")
lp.sec("Send a message to from ac2 to ac1 and manually move it to the mvbox")
ac1.direct_imap.select_config_folder("inbox")
with ac1.direct_imap.idle() as idle1:
acfactory.get_accepted_chat(ac2, ac1).send_text("hello")
@@ -1816,17 +1816,10 @@ def test_scan_folders(acfactory, lp, folder, move, expected_destination):
lp.sec("start_io() and see if DeltaChat finds the message (" + variant + ")")
ac1.set_config("scan_all_folders_debounce_secs", "0")
ac1.start_io()
chat = ac1.create_chat(ac2)
n_msgs = 1 # "Messages are end-to-end encrypted."
if folder == "Spam":
msg = ac1._evtracker.wait_next_incoming_message()
assert msg.text == "hello"
n_msgs += 1
else:
ac1._evtracker.wait_idle_inbox_ready()
assert len(chat.get_messages()) == n_msgs
msg = ac1._evtracker.wait_next_incoming_message()
assert msg.text == "hello"
# The message has reached its destination.
# The message has been downloaded, which means it has reached its destination.
ac1.direct_imap.select_folder(expected_destination)
assert len(ac1.direct_imap.get_all_messages()) == 1
if folder != expected_destination:

View File

@@ -165,11 +165,11 @@ pub enum Config {
#[strum(props(default = "1"))]
MvboxMove,
/// Watch for new messages in the "Mvbox" (aka DeltaChat folder) only.
/// Only watch the mvbox (aka DeltaChat folder) and, if `MvboxMove` is set, Inbox.
///
/// This will not entirely disable other folders, e.g. the spam folder will also still
/// be watched for new messages.
#[strum(props(default = "0"))]
/// be scanned for new messages.
#[strum(props(default = "1"))]
OnlyFetchMvbox,
/// Whether to show classic emails or only chat messages.

View File

@@ -823,10 +823,7 @@ impl Session {
.context("listing folders for resync")?;
for folder in all_folders {
let folder_meaning = get_folder_meaning(&folder);
if !matches!(
folder_meaning,
FolderMeaning::Virtual | FolderMeaning::Unknown
) {
if folder_meaning != FolderMeaning::Virtual {
self.resync_folder_uids(context, folder.name(), folder_meaning)
.await?;
}
@@ -2044,9 +2041,9 @@ async fn spam_target_folder_cfg(
}
if needs_move_to_mvbox(context, headers).await?
// If OnlyFetchMvbox is set, we don't want to move the message to
// the inbox or sentbox where we wouldn't fetch it again:
|| context.get_config_bool(Config::OnlyFetchMvbox).await?
// Don't move the message to Inbox if we won't fetch the message again there.
|| (context.get_config_bool(Config::OnlyFetchMvbox).await?
&& !context.get_config_bool(Config::MvboxMove).await?)
{
Ok(Some(Config::ConfiguredMvboxFolder))
} else {
@@ -2573,6 +2570,9 @@ async fn should_ignore_folder(
// Still respect the SentboxWatch setting.
return Ok(!context.get_config_bool(Config::SentboxWatch).await?);
}
if context.is_inbox(folder).await? {
return Ok(!context.get_config_bool(Config::MvboxMove).await?);
}
Ok(!(context.is_mvbox(folder).await? || folder_meaning == FolderMeaning::Spam))
}

View File

@@ -122,8 +122,9 @@ async fn check_target_folder_combination(
t.ctx
.set_config(Config::ConfiguredSentboxFolder, Some("Sent"))
.await?;
t.ctx.set_config_bool(Config::MvboxMove, mvbox_move).await?;
t.ctx
.set_config(Config::MvboxMove, Some(if mvbox_move { "1" } else { "0" }))
.set_config_bool(Config::OnlyFetchMvbox, mvbox_move)
.await?;
if accepted_chat {

View File

@@ -71,10 +71,13 @@ impl Imap {
_ => folder_meaning,
};
// Don't scan folders that are watched anyway
if !watched_folders.contains(&folder.name().to_string())
// Inbox shouldn't be scanned, getting messages from Inbox delayed doesn't make
// sense, the user should enable watching it instead.
&& folder_meaning != FolderMeaning::Inbox
&& folder_meaning != FolderMeaning::Trash
&& folder_meaning != FolderMeaning::Unknown
&& (folder_meaning != FolderMeaning::Unknown
|| !context.get_config_bool(Config::OnlyFetchMvbox).await?)
{
self.fetch_move_delete(context, session, folder.name(), folder_meaning)
.await

View File

@@ -1328,6 +1328,34 @@ CREATE INDEX gossip_timestamp_index ON gossip_timestamp (chat_id, fingerprint);
.await?;
}
inc_and_check(&mut migration_version, 138)?;
if dbversion < migration_version {
// `MvboxMove` now means "watch Inbox also and move chat messages from it". Preserve the old
// behavior for `OnlyFetchMvbox` users.
sql.execute_migration(
"INSERT OR REPLACE INTO config (keyname, value)
SELECT 'mvbox_move', '0'
FROM config WHERE keyname='only_fetch_mvbox' AND value!='0'
",
migration_version,
)
.await?;
}
inc_and_check(&mut migration_version, 139)?;
if dbversion < migration_version {
// `OnlyFetchMvbox` is now 1 by default to avoid scanning unknown folders. But if the user
// disabled `MvboxMove`, we have to keep `OnlyFetchMvbox` unset so that Inbox is watched.
sql.execute_migration(
"INSERT OR IGNORE INTO config (keyname, value)
SELECT 'only_fetch_mvbox', '0'
FROM config WHERE keyname='mvbox_move' AND value='0'
",
migration_version,
)
.await?;
}
let new_version = sql
.get_raw_config_int(VERSION_CFG)
.await?