From eb4e128da1cad09e30239a2ab6d18f966f0062ff Mon Sep 17 00:00:00 2001 From: alma Date: Mon, 21 Apr 2025 12:36:19 +0200 Subject: [PATCH] mail page rest --- app/courrier/page.tsx | 91 ++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 280d78a8..cfcff3d7 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -380,35 +380,80 @@ function cleanHtml(html: string): string { function decodeMimeContent(content: string): string { if (!content) return ''; - // Check if this is an Infomaniak multipart message - if (content.includes('Content-Type: multipart/')) { - const boundary = content.match(/boundary="([^"]+)"/)?.[1]; - if (boundary) { - const parts = content.split('--' + boundary); - let htmlContent = ''; - let textContent = ''; + try { + // First, try to extract the content type and encoding + const contentTypeMatch = content.match(/Content-Type:\s*([^;\r\n]+)/i); + const encodingMatch = content.match(/Content-Transfer-Encoding:\s*([^\r\n]+)/i); + const charsetMatch = content.match(/charset="?([^"\r\n;]+)"?/i); + + const contentType = contentTypeMatch ? contentTypeMatch[1].toLowerCase() : 'text/plain'; + const encoding = encodingMatch ? encodingMatch[1].toLowerCase() : '7bit'; + const charset = charsetMatch ? charsetMatch[1].toLowerCase() : 'utf-8'; - parts.forEach(part => { - if (part.includes('Content-Type: text/html')) { - const match = part.match(/\r?\n\r?\n([\s\S]+?)(?=\r?\n--)/); - if (match) { - htmlContent = cleanHtml(match[1]); + // Handle multipart messages + if (contentType.includes('multipart/')) { + const boundaryMatch = content.match(/boundary="?([^"\r\n;]+)"?/i); + if (boundaryMatch) { + const boundary = boundaryMatch[1]; + const parts = content.split('--' + boundary); + + let htmlContent = ''; + let textContent = ''; + + for (const part of parts) { + if (!part.trim()) continue; + + const partContentType = part.match(/Content-Type:\s*([^;\r\n]+)/i)?.[1]?.toLowerCase() || ''; + const partEncoding = part.match(/Content-Transfer-Encoding:\s*([^\r\n]+)/i)?.[1]?.toLowerCase() || '7bit'; + const partCharset = part.match(/charset="?([^"\r\n;]+)"?/i)?.[1]?.toLowerCase() || 'utf-8'; + + // Extract the actual content (after headers) + const contentMatch = part.match(/\r?\n\r?\n([\s\S]+?)(?=\r?\n--)/); + if (!contentMatch) continue; + + let partContent = contentMatch[1]; + + // Decode based on encoding + if (partEncoding === 'quoted-printable') { + partContent = decodeQuotedPrintable(partContent, partCharset); + } else if (partEncoding === 'base64') { + partContent = decodeBase64(partContent, partCharset); } - } else if (part.includes('Content-Type: text/plain')) { - const match = part.match(/\r?\n\r?\n([\s\S]+?)(?=\r?\n--)/); - if (match) { - textContent = cleanHtml(match[1]); + + if (partContentType.includes('text/html')) { + htmlContent = partContent; + } else if (partContentType.includes('text/plain')) { + textContent = partContent; } } - }); - - // Prefer HTML content if available - return htmlContent || textContent; + + // Prefer HTML content if available + return htmlContent || textContent || content; + } } - } - // If not multipart or no boundary found, clean the content directly - return cleanHtml(content); + // Handle single part messages + let decodedContent = content; + + // Find the actual content (after headers) + const contentMatch = content.match(/\r?\n\r?\n([\s\S]+)/); + if (contentMatch) { + decodedContent = contentMatch[1]; + } + + // Decode based on encoding + if (encoding === 'quoted-printable') { + decodedContent = decodeQuotedPrintable(decodedContent, charset); + } else if (encoding === 'base64') { + decodedContent = decodeBase64(decodedContent, charset); + } + + // Clean up the content + return cleanHtml(decodedContent); + } catch (e) { + console.error('Error decoding MIME content:', e); + return content; + } } // Add this helper function