Skip to content

[Website] Add captured mail viewer - #4000

Merged
mho22 merged 13 commits into
bgrgicak/forward-sendmail-eventfrom
bgrgicak/playground-email-tab
Aug 13, 2026
Merged

mho22 merged 13 commits into
bgrgicak/forward-sendmail-eventfrom
bgrgicak/playground-email-tab

Conversation

@bgrgicak

@bgrgicak bgrgicak commented Jul 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds an Email panel to the Playground Site Manager for viewing messages captured from the active site, including message and attachment previews.

Motivation for the change, related issues

Builds on #4103 and #3996 to make captured sendmail messages available in the Site Manager UI. Related issue: #3994.

Implementation details

  • Reads parsed messages from the active site's clientInfo.emails array and selects the newest message by default.
  • Displays message metadata and HTML or plain-text content. HTML and attachment-bearing messages render in a no-referrer, sandboxed iframe; links open outside the preview, while scripts and forms remain blocked.
  • Resolves cid: images and attachments to temporary Blob URLs, with image, video, and audio previews and downloads. URLs are revoked when no longer needed.
  • Uses @wordpress/components for the message list, empty state, and metadata. Attachment cards use isolated styles in a declarative shadow root.
  • Keeps messages in memory for the site client's lifetime. Aggregate retention is unbounded, there is no clear-mailbox action, and messages are discarded when the client restarts or is removed, or the page reloads.
  • Adds Playwright coverage that sends mail through PHP and verifies the captured subject and body in the Email panel.

Testing Instructions

  1. Start the website with npm run dev.
  2. Open the local Playground website with this Blueprint.
  3. Open Email in the Site Manager and confirm the empty state is shown.
  4. Select Send test email in the site's admin bar.
  5. Confirm the message metadata, HTML, special characters, images, and external links render correctly.
  6. Confirm supported attachments can be previewed and all attachments can be downloaded.
Email panel showing a captured message

@bgrgicak
bgrgicak force-pushed the bgrgicak/playground-email-tab branch from 8e0d1a0 to f7f91a8 Compare July 17, 2026 12:51
@bgrgicak
bgrgicak changed the base branch from trunk to bgrgicak/forward-sendmail-event July 17, 2026 13:02
@mho22 mho22 self-assigned this Jul 24, 2026
Comment on lines +60 to +65
const attachmentsHtml = renderToStaticMarkup(
<MailAttachments
attachments={mail.attachments}
resources={attachmentResources}
/>
);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the UI, I wanted attachments to be placed after the email content so it can grow vertically.
For this we needed the email content and attachment to be displayed with their full height, otherwise we would have two vertical scroll bars, one for the email content and another for attachments.

First I tried dynamically changing the height of the iframe with JavaScript, but that felt wrong, so I ended up moving attachments to the iframe and ensure we have one iframe this way.

@bgrgicak
bgrgicak marked this pull request as ready for review July 24, 2026 20:37
@bgrgicak
bgrgicak requested a review from adamziel July 24, 2026 20:37
@mho22
mho22 self-requested a review August 13, 2026 14:45
@mho22
mho22 merged commit f39795a into trunk Aug 13, 2026
57 checks passed
@mho22
mho22 deleted the bgrgicak/playground-email-tab branch August 13, 2026 14:45
mho22 added a commit that referenced this pull request Aug 13, 2026
## Summary

Forwards captured `sendmail` messages through the Playground client and
stores parsed messages in each site's website state for the inbox UI
planned in #4000 as part of #3994.

## Rationale

Email capture currently stops inside the PHP worker. Website components
need structured messages they can consume. This PR adds that plumbing
only; it does not add an inbox UI or deliver mail to the internet.

## Implementation details

- Forwards `sendmail.spawned` from each PHP instance while avoiding
duplicate forwarding listeners on reused instances.
- Re-brands the event at the remote API boundary so its `stdin` stream
crosses both Comlink hops, then parses messages with `postal-mime`.
- Processes messages sequentially and prepends them to
`clientInfo.emails`, preserving newest-first event order. Parse failures
do not block later messages.
- Prevents aborted sites from storing parsed messages and cancels queued
streams as they are reached.
- Initializes the runtime client state with `emails` and excludes parsed
email objects from Redux serializability checks.

Capture starts after `startPlaygroundWeb()` completes, so mail sent
during initial boot or Blueprint execution is not retained. Messages are
held only in memory and are discarded when the client restarts, is
removed, or the page reloads. Each source message is limited to 20 MiB,
but aggregate retention remains unbounded until the inbox UI adds an
eviction policy.

## Testing Instructions

- CI

---------

Co-authored-by: mho22 <yannick@capsules.codes>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants