diff --git a/app/api/parse-email/route.ts b/app/api/parse-email/route.ts index 2e8735b6..7af4e6a1 100644 --- a/app/api/parse-email/route.ts +++ b/app/api/parse-email/route.ts @@ -1,7 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; -import { simpleParser } from 'mailparser'; -import * as DOMPurify from 'isomorphic-dompurify'; -import { cleanHtml as cleanHtmlCentralized } from '@/lib/mail-parser-wrapper'; +import { parseEmail } from '@/lib/server/email-parser'; +import { sanitizeHtml } from '@/lib/utils/email-formatter'; interface EmailAddress { name?: string; @@ -45,68 +44,29 @@ function getEmailAddresses(addresses: any): EmailAddress[] { return []; } -/** - * @deprecated This function is deprecated and will be removed in future versions. - * Use the cleanHtml function from '@/lib/mail-parser-wrapper' instead. - * Maintained for backward compatibility only. - */ -function processHtml(html: string): string { - if (!html) return ''; - - // Delegate to the centralized implementation - return cleanHtmlCentralized(html, { - preserveStyles: true, - scopeStyles: true, - addWrapper: true - }); -} - -export async function POST(req: NextRequest) { +export async function POST(request: NextRequest) { try { - const { email } = await req.json(); + const body = await request.json(); - if (!email || typeof email !== 'string') { + if (!body.email) { return NextResponse.json( - { error: 'Invalid email content' }, + { error: 'Missing email content' }, { status: 400 } ); } + + const parsedEmail = await parseEmail(body.email); - const parsed = await simpleParser(email); + // Process HTML content if available + if (parsedEmail.html) { + parsedEmail.html = sanitizeHtml(parsedEmail.html); + } - // Process the HTML content to make it safe and displayable - const html = parsed.html - ? processHtml(parsed.html.toString()) - : undefined; - - const text = parsed.text - ? parsed.text.toString() - : undefined; - - // Extract attachments info if available - const attachments = parsed.attachments?.map(attachment => ({ - filename: attachment.filename, - contentType: attachment.contentType, - contentDisposition: attachment.contentDisposition, - size: attachment.size - })) || []; - - // Return all parsed email details - return NextResponse.json({ - subject: parsed.subject, - from: getEmailAddresses(parsed.from), - to: getEmailAddresses(parsed.to), - cc: getEmailAddresses(parsed.cc), - bcc: getEmailAddresses(parsed.bcc), - date: parsed.date, - html, - text, - attachments - }); + return NextResponse.json(parsedEmail); } catch (error) { console.error('Error parsing email:', error); return NextResponse.json( - { error: 'Failed to parse email content' }, + { error: 'Failed to parse email', details: error instanceof Error ? error.message : String(error) }, { status: 500 } ); } diff --git a/lib/email-parser.ts b/lib/email-parser.ts index 7bbfb69c..0227b1a0 100644 --- a/lib/email-parser.ts +++ b/lib/email-parser.ts @@ -1,3 +1,10 @@ +/** + * @deprecated This entire file is deprecated and will be removed in future versions. + * Use the parseEmail function from lib/server/email-parser.ts and + * sanitizeHtml from lib/utils/email-formatter.ts instead. + * This file is maintained only for backward compatibility. + */ + interface EmailHeaders { from: string; subject: string; @@ -5,7 +12,12 @@ interface EmailHeaders { to?: string; } +/** + * @deprecated Use parseEmail from lib/server/email-parser.ts instead. + */ export function parseEmailHeaders(headerContent: string): EmailHeaders { + console.warn('parseEmailHeaders is deprecated. Use parseEmail from lib/server/email-parser.ts instead.'); + const headers: { [key: string]: string } = {}; let currentHeader = ''; let currentValue = ''; @@ -48,7 +60,12 @@ export function parseEmailHeaders(headerContent: string): EmailHeaders { }; } +/** + * @deprecated Use sanitizeHtml from lib/utils/email-formatter.ts instead. + */ export function decodeEmailBody(content: string, contentType: string): string { + console.warn('decodeEmailBody is deprecated. Use sanitizeHtml from lib/utils/email-formatter.ts instead.'); + try { // Remove email client-specific markers content = content.replace(/\r\n/g, '\n') @@ -68,7 +85,12 @@ export function decodeEmailBody(content: string, contentType: string): string { } } +/** + * @deprecated Use sanitizeHtml from lib/utils/email-formatter.ts instead. + */ function extractTextFromHtml(html: string): string { + console.warn('extractTextFromHtml is deprecated. Use sanitizeHtml from lib/utils/email-formatter.ts instead.'); + // Remove scripts and style tags html = html.replace(/]*>[\s\S]*?<\/script>/gi, '') .replace(/]*>[\s\S]*?<\/style>/gi, ''); diff --git a/lib/mail-parser-wrapper.ts b/lib/mail-parser-wrapper.ts index b54058a1..356fe111 100644 --- a/lib/mail-parser-wrapper.ts +++ b/lib/mail-parser-wrapper.ts @@ -1,6 +1,7 @@ 'use client'; import DOMPurify from 'dompurify'; +import { sanitizeHtml } from '@/lib/utils/email-formatter'; export interface ParsedEmail { subject: string | null; @@ -99,119 +100,4 @@ export async function decodeEmail(emailContent: string): Promise { headers: {} }; } -} - -/** - * Cleans HTML content by removing potentially harmful elements while preserving styling. - * This is the centralized HTML sanitization function to be used across the application. - * - * Key features: - * - Safely removes scripts, iframes, and other potentially harmful elements - * - Optionally preserves and scopes CSS styles to prevent them from affecting the rest of the page - * - Fixes self-closing tags that might break in React or contentEditable contexts - * - Can add a wrapper div with isolation for additional safety - * - * @param html HTML content to sanitize - * @param options Configuration options: - * - preserveStyles: Whether to keep - ${processedHtml} - - `; - } else { - return `${processedHtml}`; - } - } - - // Just wrap the content if needed - if (defaultOptions.addWrapper) { - return ``; - } - - return processedHtml; - } catch (error) { - console.error('Error cleaning HTML:', error); - // Return something safe in case of error - return `
Error processing HTML content
`; - } } \ No newline at end of file diff --git a/lib/server/email-parser.ts b/lib/server/email-parser.ts index 6975db14..c79a50f8 100644 --- a/lib/server/email-parser.ts +++ b/lib/server/email-parser.ts @@ -1,22 +1,20 @@ +import { sanitizeHtml } from '@/lib/utils/email-formatter'; import { simpleParser } from 'mailparser'; -import { cleanHtml as cleanHtmlCentralized } from '@/lib/mail-parser-wrapper'; -/** - * @deprecated This function is deprecated and will be removed in future versions. - * Use the centralized cleanHtml function from '@/lib/mail-parser-wrapper.ts instead. - * This is maintained only for backward compatibility. - */ -export function cleanHtml(html: string): string { - console.warn('The cleanHtml function in lib/server/email-parser.ts is deprecated. Use the one in lib/mail-parser-wrapper.ts'); - return cleanHtmlCentralized(html, { preserveStyles: true, scopeStyles: false }); -} - -function getAddressText(address: any): string | null { - if (!address) return null; - if (Array.isArray(address)) { - return address.map(addr => addr.value?.[0]?.address || '').filter(Boolean).join(', '); +function getAddressText(addresses: any): string | null { + if (!addresses) return null; + + try { + if (Array.isArray(addresses)) { + return addresses.map(a => a.address || '').join(', '); + } else if (typeof addresses === 'object') { + return addresses.address || null; + } + return null; + } catch (error) { + console.error('Error formatting addresses:', error); + return null; } - return address.value?.[0]?.address || null; } export async function parseEmail(emailContent: string) { @@ -30,10 +28,7 @@ export async function parseEmail(emailContent: string) { cc: getAddressText(parsed.cc), bcc: getAddressText(parsed.bcc), date: parsed.date || null, - html: parsed.html ? cleanHtmlCentralized(parsed.html as string, { - preserveStyles: true, - scopeStyles: false - }) : null, + html: parsed.html ? sanitizeHtml(parsed.html as string) : null, text: parsed.text || null, attachments: parsed.attachments || [], headers: Object.fromEntries(parsed.headers)