fix(imap): fetch full message for attachment download to fix base64 decoding

A partial BODY.PEEK[n] fetch omits the section's MIME headers, so
enough_mail's decodeContentBinary() has no Content-Transfer-Encoding
and returns the raw base64 string instead of the decoded bytes.
Fetching BODY.PEEK[] gives enough_mail the full MIME structure and
getPart(fetchPartId) correctly decodes the attachment.

Also adds an integration test that creates an email with a binary
attachment, syncs it, and asserts the downloaded bytes match the
original — this test failed before the fix.

Closes #70

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Thomas SharedInbox
2026-05-14 19:44:09 +02:00
co-authored by Claude Sonnet 4.6
parent 3802ca57ed
commit ca28bd01af
2 changed files with 62 additions and 1 deletions
@@ -2509,9 +2509,13 @@ class EmailRepositoryImpl implements EmailRepository {
);
try {
await client.selectMailboxByPath(emailRow.mailboxPath);
// Fetch the full message so enough_mail has MIME headers (including
// Content-Transfer-Encoding) and getPart() can decode the part correctly.
// A partial BODY.PEEK[n] fetch omits those headers, causing
// decodeContentBinary() to return raw base64 instead of decoded bytes.
final fetch = await client.uidFetchMessage(
emailRow.uid,
'BODY.PEEK[${attachment.fetchPartId}]',
'BODY.PEEK[]',
);
final msg = fetch.messages.first;
final part = msg.getPart(attachment.fetchPartId) ?? msg;