fix: stop sync from moving Trash mails back to Inbox

- When mail is moved to Trash in DB (folder_id=Trash, deleted_at set) but IMAP MOVE fails,
  the mail stays in INBOX on the IMAP server
- Previously sync restored deleted_at and moved folder_id back to INBOX
- Now sync only restores if mail is in the SAME folder in DB and IMAP
- If mail is in Trash in DB but INBOX on IMAP, skip it — sync queue will retry the MOVE
This commit is contained in:
Agent Zero
2026-07-20 13:56:30 +02:00
parent 7631698215
commit 1a2f7f3ab6
+26 -5
View File
@@ -663,11 +663,21 @@ async def imap_sync_folder(
if existing_mail: if existing_mail:
# If mail has deleted_at but is still on the IMAP server, # If mail has deleted_at but is still on the IMAP server,
# the IMAP delete failed — restore it so it's visible again. # the IMAP delete failed.
# This prevents mails from being permanently hidden when IMAP delete fails. # Only restore if the mail is in the SAME folder we're syncing.
# If the mail was moved to Trash in DB (folder_id=Trash) but is
# still in INBOX on IMAP, DON'T restore to INBOX — keep it
# in Trash and let the sync queue retry the IMAP MOVE.
if existing_mail.deleted_at is not None: if existing_mail.deleted_at is not None:
if existing_mail.folder_id == folder.id:
# Mail is in the right folder on IMAP — restore
existing_mail.deleted_at = None existing_mail.deleted_at = None
logger.info("imap_sync_folder: restored mail %s (still on IMAP server, delete had failed)", existing_mail.id) logger.info("imap_sync_folder: restored mail %s (still on IMAP server in correct folder)", existing_mail.id)
else:
# Mail is in a different folder in DB — IMAP move failed
# Don't restore, don't change folder_id — keep in Trash
logger.info("imap_sync_folder: skipping mail %s (deleted, in folder %s but found in %s on IMAP, move failed)", existing_mail.id, existing_mail.folder_id, folder.imap_name)
continue
# Update folder_id and imap_uid if mail moved to a different folder # Update folder_id and imap_uid if mail moved to a different folder
if existing_mail.folder_id != folder.id: if existing_mail.folder_id != folder.id:
existing_mail.folder_id = folder.id existing_mail.folder_id = folder.id
@@ -1161,10 +1171,21 @@ async def imap_sync_account(
if existing_mail: if existing_mail:
# If mail has deleted_at but is still on the IMAP server, # If mail has deleted_at but is still on the IMAP server,
# the IMAP delete failed — restore it so it's visible again. # the IMAP delete failed.
# Only restore if the mail is in the SAME folder we're syncing.
# If the mail was moved to Trash in DB (folder_id=Trash) but is
# still in INBOX on IMAP, DON'T restore to INBOX — keep it
# in Trash and let the sync queue retry the IMAP MOVE.
if existing_mail.deleted_at is not None: if existing_mail.deleted_at is not None:
if existing_mail.folder_id == folder.id:
# Mail is in the right folder on IMAP — restore
existing_mail.deleted_at = None existing_mail.deleted_at = None
logger.info("imap_sync_account: restored mail %s (still on IMAP server, delete had failed)", existing_mail.id) logger.info("imap_sync_account: restored mail %s (still on IMAP server in correct folder)", existing_mail.id)
else:
# Mail is in a different folder in DB — IMAP move failed
# Don't restore, don't change folder_id — keep in Trash
logger.info("imap_sync_account: skipping mail %s (deleted, in folder %s but found in %s on IMAP, move failed)", existing_mail.id, existing_mail.folder_id, folder.imap_name)
continue
# Track folder moves: update folder_id and imap_uid if the # Track folder moves: update folder_id and imap_uid if the
# mail now appears in a different IMAP folder. # mail now appears in a different IMAP folder.
if existing_mail.folder_id != folder.id: if existing_mail.folder_id != folder.id: