fix: stop cross-folder message_id dedup — mails were being moved between folders

- message_id dedup was searching across ALL folders
- A mail in Trash with same message_id as one in INBOX was found and moved to INBOX
- Now message_id dedup only searches within the SAME folder
- This matches how real mail clients work: same message_id in different folders = separate copies
This commit is contained in:
Agent Zero
2026-07-20 14:03:19 +02:00
parent 1a2f7f3ab6
commit 4acebe55e5
+5 -1
View File
@@ -636,7 +636,9 @@ async def imap_sync_folder(
) )
).scalar_one_or_none() ).scalar_one_or_none()
# Also check by message_id — mail may have been moved to Trash by IMAP server # Also check by message_id — but ONLY within the same folder
# to prevent cross-folder moves. A mail in Trash and INBOX with
# the same message_id are separate copies (like real mail clients).
if not existing_mail: if not existing_mail:
# Fetch headers first to get Message-ID # Fetch headers first to get Message-ID
fetch_hdr = await client.uid('fetch', uid_str, '(BODY.PEEK[HEADER.FIELDS (MESSAGE-ID)])') fetch_hdr = await client.uid('fetch', uid_str, '(BODY.PEEK[HEADER.FIELDS (MESSAGE-ID)])')
@@ -655,6 +657,7 @@ async def imap_sync_folder(
and_( and_(
Mail.account_id == account.id, Mail.account_id == account.id,
Mail.message_id == peek_msg_id, Mail.message_id == peek_msg_id,
Mail.folder_id == folder.id,
Mail.tenant_id == tenant_id, Mail.tenant_id == tenant_id,
) )
) )
@@ -1163,6 +1166,7 @@ async def imap_sync_account(
and_( and_(
Mail.account_id == account.id, Mail.account_id == account.id,
Mail.message_id == message_id, Mail.message_id == message_id,
Mail.folder_id == folder.id,
Mail.tenant_id == tenant_id, Mail.tenant_id == tenant_id,
) )
) )