diff --git a/components/email/email-viewer.tsx b/components/email/email-viewer.tsx index ccc7b778..31f5d982 100644 --- a/components/email/email-viewer.tsx +++ b/components/email/email-viewer.tsx @@ -2172,6 +2172,26 @@ export function EmailViewer({ lastBodyHeightRef.current = initialHeight; setIframeReady(true); + // Hide images that fail to load (dead/mixed-content/unreachable external + // URLs) rather than leaving the browser's broken-image placeholder and + // alt text, which read as stray label text in an otherwise image-only + // email (e.g. a blocked "logo" alt). Blocked images already carry a 1x1 + // transparent pixel (naturalWidth 1) and display:none, so they're skipped. + const hideIfBroken = (img: HTMLImageElement) => { + if (img.complete && img.naturalWidth === 0 && img.getAttribute('src')) { + img.style.display = 'none'; + } + }; + doc.querySelectorAll('img').forEach((el) => { + const img = el as HTMLImageElement; + if (img.complete) { + hideIfBroken(img); + } else { + img.addEventListener('error', () => { img.style.display = 'none'; }, { once: true }); + img.addEventListener('load', () => hideIfBroken(img), { once: true }); + } + }); + // Make links open in new tab doc.querySelectorAll('a').forEach(a => { a.setAttribute('target', '_blank');