mail page fix
This commit is contained in:
parent
1f9040bd98
commit
a7cfeb759a
@ -331,15 +331,24 @@ const initialSidebarItems = [
|
|||||||
function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward'): string {
|
function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward'): string {
|
||||||
if (!email.body) return '';
|
if (!email.body) return '';
|
||||||
|
|
||||||
const { headers, body } = splitEmailHeadersAndBody(email.body);
|
try {
|
||||||
const { contentType, encoding, charset } = parseEmailHeaders(headers);
|
// Split email into headers and body
|
||||||
|
const [headersPart, ...bodyParts] = email.body.split('\r\n\r\n');
|
||||||
let content = '';
|
if (!headersPart || bodyParts.length === 0) {
|
||||||
|
throw new Error('Invalid email format: missing headers or body');
|
||||||
if (contentType.includes('multipart/')) {
|
}
|
||||||
const boundary = contentType.match(/boundary="([^"]+)"/)?.[1];
|
|
||||||
|
const body = bodyParts.join('\r\n\r\n');
|
||||||
|
|
||||||
|
// Parse headers using Infomaniak MIME decoder
|
||||||
|
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).filter(part => part.trim());
|
const parts = body.split(`--${boundary}`);
|
||||||
|
|
||||||
// Find HTML part first, fallback to text part
|
// Find HTML part first, fallback to text part
|
||||||
const htmlPart = parts.find(part => part.toLowerCase().includes('content-type: text/html'));
|
const htmlPart = parts.find(part => part.toLowerCase().includes('content-type: text/html'));
|
||||||
@ -347,84 +356,64 @@ function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward'): st
|
|||||||
|
|
||||||
const selectedPart = htmlPart || textPart;
|
const selectedPart = htmlPart || textPart;
|
||||||
if (selectedPart) {
|
if (selectedPart) {
|
||||||
const partHeaders = selectedPart.split('\r\n\r\n')[0];
|
const [partHeaders, ...partBodyParts] = selectedPart.split('\r\n\r\n');
|
||||||
const partBody = selectedPart.split('\r\n\r\n').slice(1).join('\r\n\r\n');
|
const partBody = partBodyParts.join('\r\n\r\n');
|
||||||
const { encoding: partEncoding } = parseEmailHeaders(partHeaders);
|
const partHeaderInfo = parseEmailHeaders(partHeaders);
|
||||||
|
|
||||||
content = partEncoding === 'quoted-printable'
|
content = partHeaderInfo.encoding === 'quoted-printable'
|
||||||
? decodeQuotedPrintable(partBody, charset)
|
? decodeQuotedPrintable(partBody, partHeaderInfo.charset)
|
||||||
: partBody;
|
: partBody;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
content = headerInfo.encoding === 'quoted-printable'
|
||||||
|
? decodeQuotedPrintable(body, headerInfo.charset)
|
||||||
|
: body;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
content = encoding === 'quoted-printable'
|
// Convert plain text to HTML if needed
|
||||||
? decodeQuotedPrintable(body, charset)
|
if (!headerInfo.contentType.includes('text/html')) {
|
||||||
: body;
|
content = content
|
||||||
}
|
.split('\n')
|
||||||
|
.map(line => {
|
||||||
// Convert plain text to HTML if needed, preserving line breaks
|
if (!line.trim()) return '<br>';
|
||||||
if (!contentType.includes('text/html')) {
|
if (line.startsWith('>')) {
|
||||||
content = content
|
return `<p class="text-gray-600">${line}</p>`;
|
||||||
.split('\n')
|
}
|
||||||
.map(line => {
|
return `<p>${line}</p>`;
|
||||||
// Preserve empty lines
|
})
|
||||||
if (!line.trim()) return '<br>';
|
.join('');
|
||||||
// Handle quoted text
|
}
|
||||||
if (line.startsWith('>')) {
|
|
||||||
return `<p class="text-gray-600">${line}</p>`;
|
// Clean HTML content
|
||||||
}
|
content = cleanHtml(content);
|
||||||
return `<p>${line}</p>`;
|
|
||||||
})
|
const date = new Date(email.date).toLocaleString();
|
||||||
.join('');
|
|
||||||
}
|
if (type === 'forward') {
|
||||||
|
return `
|
||||||
// Clean HTML content while preserving formatting
|
<div class="prose max-w-none">
|
||||||
content = content
|
<div class="border-l-4 border-gray-300 pl-4 my-4">
|
||||||
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
|
<p class="text-sm text-gray-600 mb-2"><strong>From:</strong> ${email.from}</p>
|
||||||
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
|
<p class="text-sm text-gray-600 mb-2"><strong>Date:</strong> ${date}</p>
|
||||||
.replace(/<meta[^>]*>/gi, '')
|
<p class="text-sm text-gray-600 mb-2"><strong>Subject:</strong> ${email.subject}</p>
|
||||||
.replace(/<link[^>]*>/gi, '')
|
<p class="text-sm text-gray-600 mb-2"><strong>To:</strong> ${Array.isArray(email.to) ? email.to.join(', ') : email.to}</p>
|
||||||
.replace(/<base[^>]*>/gi, '')
|
<div class="mt-4 prose-sm">${content}</div>
|
||||||
.replace(/<title[^>]*>[\s\S]*?<\/title>/gi, '')
|
</div>
|
||||||
.replace(/<head[^>]*>[\s\S]*?<\/head>/gi, '')
|
|
||||||
.replace(/<body[^>]*>/gi, '')
|
|
||||||
.replace(/<\/body>/gi, '')
|
|
||||||
.replace(/<html[^>]*>/gi, '')
|
|
||||||
.replace(/<\/html>/gi, '');
|
|
||||||
|
|
||||||
// Sanitize HTML content while preserving formatting
|
|
||||||
content = DOMPurify.sanitize(content, {
|
|
||||||
ALLOWED_TAGS: [
|
|
||||||
'p', 'br', 'div', 'span', 'b', 'i', 'u', 'strong', 'em',
|
|
||||||
'blockquote', 'ul', 'ol', 'li', 'a', 'h1', 'h2', 'h3', 'h4',
|
|
||||||
'table', 'thead', 'tbody', 'tr', 'td', 'th', 'pre', 'code'
|
|
||||||
],
|
|
||||||
ALLOWED_ATTR: ['href', 'style', 'class', 'target'],
|
|
||||||
});
|
|
||||||
|
|
||||||
const date = new Date(email.date).toLocaleString();
|
|
||||||
|
|
||||||
if (type === 'forward') {
|
|
||||||
return `
|
|
||||||
<div class="prose max-w-none">
|
|
||||||
<div class="border-l-4 border-gray-300 pl-4 my-4">
|
|
||||||
<p class="text-sm text-gray-600"><strong>From:</strong> ${email.from}</p>
|
|
||||||
<p class="text-sm text-gray-600"><strong>Date:</strong> ${date}</p>
|
|
||||||
<p class="text-sm text-gray-600"><strong>Subject:</strong> ${email.subject}</p>
|
|
||||||
<p class="text-sm text-gray-600"><strong>To:</strong> ${Array.isArray(email.to) ? email.to.join(', ') : email.to}</p>
|
|
||||||
<div class="mt-4 prose-sm">${content}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
`;
|
||||||
`;
|
} else {
|
||||||
} else {
|
return `
|
||||||
return `
|
<div class="prose max-w-none">
|
||||||
<div class="prose max-w-none">
|
<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">On ${date}, ${email.from} wrote:</p>
|
||||||
<p class="text-sm text-gray-600">On ${date}, ${email.from} wrote:</p>
|
<div class="mt-4 prose-sm">${content}</div>
|
||||||
<div class="mt-4 prose-sm">${content}</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
`;
|
||||||
`;
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing email body:', error);
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user