From b3555876a0d8722ae99cbad441193b3e088a3c4e Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 18 Aug 2026 05:17:41 +0200 Subject: [PATCH] fix: render text-only emails in the email preview The email details preview always fed the html body into the iframe, so emails sent with only a text body showed an empty preview. Fall back to the text body, escaped and wrapped in a minimal pre document, and show a placeholder when the email has no content at all. --- .../app/(dashboard)/emails/email-details.tsx | 28 +++++++++++++-- apps/web/src/lib/email-preview.ts | 27 +++++++++++++++ apps/web/src/lib/email-preview.unit.test.ts | 34 +++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 apps/web/src/lib/email-preview.ts create mode 100644 apps/web/src/lib/email-preview.unit.test.ts diff --git a/apps/web/src/app/(dashboard)/emails/email-details.tsx b/apps/web/src/app/(dashboard)/emails/email-details.tsx index f5bbedbf..22118428 100644 --- a/apps/web/src/app/(dashboard)/emails/email-details.tsx +++ b/apps/web/src/app/(dashboard)/emails/email-details.tsx @@ -20,6 +20,7 @@ import { COMPLAINT_ERROR_MESSAGES, DELIVERY_DELAY_ERRORS, } from "@usesend/lib/src/constants/ses-errors"; +import { getEmailPreviewSrcDoc } from "~/lib/email-preview"; import CancelEmail from "./cancel-email"; import { useEffect } from "react"; import { useState } from "react"; @@ -90,7 +91,10 @@ export default function EmailDetails({ emailId }: { emailId: string }) { animate={{ opacity: 1 }} transition={{ duration: 0.2, delay: 0.3 }} > - + {emailQuery.data?.latestStatus !== "SCHEDULED" ? ( @@ -134,7 +138,13 @@ export default function EmailDetails({ emailId }: { emailId: string }) { ); } -const EmailPreview = ({ html }: { html: string }) => { +const EmailPreview = ({ + html, + text, +}: { + html: string | null | undefined; + text: string | null | undefined; +}) => { const [show, setShow] = useState(false); useEffect(() => { @@ -145,17 +155,29 @@ const EmailPreview = ({ html }: { html: string }) => { return () => clearTimeout(timer); }, []); + const srcDoc = getEmailPreviewSrcDoc(html, text); + if (!show) { return (
); } + if (!srcDoc) { + return ( +
+ + No content to preview + +
+ ); + } + return (