diff --git a/components/email/EmailContentDisplay.tsx b/components/email/EmailContentDisplay.tsx index 46e915b8..594dcbab 100644 --- a/components/email/EmailContentDisplay.tsx +++ b/components/email/EmailContentDisplay.tsx @@ -5,7 +5,7 @@ import { renderEmailContent } from '@/lib/utils/email-utils'; import { EmailContent } from '@/types/email'; interface EmailContentDisplayProps { - content: EmailContent; + content: EmailContent | null | undefined; className?: string; showQuotedText?: boolean; type?: 'html' | 'text' | 'auto'; @@ -33,13 +33,18 @@ const EmailContentDisplay: React.FC = ({ direction: 'ltr' } as EmailContent; } - return content; + + // Ensure all required fields are present + return { + text: content.text || '', + html: content.html, + isHtml: !!content.isHtml, + direction: content.direction || 'ltr' + } as EmailContent; }, [content]); // Render the content with proper formatting const htmlContent = useMemo(() => { - if (!safeContent) return ''; - try { // Override content type if specified let contentToRender: EmailContent = { ...safeContent }; diff --git a/hooks/use-email-fetch.ts b/hooks/use-email-fetch.ts index 684be855..4bf5d72f 100644 --- a/hooks/use-email-fetch.ts +++ b/hooks/use-email-fetch.ts @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback, useRef } from 'react'; import { useToast } from './use-toast'; import { EmailMessage, EmailContent } from '@/types/email'; +import { sanitizeHtml } from '@/lib/utils/email-utils'; interface EmailFetchState { email: EmailMessage | null; @@ -72,16 +73,63 @@ export function useEmailFetch({ onEmailLoaded, onError }: UseEmailFetchProps = { const data = await response.json(); + // Process content based on what type it is + let processedContent: EmailContent; + + if (data.content) { + if (typeof data.content === 'object') { + // If data.content is already an object, normalize it + processedContent = { + text: data.content.text || '', + html: data.content.html || undefined, + isHtml: !!data.content.html, + direction: data.content.direction || 'ltr' + }; + } else if (typeof data.content === 'string') { + // If data.content is a string, determine if it's HTML + const isHtml = data.content.trim().startsWith('<') && + (data.content.includes('')); + + processedContent = { + text: isHtml ? data.content.replace(/<[^>]*>/g, '') : data.content, + html: isHtml ? sanitizeHtml(data.content) : undefined, + isHtml: isHtml, + direction: 'ltr' + }; + } else { + // Fallback for any other case + processedContent = { + text: 'Unsupported content format', + html: undefined, + isHtml: false, + direction: 'ltr' + }; + } + } else if (data.html || data.text) { + // Handle separate html/text properties + processedContent = { + text: data.text || (data.html ? data.html.replace(/<[^>]*>/g, '') : ''), + html: data.html ? sanitizeHtml(data.html) : undefined, + isHtml: !!data.html, + direction: 'ltr' + }; + } else { + // No content at all + processedContent = { + text: 'No content available', + html: undefined, + isHtml: false, + direction: 'ltr' + }; + } + // Create properly formatted email with all required fields const transformedEmail: EmailMessage = { ...data, - // Ensure content is properly formatted - content: { - text: data.content?.text || '', - html: data.content?.html || undefined, - isHtml: data.content?.html ? true : false, - direction: data.content?.direction || 'ltr' - } + content: processedContent }; setState({ email: transformedEmail, loading: false, error: null }); diff --git a/lib/utils/email-utils.ts b/lib/utils/email-utils.ts index 70a3a18d..89a2763b 100644 --- a/lib/utils/email-utils.ts +++ b/lib/utils/email-utils.ts @@ -145,7 +145,7 @@ export function sanitizeHtml(html: string): string { /** * Format plain text for HTML display with proper line breaks */ -export function formatPlainTextToHtml(text: string): string { +export function formatPlainTextToHtml(text: string | null | undefined): string { if (!text) return ''; // Escape HTML characters to prevent XSS @@ -204,14 +204,22 @@ export function renderEmailContent(content: EmailContent): string { } try { + // Ensure content has all required fields with defaults + const safeContent = { + text: content.text || '', + html: content.html, + isHtml: !!content.isHtml, + direction: content.direction || 'ltr' + }; + // Determine if we're rendering HTML or plain text - if (content.isHtml && content.html) { + if (safeContent.isHtml && safeContent.html) { // For HTML content, wrap it with proper styling - return ``; + return ``; } else { // For plain text, format it as HTML and wrap with monospace styling - const formattedText = formatPlainTextToHtml(content.text); - return ``; + const formattedText = formatPlainTextToHtml(safeContent.text); + return ``; } } catch (error) { console.error('Error rendering email content:', error);