fix: dedup by message_id in imap_sync_folder — stop deleted mails reappearing from Trash
- imap_sync_folder now checks message_id in addition to (folder_id, imap_uid) - If mail was moved to Trash by IMAP server (new UID, same message_id), it is recognized - Soft-deleted mails with matching message_id are skipped, not re-created - Prevents deleted mails from reappearing when IMAP server moves them to Trash
This commit is contained in:
@@ -635,10 +635,41 @@ 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
|
||||||
|
if not existing_mail:
|
||||||
|
# Fetch headers first to get Message-ID
|
||||||
|
fetch_hdr = await client.uid('fetch', uid_str, '(BODY.PEEK[HEADER.FIELDS (MESSAGE-ID)])')
|
||||||
|
hdr_raw = None
|
||||||
|
for line in (fetch_hdr.lines if hasattr(fetch_hdr, 'lines') else fetch_hdr):
|
||||||
|
if isinstance(line, bytearray):
|
||||||
|
hdr_raw = bytes(line)
|
||||||
|
break
|
||||||
|
if hdr_raw:
|
||||||
|
hdr_msg = message_from_bytes(hdr_raw)
|
||||||
|
peek_msg_id = hdr_msg.get("Message-ID", "")
|
||||||
|
if peek_msg_id:
|
||||||
|
existing_mail = (
|
||||||
|
await db.execute(
|
||||||
|
select(Mail).where(
|
||||||
|
and_(
|
||||||
|
Mail.account_id == account.id,
|
||||||
|
Mail.message_id == peek_msg_id,
|
||||||
|
Mail.tenant_id == tenant_id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).scalar_one_or_none()
|
||||||
|
|
||||||
if existing_mail:
|
if existing_mail:
|
||||||
# Don't touch soft-deleted mails — they're being deleted via sync queue
|
# Don't touch soft-deleted mails — they're being deleted via sync queue
|
||||||
if existing_mail.deleted_at is not None:
|
if existing_mail.deleted_at is not None:
|
||||||
continue
|
continue
|
||||||
|
# Update folder_id and imap_uid if mail moved to a different folder
|
||||||
|
if existing_mail.folder_id != folder.id:
|
||||||
|
existing_mail.folder_id = folder.id
|
||||||
|
existing_mail.imap_uid = uid_str
|
||||||
|
elif not existing_mail.imap_uid:
|
||||||
|
existing_mail.imap_uid = uid_str
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Fetch and parse the email
|
# Fetch and parse the email
|
||||||
|
|||||||
Reference in New Issue
Block a user