Skip to content

fix(eml-preview): recover PDF MIME type from extension when email declares octet-stream (ERMAIN-550) - #928

Merged
bdart merged 3 commits into
mainfrom
feat/eml-attachment-mime-fix-e7cb
Aug 9, 2026
Merged

fix(eml-preview): recover PDF MIME type from extension when email declares octet-stream (ERMAIN-550)#928
bdart merged 3 commits into
mainfrom
feat/eml-attachment-mime-fix-e7cb

Conversation

@bdart

@bdart bdart commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Problem

When viewing an EML email preview and clicking a PDF attachment listed inside the email, the browser downloads the file instead of opening a nested inline preview. The downloaded file has no extension — the filename is a bare UUID (the UUID portion of the blob URL).

Root cause: Email clients sometimes send PDF attachments with Content-Type: application/octet-stream instead of application/pdf. When EmlPreview parses such an email via PostalMime, it creates a Blob typed as application/octet-stream. Browsers treat blob URLs with that content type as binary downloads rather than rendering them inline in an <iframe>. Since blob:// URLs carry no filename metadata, the download filename defaults to the blob's UUID.

Fix

Added recoverMimeType() in EmlPreview.tsx — a small helper that upgrades a generic application/octet-stream MIME type to a more specific one derived from the filename extension, before the Blob is created. Currently maps:

  • .pdfapplication/pdf
  • .emlmessage/rfc822

Applied in two places:

  1. attachmentBlob() — ensures the Blob itself has the correct type, so <iframe src={blobUrl}> renders inline rather than triggering a download.
  2. ParsedAttachment.mimeType — ensures FilePreviewContent also receives the recovered type for routing (e.g. isPdf check).

Both EmlPreviewBody (direct attachments) and EmlThreadBody (nested thread message attachments) are covered.

Tests

Added 4 new test cases in EmlPreview.test.tsx:

  • Clicking a application/pdf-typed PDF shows the inline PDF viewer (file-preview-pdf) with a working back button.
  • Clicking an application/octet-stream-typed PDF (the bug scenario) also shows the inline PDF viewer — not a download.
  • The blob created for an application/octet-stream PDF attachment has its MIME type recovered to application/pdf (directly verifies the fix prevents the browser from triggering a download).
  • The last test is explicitly labelled as an ERMAIN-550 regression guard.

cursoragent and others added 2 commits August 9, 2026 17:21
…lares octet-stream

When an email client sends a PDF attachment with
Content-Type: application/octet-stream instead of application/pdf,
the browser treats the blob URL as a binary download rather than
rendering it inline in the iframe. The download filename defaults to
the bare UUID from the blob URL since there is no filename metadata
associated with blob:// URLs.

Fix: add recoverMimeType() that uses the filename extension to upgrade
a generic application/octet-stream to the specific type (pdf, eml)
before creating the Blob. Apply this both to the blob itself (so the
browser renders inline) and to ParsedAttachment.mimeType (so
FilePreviewContent routes correctly).

Applies to both EmlPreviewBody (direct attachments) and EmlThreadBody
(nested thread message attachments).

Fixes ERMAIN-550

Co-authored-by: Daniel <bdart@users.noreply.github.com>
PostalMime types `Attachment.filename` as `string | null`, so the helper
signature broke the frontend library build and every job downstream of it.

Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com>
@bdart
bdart force-pushed the feat/eml-attachment-mime-fix-e7cb branch from 39cc7bb to 86783fb Compare August 9, 2026 15:22
@bdart
bdart marked this pull request as ready for review August 9, 2026 15:32
@bdart
bdart enabled auto-merge (squash) August 9, 2026 15:40
@bdart
bdart merged commit 1394215 into main Aug 9, 2026
32 checks passed
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.

2 participants