diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 27335ee0..f05d85d7 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -344,54 +344,60 @@ function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward' = 'r body = email.body; } + // Parse headers + const headerInfo = parseEmailHeaders(headers); + const boundary = extractBoundary(headers); + // Handle multipart emails - if (headers.includes('multipart/alternative')) { - const boundary = headers.match(/boundary="([^"]+)"/)?.[1]; - if (boundary) { - const parts = body.split(`--${boundary}`); - for (const part of parts) { - if (part.includes('text/html')) { - content = part.split('\r\n\r\n')[1] || ''; - break; - } else if (part.includes('text/plain')) { - content = part.split('\r\n\r\n')[1] || ''; + if (boundary) { + const parts = body.split(`--${boundary}`); + for (const part of parts) { + if (!part.trim()) continue; + + const [partHeaders, ...partBodyParts] = part.split('\r\n\r\n'); + if (!partHeaders || partBodyParts.length === 0) continue; + + const partBody = partBodyParts.join('\r\n\r\n'); + const partHeaderInfo = parseEmailHeaders(partHeaders); + + try { + let decodedContent = ''; + if (partHeaderInfo.encoding === 'base64') { + decodedContent = decodeBase64(partBody, partHeaderInfo.charset); + } else if (partHeaderInfo.encoding === 'quoted-printable') { + decodedContent = decodeQuotedPrintable(partBody, partHeaderInfo.charset); + } else { + decodedContent = convertCharset(partBody, partHeaderInfo.charset); } + + if (partHeaderInfo.contentType.includes('text/html')) { + content = decodedContent; + break; + } else if (partHeaderInfo.contentType.includes('text/plain') && !content) { + content = decodedContent; + } + } catch (error) { + console.error('Error decoding email part:', error); } } - } else if (headers.includes('text/html')) { - content = body; - } else if (headers.includes('text/plain')) { - // Convert plain text to HTML while preserving formatting - content = body - .replace(/\r\n/g, '
') - .replace(/\n/g, '
') - .replace(/\r/g, '
'); + } else { + // Handle simple email + try { + if (headerInfo.encoding === 'base64') { + content = decodeBase64(body, headerInfo.charset); + } else if (headerInfo.encoding === 'quoted-printable') { + content = decodeQuotedPrintable(body, headerInfo.charset); + } else { + content = convertCharset(body, headerInfo.charset); + } + } catch (error) { + console.error('Error decoding email body:', error); + content = body; + } } // Clean and sanitize HTML content - content = content - .replace(/]*>[\s\S]*?<\/style>/gi, '') - .replace(/]*>[\s\S]*?<\/script>/gi, '') - .replace(/]*>/gi, '') - .replace(/]*>/gi, '') - .replace(/]*>/gi, '') - .replace(/]*>[\s\S]*?<\/title>/gi, '') - .replace(/]*>[\s\S]*?<\/head>/gi, '') - .replace(/]*>/gi, '') - .replace(/<\/body>/gi, '') - .replace(/]*>/gi, '') - .replace(/<\/html>/gi, '') - .replace(/]*>/gi, '') - .replace(//gi, ''); - - // Clean up any remaining HTML entities - content = content - .replace(/ /g, ' ') - .replace(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, "'"); + content = cleanHtml(content); // Format the reply/forward content let formattedContent = '';