diff --git a/app/globals.css b/app/globals.css index 1f0a4c0b..28557475 100644 --- a/app/globals.css +++ b/app/globals.css @@ -158,3 +158,57 @@ div[style*="---------- Forwarded message ---------"] { padding: 16px; } +/* Enhanced email content preservation */ +.preserve-email-formatting button, +.preserve-email-formatting a[role="button"], +.preserve-email-formatting a.button, +.preserve-email-formatting .button, +.preserve-email-formatting [class*="btn"], +.preserve-email-formatting [class*="button"] { + display: inline-block; + padding: 0.5rem 1rem; + border-radius: 0.25rem; + background-color: #f97316; /* Orange for the Confirm Now button */ + color: white !important; + text-decoration: none; + font-weight: 500; + text-align: center; + cursor: pointer; + border: none; + margin: 0.5rem 0; +} + +/* Ensure images are displayed properly */ +.preserve-email-formatting img { + max-width: 100%; + height: auto; + display: inline-block; +} + +/* Ensure divs with background images are displayed */ +.preserve-email-formatting [style*="background-image"] { + background-size: contain; + background-repeat: no-repeat; + background-position: center; + min-height: 40px; +} + +/* Preserve text styling */ +.preserve-email-formatting p, +.preserve-email-formatting div, +.preserve-email-formatting span { + margin-bottom: 0.75rem; + max-width: 100%; + word-break: break-word; +} + +/* Ensure the prose class doesn't override important email styling */ +.prose.preserve-email-formatting a { + text-decoration: none; + color: #3b82f6; +} + +.prose.preserve-email-formatting img { + margin: 0; +} + diff --git a/components/email/EmailContent.tsx b/components/email/EmailContent.tsx index 7d20caff..3171a282 100644 --- a/components/email/EmailContent.tsx +++ b/components/email/EmailContent.tsx @@ -43,7 +43,7 @@ export default function EmailContent({ email }: EmailContentProps) { if (isForwarded || isReply) { setContent(
diff --git a/components/email/EmailPreview.tsx b/components/email/EmailPreview.tsx index 644ae22a..16dfa1bb 100644 --- a/components/email/EmailPreview.tsx +++ b/components/email/EmailPreview.tsx @@ -72,7 +72,7 @@ export default function EmailPreview({ email, loading = false, onReply }: EmailP if (isForwarded || isReply) { return (
diff --git a/lib/utils/email-formatter.ts b/lib/utils/email-formatter.ts index 6a529e40..485c0798 100644 --- a/lib/utils/email-formatter.ts +++ b/lib/utils/email-formatter.ts @@ -108,14 +108,34 @@ export function formatEmailDate(date: Date | string | undefined): string { /** * Sanitize HTML content before processing or displaying * This ensures the content is properly sanitized while preserving text direction - * @param content HTML content to sanitize + * @param html HTML content to sanitize * @returns Sanitized HTML with preserved text direction */ -export function sanitizeHtml(content: string): string { - if (!content) return ''; +export function sanitizeHtml(html: string): string { + if (!html) return ''; - // Sanitize the HTML using our configured DOMPurify with text direction preserved - return DOMPurify.sanitize(content); + try { + // Use DOMPurify but ensure we keep all elements and attributes that might be in emails + const clean = DOMPurify.sanitize(html, { + ADD_TAGS: ['button', 'style', 'img', 'iframe', 'meta'], + ADD_ATTR: ['target', 'rel', 'style', 'class', 'id', 'href', 'src', 'alt', 'title', 'width', 'height', 'onclick'], + KEEP_CONTENT: true, + WHOLE_DOCUMENT: false, + ALLOW_DATA_ATTR: true, + ALLOW_UNKNOWN_PROTOCOLS: true, + FORCE_BODY: false, + RETURN_DOM: false, + RETURN_DOM_FRAGMENT: false, + }); + + return clean; + } catch (e) { + console.error('Error sanitizing HTML:', e); + // Fall back to a basic sanitization approach + return html + .replace(/)<[^<]*)*<\/script>/gi, '') + .replace(/on\w+="[^"]*"/g, ''); + } } /**