E-Mail-Detail: Links sichtbar + Header kompakter

Bug 1 (Header gestaucht): kompakteres Vertical-Spacing im
Header (px-4 pt-3 pb-2 statt p-4, space-y-2 statt -3),
Subject auf max 2 Zeilen begrenzt mit vollem Titel im
tooltip. min-h-0 auf der Flex-Container, damit der Body
tatsächlich flex-1 claimt.

Bug 2 (Link unsichtbar): Corporate-CTAs stylen ihre Buttons
gerne mit inline style="color:white;background:green"; der
zugehörige <style>-Block wird von DOMPurify entfernt, das
inline-style am <a> überlebt aber – Ergebnis: weißer Link
auf weißem CRM-Hintergrund, unsichtbar. Fix: von <a>-Tags
werden style und class gestrippt, dann greift Browser-
Default (blau/violett + unterstrichen) wieder.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-17 12:47:59 +02:00
co-authored by Claude Opus 4.7
parent b099297e11
commit 9425cb2ab6
+23 -6
View File
@@ -54,6 +54,15 @@ export default function EmailDetail({
// Email-Body sanitizen + alle <a>-Links auf neuen Tab umstellen. // Email-Body sanitizen + alle <a>-Links auf neuen Tab umstellen.
// rel="noopener noreferrer" verhindert window.opener-Tab-Hijacking. // rel="noopener noreferrer" verhindert window.opener-Tab-Hijacking.
//
// 2026-07-17: Zusätzlich werden von <a>-Tags inline `style` und `class`
// gestrippt. Grund: Corporate-Emails (Grünwelt/Vodafone/Klarmobil …)
// stylen ihre CTA-Buttons oft mit `style="color:white;background:green"`.
// Der zugehörige `<style>`-Block wird von DOMPurify entfernt (=> FORBID_TAGS),
// aber inline-styles am `<a>` selbst überleben Ergebnis: weißer Link
// auf weißem CRM-Hintergrund, unsichtbar (User-Bug 2026-07-17). Wir
// fahren die Links auf Browser-Default runter, dann rendert der Link
// wieder als blau/violett + unterstrichen.
const safeHtmlBody = useMemo(() => { const safeHtmlBody = useMemo(() => {
if (!email.htmlBody) return ''; if (!email.htmlBody) return '';
const sanitized = DOMPurify.sanitize(email.htmlBody, { const sanitized = DOMPurify.sanitize(email.htmlBody, {
@@ -66,6 +75,9 @@ export default function EmailDetail({
wrapper.querySelectorAll('a').forEach((a) => { wrapper.querySelectorAll('a').forEach((a) => {
a.setAttribute('target', '_blank'); a.setAttribute('target', '_blank');
a.setAttribute('rel', 'noopener noreferrer'); a.setAttribute('rel', 'noopener noreferrer');
// Corporate-CTA-Styling raus, sonst weiß-auf-weiß nicht sichtbar.
a.removeAttribute('style');
a.removeAttribute('class');
}); });
return wrapper.innerHTML; return wrapper.innerHTML;
}, [email.htmlBody]); }, [email.htmlBody]);
@@ -197,12 +209,17 @@ export default function EmailDetail({
const attachments = parseAttachments(email.attachmentNames); const attachments = parseAttachments(email.attachmentNames);
return ( return (
<div className="flex flex-col h-full"> <div className="flex flex-col h-full min-h-0">
{/* Header */} {/* Header kompakter Vertical-Rhythm, damit der Body-Bereich bei
<div className="p-4 border-b border-gray-200 space-y-3"> langen Betreffen nicht auf 100px zusammengestaucht wird. Subject
wird auf max 2 Zeilen begrenzt (mit vollem Titel im tooltip). */}
<div className="px-4 pt-3 pb-2 border-b border-gray-200 space-y-2 flex-shrink-0">
{/* Subject & Actions */} {/* Subject & Actions */}
<div className="flex items-start justify-between gap-4"> <div className="flex items-start justify-between gap-4">
<h2 className="text-lg font-semibold text-gray-900"> <h2
className="text-lg font-semibold text-gray-900 line-clamp-2 leading-snug"
title={email.subject || undefined}
>
{email.subject || '(Kein Betreff)'} {email.subject || '(Kein Betreff)'}
</h2> </h2>
<div className="flex items-center gap-2 flex-shrink-0"> <div className="flex items-center gap-2 flex-shrink-0">
@@ -291,8 +308,8 @@ export default function EmailDetail({
</div> </div>
</div> </div>
{/* From/To/Date */} {/* From/To/Date tighter leading */}
<div className="text-sm space-y-1"> <div className="text-sm space-y-0.5">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-gray-500 w-12">Von:</span> <span className="text-gray-500 w-12">Von:</span>
<span className="font-medium text-gray-900"> <span className="font-medium text-gray-900">