Skip to content

fix(mail): restore lost IMAP draft attachments when spool is empty#391

Open
tobias-weiss-ai-xr wants to merge 1 commit into
Alinto:masterfrom
tobias-weiss-ai-xr:fix-draft-attachments-lost
Open

fix(mail): restore lost IMAP draft attachments when spool is empty#391
tobias-weiss-ai-xr wants to merge 1 commit into
Alinto:masterfrom
tobias-weiss-ai-xr:fix-draft-attachments-lost

Conversation

@tobias-weiss-ai-xr

Copy link
Copy Markdown

Description

When reopening a previously saved draft for editing and then saving again, attachments are silently lost. The MIME message during [SOGoDraftObject save] is generated by reading attachment files from the spool directory via bodyPartsForAllAttachmentsfetchAttachmentAttrs. If the spool is empty (server restart, cache cleanup, or a fresh editing session), the method returns zero files and the draft is saved to IMAP without any attachments.

Root Cause

bodyPartsForAllAttachments only reads from the spool directory on disk. It has no fallback to the existing IMAP message, which still holds the original attachment data. When the spool and IMAP are out of sync, attachments are silently dropped during MIME generation.

Fix

Added a guard at the beginning of bodyPartsForAllAttachments in SoObjects/Mailer/SOGoDraftObject.m:

  • If fetchAttachmentAttrs returns 0 files (count == 0), AND the draft has a valid IMAP4ID > -1 (was previously saved to IMAP)...
  • ...create a SOGoMailObject from the existing IMAP message, download all its attachments to the spool directory via the existing _fetchAttachmentsFromMail:onlyImages: method, then re-read the spool.

This ensures attachments are restored from IMAP before MIME generation, without affecting new drafts or drafts that already have files in spool.

Impact

  • New drafts: unaffected (IMAP4ID == -1)
  • Drafts with populated spool: unaffected (count > 0)
  • Reopened drafts with cleaned/empty spool: attachments are now correctly restored from IMAP

See #6046 for related draft attachment handling.

When reopening a previously saved draft for editing, the MIME message during 'save' is generated by reading attachment files from the spool directory only. If the spool directory is empty (server restart, cache cleanup, or fresh editing session), bodyPartsForAllAttachments returns zero files and the draft is saved to IMAP without its attachments — silently losing them.

This fix checks whether the spool has any attachment files before generating the MIME message. If it finds none and the draft has a valid IMAP4ID (was previously saved to IMAP), it downloads the attachments from the existing IMAP draft back into the spool directory via the existing _fetchAttachmentsFromMail:onlyImages: method, then retries the spool read. This ensures attachments are preserved across editing sessions.

The fix only triggers when count == 0 (spool empty) and IMAP4ID > -1 (draft exists in IMAP), so it never affects new drafts or drafts with files already in spool.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant