Skip to content

fix(react-email): leave direction marks out of the preview padding - #3772

Merged
dielduarte merged 3 commits into
resend:canaryfrom
HarshMN2345:fix/preview-padding-direction-marks
Oct 14, 2026
Merged

dielduarte merged 3 commits into
resend:canaryfrom
HarshMN2345:fix/preview-padding-direction-marks

Conversation

@HarshMN2345

@HarshMN2345 HarshMN2345 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Bug fix for #3771.

<Preview> pads the preview with \xa0‌​‍‎‏. rspamd's HIDDEN_TEXT rule ignores all of these as preview padding except the direction marks U+200E and U+200F. A typical 40-character preview gets 320 of them, which is above the rule's 200-character threshold.

This drops the two direction marks from the padding and keeps the other five characters and the length logic as they are. It also updates the renderWhiteSpace test and the two inline snapshots that contain the padding, and adds a patch changeset for react-email.

Verification: I rendered an email with <Preview>Reset your Acme password using the link.</Preview> and scored it with rspamc (rspamd/rspamd:latest, 4.2.1):

  • Before: 9.19, with HIDDEN_TEXT (3.54) and MANY_INVISIBLE_PARTS
  • After: 5.60, with neither rule

The preview and get-email-component tests pass. The pretty test still passes; it uses the old padding as static input.


Summary by cubic

Fixes <Preview> padding in react-email so spam filters such as rspamd no longer flag emails as hidden text. The hidden padding previously included the direction marks U+200E and U+200F, which rspamd's HIDDEN_TEXT rule counts, pushing a 40-character preview past its 200-character threshold.

  • Drops the two direction marks from the padding and keeps the other five characters and the length logic unchanged.
  • Updates the renderWhiteSpace test, the inline snapshots, and the export and get-email-component snapshots, and adds a regression test asserting padding uses only characters spam filters ignore.
  • Adds a patch changeset for react-email; the padding sequence is now \xa0‌​‍, so update any code that matches the old sequence.
  • Verified with rspamc: the sample preview's score dropped from 9.19 to 5.60, with HIDDEN_TEXT and MANY_INVISIBLE_PARTS no longer triggering.

Written for commit f6ee7ba. Summary will update on new commits.

View guided diff

@vercel

vercel Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

@HarshMN2345 is attempting to deploy a commit to the resend Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f6ee7ba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
react-email Patch
@react-email/editor Patch
@react-email/ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the linear-synced PR has been synced to Linear label Oct 5, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/react-email@3772
npm i https://pkg.pr.new/@react-email/ui@3772

commit: f6ee7ba

@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
react-email Ready Ready Preview Oct 14, 2026 7:55pm UTC
react-email-demo Ready Ready Preview Oct 14, 2026 7:55pm UTC

Request Review

HarshMN2345 and others added 3 commits October 14, 2026 16:53
The exported template renders <Preview> from source, so its padding
no longer carries U+200E and U+200F.
… hidden text

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@dielduarte dielduarte left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verified locally:

rspamd 4.2.2 (rspamd/rspamd:4.2.2, the rule shipped in 4.2.0): reproduced the issue. With a 40-char preview, the old padding scores HIDDEN_TEXT (3.54)[354] (320 direction marks + 34 preview chars) plus MANY_INVISIBLE_PARTS (0.05). With this change, neither fires. A Hebrew preview went from HIDDEN_TEXT (3.68) to clean.

Send tests (OLD vs NEW padding, English and Hebrew previews, body includes a canary string to detect leaks):

  • Gmail: identical for English, no body leak. Hebrew now renders in the correct RTL order with NEW (OLD put "Acme" at the wrong end).
  • Outlook.com: preview text then blank padding, no body leak, no garbled characters.
  • Apple Mail: identical for OLD and NEW. Apple Mail builds the snippet from the text/plain part, so the HTML padding doesn't affect it (separate, pre-existing issue).

Pushed on top:

  • A test asserting the padding only contains characters rspamd ignores as preview padding. It fails against the old padding and passes with this change.
  • A changeset note that the padding sequence changed, for anyone string-replacing it in rendered HTML.
  • Rebased onto canary.

Thanks @HarshMN2345!

@dielduarte
dielduarte merged commit 7190dca into resend:canary Oct 14, 2026
13 of 14 checks passed

This branch was successfully deployed

2 active deployments
Preview – react-email-demo — f6ee7ba3 Deployed Oct 14, 2026 by vercel[bot]
Preview – react-email — f6ee7ba3 Deployed Oct 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

linear-synced PR has been synced to Linear

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants