Skip to content

Raw tab freezes the UI on large messages (1.5 MB email = ~7 s main-thread block) #50

Description

@xsmyile

What happens

Opening the Raw tab on a message with PDF attachments freezes the tab for several seconds; on a slow machine or a bigger message Chrome shows Page unresponsive.

Reproduced with a real message from a Django app that mails a contract PDF + an instructions PDF (1,548,621 bytes on the wire, ~20k lines of base64, longest line 135 chars).

Measured in the running app (localhost:8025, Chrome, M-series):

click "Raw" -> 7267 ms main thread blocked
<pre> text length: 1548621
<pre> scrollHeight: 389174 px
JS heap after:  4 MB

Heap stays tiny, so this is layout/paint, not memory: the whole raw source is dropped into one non-virtualized <pre> and the browser lays out ~20k line boxes in a single frame.

Where

ui/src/components/MessageDetail.tsx:613RawView renders the entire string at once:

<pre class="p-4 text-xs ... whitespace-pre-wrap font-mono leading-relaxed">
  {raw()}
</pre>

There is no size cap and no virtualization anywhere in ui/src.

The server side is fine: GET /api/v1/messages/{id}/raw (crates/rustmail-api/src/handlers.rs:222) answered the 1.5 MB body in 2.5 ms.

Related, same file

ui/src/components/MessageDetail.tsx:38 — the rawSource resource is created on selectedId, so the full raw body is fetched for every selected message even when the user never opens Raw or Headers. Headers only needs the block before the first blank line.

Possible fixes

  • Cap what RawView renders (first N KB) with an explicit "showing first N KB of X — download .eml" affordance, and link exportUrl(id, "eml").
  • Or chunk/virtualize the <pre> (render slices on scroll) so layout cost is bounded.
  • Independently: fetch raw lazily, only when tab() is raw or headers — or add a ?headers_only=1 variant for the Headers tab.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions