/** * Centralized Email Content Utilities * * This file contains all core functions for email content processing: * - Content extraction * - HTML sanitization * - Text direction handling * - URL fixing * * Other modules should import from this file rather than implementing their own versions. */ import { sanitizeHtml } from './dom-purify-config'; import { detectTextDirection } from './text-direction'; import { EmailContent } from '@/types/email'; /** * Extract content from various possible email formats * Centralized implementation to reduce duplication across the codebase */ export function extractEmailContent(email: any): { text: string; html: string } { // Default empty values let textContent = ''; let htmlContent = ''; // Early exit if no email if (!email) { console.log('extractEmailContent: No email provided'); return { text: '', html: '' }; } try { // Extract based on common formats if (email.content && typeof email.content === 'object') { // Standard format with content object textContent = email.content.text || ''; htmlContent = email.content.html || ''; // Handle complex email formats where content might be nested if (!textContent && !htmlContent) { // Try to find content in deeper nested structure if (email.content.body) { if (typeof email.content.body === 'string') { // Determine if body is HTML or text if (isHtmlContent(email.content.body)) { htmlContent = email.content.body; } else { textContent = email.content.body; } } else if (typeof email.content.body === 'object' && email.content.body) { // Some email formats nest content inside body htmlContent = email.content.body.html || ''; textContent = email.content.body.text || ''; } } // Check for data property which some email services use if (!textContent && !htmlContent && email.content.data) { if (typeof email.content.data === 'string') { // Check if data looks like HTML if (isHtmlContent(email.content.data)) { htmlContent = email.content.data; } else { textContent = email.content.data; } } } // 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 if (isHtmlContent(email.content)) { htmlContent = email.content; } else { textContent = email.content; } } else { // Check other common properties htmlContent = email.html || ''; textContent = email.text || ''; // If still no content, check for less common properties if (!htmlContent && !textContent) { // Try additional properties that some email clients use htmlContent = email.body?.html || email.bodyHtml || email.htmlBody || ''; textContent = email.body?.text || email.bodyText || email.plainText || ''; } } } catch (error) { console.error('Error extracting email content:', error); } // Ensure we always have at least some text content if (!textContent && htmlContent) { textContent = extractTextFromHtml(htmlContent); } // Log extraction results console.log('Extracted email content:', { hasHtml: !!htmlContent, htmlLength: htmlContent?.length || 0, hasText: !!textContent, textLength: textContent?.length || 0 }); return { text: textContent, html: htmlContent }; } /** * Extract plain text from HTML content */ export function extractTextFromHtml(html: string): string { if (!html) return ''; try { // Use DOM API if available if (typeof window !== 'undefined' && typeof document !== 'undefined') { const tempDiv = document.createElement('div'); tempDiv.innerHTML = html; return tempDiv.textContent || tempDiv.innerText || ''; } else { // Simple regex fallback for non-browser environments return html.replace(/<[^>]*>/g, ' ') .replace(/ /g, ' ') .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&') .replace(/\s+/g, ' ') .trim(); } } catch (e) { console.error('Error extracting text from HTML:', e); // Fallback to basic strip return html.replace(/<[^>]*>/g, ' ').trim(); } } /** * Check if a string is likely HTML content */ export function isHtmlContent(content: string): boolean { if (!content) return false; return content.trim().startsWith('<') && (content.includes('') || content.includes('Error displaying email content
${error instanceof Error ? error.message : 'Unknown error'}