mail page fix design

This commit is contained in:
alma 2025-04-21 19:59:00 +02:00
parent 127765069f
commit 525a7db670

View File

@ -328,93 +328,98 @@ const initialSidebarItems = [
} }
]; ];
function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward'): string { function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward' = 'reply') {
if (!email.body) return ''; if (!email.body) return '';
try { let content = '';
// Split email into headers and body let headers = '';
const [headersPart, ...bodyParts] = email.body.split('\r\n\r\n'); let body = '';
if (!headersPart || bodyParts.length === 0) {
throw new Error('Invalid email format: missing headers or body'); // Split headers and body
const parts = email.body.split('\r\n\r\n');
if (parts.length > 1) {
headers = parts[0];
body = parts.slice(1).join('\r\n\r\n');
} else {
body = email.body;
} }
const body = bodyParts.join('\r\n\r\n'); // Handle multipart emails
if (headers.includes('multipart/alternative')) {
// Parse headers using Infomaniak MIME decoder const boundary = headers.match(/boundary="([^"]+)"/)?.[1];
const headerInfo = parseEmailHeaders(headersPart);
const boundary = extractBoundary(headersPart);
let content = '';
// If it's a multipart email
if (boundary) { if (boundary) {
const parts = body.split(`--${boundary}`); const parts = body.split(`--${boundary}`);
for (const part of parts) {
// Find HTML part first, fallback to text part if (part.includes('text/html')) {
const htmlPart = parts.find(part => part.toLowerCase().includes('content-type: text/html')); content = part.split('\r\n\r\n')[1] || '';
const textPart = parts.find(part => part.toLowerCase().includes('content-type: text/plain')); break;
} else if (part.includes('text/plain')) {
const selectedPart = htmlPart || textPart; content = part.split('\r\n\r\n')[1] || '';
if (selectedPart) {
const [partHeaders, ...partBodyParts] = selectedPart.split('\r\n\r\n');
const partBody = partBodyParts.join('\r\n\r\n');
const partHeaderInfo = parseEmailHeaders(partHeaders);
content = partHeaderInfo.encoding === 'quoted-printable'
? decodeQuotedPrintable(partBody, partHeaderInfo.charset)
: partBody;
} }
} else { }
content = headerInfo.encoding === 'quoted-printable' }
? decodeQuotedPrintable(body, headerInfo.charset) } else if (headers.includes('text/html')) {
: body; content = body;
} else if (headers.includes('text/plain')) {
// Convert plain text to HTML while preserving formatting
content = body
.replace(/\r\n/g, '<br>')
.replace(/\n/g, '<br>')
.replace(/\r/g, '<br>');
} }
// Convert plain text to HTML if needed // Clean and sanitize HTML content
if (!headerInfo.contentType.includes('text/html')) {
content = content content = content
.split('\n') .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
.map(line => { .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
if (!line.trim()) return '<br>'; .replace(/<meta[^>]*>/gi, '')
if (line.startsWith('>')) { .replace(/<link[^>]*>/gi, '')
return `<p class="text-gray-600" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;">${line}</p>`; .replace(/<base[^>]*>/gi, '')
} .replace(/<title[^>]*>[\s\S]*?<\/title>/gi, '')
return `<p dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;">${line}</p>`; .replace(/<head[^>]*>[\s\S]*?<\/head>/gi, '')
}) .replace(/<body[^>]*>/gi, '')
.join(''); .replace(/<\/body>/gi, '')
} .replace(/<html[^>]*>/gi, '')
.replace(/<\/html>/gi, '')
.replace(/<!DOCTYPE[^>]*>/gi, '')
.replace(/<!--[\s\S]*?-->/gi, '');
// Clean HTML content // Clean up any remaining HTML entities
content = cleanHtml(content); content = content
.replace(/&nbsp;/g, ' ')
const date = new Date(email.date).toLocaleString(); .replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'");
// Format the reply/forward content
let formattedContent = '';
if (type === 'forward') { if (type === 'forward') {
return ` formattedContent = `
<div class="prose max-w-none" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"> <div class="prose max-w-none" dir="ltr">
<div class="border-l-4 border-gray-300 pl-4 my-4"> <div class="border-l-4 border-gray-300 pl-4 my-4">
<p class="text-sm text-gray-600 mb-2" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"><strong>From:</strong> ${email.from}</p> <p class="text-sm text-gray-600 mb-2">Forwarded message from ${email.from}</p>
<p class="text-sm text-gray-600 mb-2" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"><strong>Date:</strong> ${date}</p> <p class="text-sm text-gray-600 mb-2">Date: ${new Date(email.date).toLocaleString()}</p>
<p class="text-sm text-gray-600 mb-2" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"><strong>Subject:</strong> ${email.subject}</p> <p class="text-sm text-gray-600 mb-2">Subject: ${email.subject}</p>
<p class="text-sm text-gray-600 mb-2" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"><strong>To:</strong> ${Array.isArray(email.to) ? email.to.join(', ') : email.to}</p> <p class="text-sm text-gray-600 mb-2">To: ${email.to}</p>
<div class="mt-4 prose-sm" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;">${content}</div> ${email.cc ? `<p class="text-sm text-gray-600 mb-2">Cc: ${email.cc}</p>` : ''}
<div class="mt-4 prose-sm">${content}</div>
</div> </div>
</div> </div>
`; `;
} else { } else {
return ` formattedContent = `
<div class="prose max-w-none" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;"> <div class="prose max-w-none" dir="ltr">
<div class="border-l-4 border-gray-300 pl-4 my-4"> <div class="border-l-4 border-gray-300 pl-4 my-4">
<p class="text-sm text-gray-600 mb-2" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;">On ${date}, ${email.from} wrote:</p> <p class="text-sm text-gray-600 mb-2">On ${new Date(email.date).toLocaleString()}, ${email.from} wrote:</p>
<div class="mt-4 prose-sm" dir="ltr" style="unicode-bidi: bidi-override; direction: ltr;">${content}</div> <div class="mt-4 prose-sm">${content}</div>
</div> </div>
</div> </div>
`; `;
} }
} catch (error) {
console.error('Error processing email body:', error); return formattedContent;
return '';
}
} }
export default function CourrierPage() { export default function CourrierPage() {