Files
Ben Gotow ceedb78b3a Add EML export functionality for messages and folders (#2652)
* Implement EML export features: download, forward-as-attachment, drag-and-drop, folder export

Four new client-side EML export capabilities backed by the sync engine's
GetMessageRFC2822Task and a new GetManyRFC2822Task:

- Single message download: "Download as .eml" in message actions menu and
  "Save as .eml..." in thread list context menu (single & multi-select)
- Forward as attachment: new dropdown option that fetches RFC2822 source,
  creates a draft with the .eml attached, and opens the composer
- Drag-and-drop: pre-stages .eml temp files when threads are dragged so
  they're available for external drop targets
- Folder export: right-click any folder in the sidebar to bulk export all
  messages via GetManyRFC2822Task with directory picker

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Move Forward as Attachment to app menu and fix eslint regex errors

- Remove "Forward as Attachment" from the per-message dropdown and
  add it as a Thread > Forward as Attachment menu item (all platforms)
- Register core:forward-as-attachment command handler in MessageList
- Fix no-useless-escape: use character class [/?<>\\:*|"] instead
  of individually escaping each character
- Fix no-control-regex: use \u0000-\u001f unicode escapes in eml-utils

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Consolidate EML filename logic and add Save as .eml to Thread menu

- Reduce eml-utils.ts to a single `defaultEmlFilename()` helper, removing
  the indexed format that duplicates backend logic (GetManyRFC2822Task
  owns indexed naming for folder export)
- Export EmlUtils via mailspring-exports so all consumers share one copy
- Replace 5 inline sanitization regex copies with EmlUtils calls
- Use message ID for temp files (drag, forward) since names don't matter
- Add Thread > Save as .eml... to app menu (all platforms) with
  core:save-as-eml command handler in MessageList

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Add implementation plan for EML import via drag-and-drop

Documents the architecture for allowing users to drag .eml files onto
sidebar folders to upload them to IMAP servers via APPEND. Covers
frontend task class, sidebar drop handler changes, backend sync engine
work, and error handling.

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Forward attachment name, drag-to-desktop, and export progress sidebar

- Rename forwarded attachment from '{messageId}.eml' to
  'Forwarded Message.eml' for a cleaner appearance
- Drag-to-desktop: set text/uri-list with file:// URIs alongside
  internal drag data so desktop file managers (Nautilus, Finder, Dolphin)
  can receive .eml files on drop without breaking internal folder moves
- Add result attribute (total/exported/failed/errors) to
  GetManyRFC2822Task to capture progress data from the sync engine
- New ExportActivity component in the activity sidebar that shows
  real-time export progress with a progress bar, always visible
  (not hidden behind the expand toggle like other sync tasks)

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Remove drag-to-desktop EML export from thread list

Revert the text/uri-list + async fetch approach for drag-to-desktop.
Fetching RFC2822 data from IMAP on every drag start is wasteful since
most drags are internal folder moves. Users can use the right-click
"Save as .eml..." or Thread menu instead.

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Fix three bugs in forward-as-attachment

- Pass from: [account.defaultMe()] alongside accountId to
  DraftFactory.createDraft so multi-account users get the correct
  sender identity instead of the default account's
- Check fs.existsSync after waitForPerformRemote and show an error
  dialog if the RFC2822 fetch failed, preventing orphaned empty drafts
- Use a unique temp directory per message ID (mailspring-fwd-{id}/)
  with a fixed basename of "Forwarded Message.eml" so concurrent
  forward operations don't race on the same file while the attachment
  still has a clean display name

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

* Add Forward as Attachment to thread list right-click menu

Appears after Forward for single-thread selections. Uses the same
pattern as the app menu handler: fetches RFC2822 to a unique temp
directory, checks for errors, creates a draft with correct from/
accountId, attaches the .eml, and pops out the composer.

https://claude.ai/code/session_01DrDkuNAWZEJAvAno9G5csJ

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-09 23:14:30 -05:00
..