From c15e79c5a184c1f1e54ed3b31e68e5e21fe8fbd2 Mon Sep 17 00:00:00 2001 From: alma Date: Thu, 1 May 2025 12:50:00 +0200 Subject: [PATCH] courrier preview --- components/email/ComposeEmail.tsx | 78 +++++++++++------------- components/email/EmailContentDisplay.tsx | 29 +-------- components/email/EmailDetailView.tsx | 38 +++++++++--- components/email/RichEmailEditor.tsx | 30 ++------- lib/utils/email-content.ts | 45 ++------------ lib/utils/email-utils.ts | 74 +++++++++++----------- 6 files changed, 110 insertions(+), 184 deletions(-) diff --git a/components/email/ComposeEmail.tsx b/components/email/ComposeEmail.tsx index b71684b8..f825c940 100644 --- a/components/email/ComposeEmail.tsx +++ b/components/email/ComposeEmail.tsx @@ -200,58 +200,48 @@ export default function ComposeEmail(props: ComposeEmailProps) { // Provide a basic template if the content is empty const { fromStr, toStr, ccStr, dateStr, subject } = getFormattedInfoForEmail(initialEmail); const fallbackContent = ` -
-
-
-
---------------------------- Forwarded Message ----------------------------
-
- - - - - - - - - - - - - - - - - - ${ccStr ? ` - - - - ` : ''} -
From:${fromStr}
Date:${dateStr}
Subject:${subject || ''}
To:${toStr}
Cc:${ccStr}
-
-
----------------------------------------------------------------------
-
+
+
+
---------------------------- Forwarded Message ----------------------------
-
[Original message content could not be loaded]
+ + + + + + + + + + + + + + + + + + ${ccStr ? ` + + + + ` : ''} +
From:${fromStr}
Date:${dateStr}
Subject:${subject || ''}
To:${toStr}
Cc:${ccStr}
+
+
----------------------------------------------------------------------
+
+
+
+ [Original message content could not be loaded]
`; setEmailContent(fallbackContent); } else { console.log('Setting forward content:', { length: content.length, - isHtml: formatted.content.isHtml, - hasForwardedTable: content.includes('---------------------------- Forwarded Message ----------------------------'), - hasClosingContainer: content.includes('
') + isHtml: formatted.content.isHtml }); - - // Ensure the content is wrapped in a div to preserve structure - // Add a distinctive id to help with debugging - if (!content.startsWith('${content}`; - setEmailContent(wrappedContent); - } else { - setEmailContent(content); - } + setEmailContent(content); } // Handle attachments for forward (original attachments + extracted inline images) diff --git a/components/email/EmailContentDisplay.tsx b/components/email/EmailContentDisplay.tsx index 0b4b1620..5ba2c26b 100644 --- a/components/email/EmailContentDisplay.tsx +++ b/components/email/EmailContentDisplay.tsx @@ -73,11 +73,7 @@ const EmailContentDisplay: React.FC = ({

Content Type: {typeof content === 'string' ? 'Text' : 'HTML'}

HTML Length: {typeof content === 'string' ? content.length : content?.html?.length || 0}

-

Text Length: {typeof content === 'string' ? 0 : content?.text?.length || 0}

-

Has Forwarded Header: {typeof content === 'string' ? - content.includes('Forwarded Message') : - (content?.html?.includes('Forwarded Message') || content?.text?.includes('Forwarded Message')) ? 'Yes' : 'No' - }

+

Text Length: {typeof content === 'string' ? content.length : content?.text?.length || 0}

)} @@ -107,29 +103,6 @@ const EmailContentDisplay: React.FC = ({ border-left: none; border-right: 2px solid #ddd; } - - /* Specific styling for forwarded email header */ - :global(.forwarded-email-header) { - margin: 20px 0 10px 0 !important; - color: #666 !important; - font-family: Arial, sans-serif !important; - } - - :global(.forwarded-email-header table) { - margin-bottom: 10px !important; - font-size: 14px !important; - width: 100% !important; - border-collapse: collapse !important; - } - - :global(.forwarded-email-header td) { - padding: 3px 5px !important; - vertical-align: top !important; - } - - :global(.forwarded-email-content) { - margin-top: 15px !important; - } `} ); diff --git a/components/email/EmailDetailView.tsx b/components/email/EmailDetailView.tsx index eaa26f36..afb1ef28 100644 --- a/components/email/EmailDetailView.tsx +++ b/components/email/EmailDetailView.tsx @@ -48,19 +48,39 @@ export default function EmailDetailView({ console.log('EmailDetailView renderEmailContent', { hasContent: !!email.content, contentType: typeof email.content, - hasHtml: !!email.content?.html, - hasText: !!email.content?.text + hasHtml: !!email.html, + hasText: !!email.text }); - // Import the centralized rendering function - const { formatEmailContent } = require('@/lib/utils/email-utils'); + // Determine what content to use and how to handle it + let contentToUse = ''; - // Use the centralized formatting function - const formattedContent = formatEmailContent(email); + if (email.content) { + // If content is a string, use it directly + if (typeof email.content === 'string') { + contentToUse = email.content; + } + // If content is an object with html/text properties + else if (typeof email.content === 'object') { + contentToUse = email.content.html || email.content.text || ''; + } + } + // Fall back to html or text properties if content is not available + else if (email.html) { + contentToUse = email.html; + } + else if (email.text) { + // Convert plain text to HTML with line breaks + contentToUse = email.text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/\n/g, '
'); + } - // Return formatted content or fallback message - return formattedContent ? -
: + // Return content or fallback message + return contentToUse ? +
:
No content available
; } catch (e) { console.error('Error rendering email:', e); diff --git a/components/email/RichEmailEditor.tsx b/components/email/RichEmailEditor.tsx index 53fe2e6f..e7a1c310 100644 --- a/components/email/RichEmailEditor.tsx +++ b/components/email/RichEmailEditor.tsx @@ -91,22 +91,13 @@ const RichEmailEditor: React.FC = ({ console.log('Setting initial content in editor', { length: initialContent.length, startsWithHtml: initialContent.trim().startsWith('<'), - hasForwardedHeader: initialContent.includes('Forwarded Message'), }); // Detect text direction const direction = detectTextDirection(initialContent); - // Preserve forwarded email structure by wrapping in a container if needed - let contentToSet = initialContent; - if (initialContent.includes('Forwarded Message') && !initialContent.includes('forwarded-email-container')) { - // This might be a forwarded email that wasn't properly wrapped - contentToSet = `
${initialContent}
`; - console.log('Adding container to forwarded email content'); - } - // Process HTML content using centralized utility - const sanitizedContent = processHtmlContent(contentToSet); + const sanitizedContent = processHtmlContent(initialContent); // Check if sanitized content is valid if (sanitizedContent.trim().length === 0) { @@ -114,7 +105,7 @@ const RichEmailEditor: React.FC = ({ // Try to extract text content if HTML processing failed try { const tempDiv = document.createElement('div'); - tempDiv.innerHTML = contentToSet; + tempDiv.innerHTML = initialContent; const textContent = tempDiv.textContent || tempDiv.innerText || 'Empty content'; // Set text directly to ensure something displays @@ -218,36 +209,27 @@ const RichEmailEditor: React.FC = ({ try { console.log('Updating content in editor:', { contentLength: initialContent.length, - startsWithHtml: initialContent.trim().startsWith('<'), - hasForwardedHeader: initialContent.includes('Forwarded Message'), + startsWithHtml: initialContent.trim().startsWith('<') }); // Detect text direction const direction = detectTextDirection(initialContent); - // Special handling for forwarded email content - let contentToSet = initialContent; - if (initialContent.includes('Forwarded Message') && !initialContent.includes('forwarded-email-container')) { - // This might be a forwarded email that wasn't properly wrapped - contentToSet = `
${initialContent}
`; - console.log('Adding container to forwarded email content during update'); - } - // Process HTML content using centralized utility - const sanitizedContent = processHtmlContent(contentToSet); + const sanitizedContent = processHtmlContent(initialContent); // Check if content is valid HTML if (sanitizedContent.trim().length === 0) { console.warn('Sanitized content is empty, using original content'); // If sanitized content is empty, try to extract text from original const tempDiv = document.createElement('div'); - tempDiv.innerHTML = contentToSet; + tempDiv.innerHTML = initialContent; const textContent = tempDiv.textContent || tempDiv.innerText || ''; // Create simple HTML with text content quillRef.current.setText(textContent); } else { - // Set content directly to the root element rather than using clipboard + // SIMPLIFIED: Set content directly to the root element rather than using clipboard quillRef.current.root.innerHTML = sanitizedContent; // Set the direction for the content diff --git a/lib/utils/email-content.ts b/lib/utils/email-content.ts index c6eaac4c..dac643c4 100644 --- a/lib/utils/email-content.ts +++ b/lib/utils/email-content.ts @@ -65,27 +65,6 @@ export function extractEmailContent(email: any): { text: string; html: string } } } } - - // Special case for YCharts and similar emails where content is detected as object - // but doesn't have standard html/text properties - stringify and try to extract - if (!textContent && !htmlContent) { - try { - // Try to extract from stringified version - const contentString = JSON.stringify(email.content); - if (contentString && contentString.includes(']*>([\s\S]*)<\/html>/i) || - contentString.match(/]*>([\s\S]*)<\/body>/i); - - if (htmlMatch && htmlMatch[1]) { - htmlContent = htmlMatch[1]; - console.log('Extracted HTML from stringified content object'); - } - } - } catch (err) { - console.warn('Failed to extract from stringified content:', err); - } - } } } else if (typeof email.content === 'string') { // Check if content is likely HTML @@ -234,16 +213,6 @@ export function processHtmlContent(htmlContent: string, textContent?: string): s // Use the centralized sanitizeHtml function let sanitizedContent = sanitizeHtml(htmlContent); - // If sanitized content is empty but original content wasn't, - // try to extract text as a fallback - if (!sanitizedContent.trim() && htmlContent.trim()) { - console.warn('Sanitized content is empty, attempting to extract text as fallback'); - const extractedText = extractTextFromHtml(htmlContent); - if (extractedText) { - return `
${extractedText}
`; - } - } - // Fix URL encoding issues and clean up content try { if (typeof window !== 'undefined' && typeof document !== 'undefined') { @@ -274,14 +243,12 @@ export function processHtmlContent(htmlContent: string, textContent?: string): s if (src) { // Don't modify cid: URLs as they are handled specially in email clients if (src.startsWith('cid:')) { - // Keep cid: URLs as they are but add data attribute for debugging - img.setAttribute('data-cid-preserved', 'true'); + // Keep cid: URLs as they are console.log('Preserving CID reference:', src); } - // Fix http:// URLs to https:// for security - unless they're to known image hosts + // Fix http:// URLs to https:// for security else if (src.startsWith('http://')) { img.setAttribute('src', src.replace('http://', 'https://')); - console.log('Fixed HTTP image URL:', src); } // Handle relative URLs that might be broken else if (!src.startsWith('https://') && !src.startsWith('data:')) { @@ -336,21 +303,17 @@ export function processHtmlContent(htmlContent: string, textContent?: string): s } // Fix common email client quirks without breaking cid: URLs - sanitizedContent = sanitizedContent + return sanitizedContent // Fix for Outlook WebVML content .replace(/