diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx
index cb098b5d..290d5d90 100644
--- a/app/courrier/page.tsx
+++ b/app/courrier/page.tsx
@@ -328,61 +328,93 @@ const initialSidebarItems = [
}
];
-function getReplyBody(email: any, type: 'reply' | 'reply-all' | 'forward' = 'reply'): string {
- let content = '';
+function getReplyBody(email: Email, type: 'reply' | 'reply-all' | 'forward'): string {
+ if (!email.body) return '';
- if (email.body) {
- // Handle multipart emails
- if (email.body.includes('Content-Type: multipart/alternative')) {
- const parts = email.body.split('--');
- for (const part of parts) {
- if (part.includes('Content-Type: text/html')) {
- content = part.split('\n\n')[1] || '';
- break;
- }
- }
- } else {
- content = email.body;
+ try {
+ // Split email into headers and body
+ const [headersPart, ...bodyParts] = email.body.split('\r\n\r\n');
+ if (!headersPart || bodyParts.length === 0) {
+ throw new Error('Invalid email format: missing headers or body');
}
- // Clean and structure the content
- content = content
- .replace(/
/gi, '\n')
- .replace(/
/gi, '\n')
- .replace(/<\/div>/gi, '\n')
- .trim();
-
- // Convert plain text to HTML while preserving formatting
- content = content
- .split('\n')
- .map(line => `
${line}
`)
- .join('');
-
- // Add proper quoting structure
- const quotedContent = `
-
- ${content}
-
- `;
-
- // Add metadata based on type
- const metadata = `
-
- ${type === 'forward' ? 'Forwarded message' : 'Original message'}
- From: ${email.from}
- Date: ${new Date(email.date).toLocaleString()}
- Subject: ${email.subject}
-
- `;
-
- return type === 'forward'
- ? `
${metadata}${quotedContent}
`
- : `
${metadata}${quotedContent}
`;
+ 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) {
+ const parts = body.split(`--${boundary}`);
+
+ // Find HTML part first, fallback to text part
+ const htmlPart = parts.find(part => part.toLowerCase().includes('content-type: text/html'));
+ const textPart = parts.find(part => part.toLowerCase().includes('content-type: text/plain'));
+
+ const selectedPart = htmlPart || textPart;
+ 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)
+ : body;
+ }
+
+ // Convert plain text to HTML if needed
+ if (!headerInfo.contentType.includes('text/html')) {
+ content = content
+ .split('\n')
+ .map(line => {
+ if (!line.trim()) return '
';
+ if (line.startsWith('>')) {
+ return `
${line}
`;
+ }
+ return `
${line}
`;
+ })
+ .join('');
+ }
+
+ // Clean HTML content
+ content = cleanHtml(content);
+
+ const date = new Date(email.date).toLocaleString();
+
+ if (type === 'forward') {
+ return `
+
+
+
From: ${email.from}
+
Date: ${date}
+
Subject: ${email.subject}
+
To: ${Array.isArray(email.to) ? email.to.join(', ') : email.to}
+
${content}
+
+
+ `;
+ } else {
+ return `
+
+
+
On ${date}, ${email.from} wrote:
+
${content}
+
+
+ `;
+ }
+ } catch (error) {
+ console.error('Error processing email body:', error);
+ return '';
}
-
- return '';
}
export default function CourrierPage() {
@@ -1492,92 +1524,92 @@ export default function CourrierPage() {
- {/* Sidebar */}
-
- {/* Courrier Title */}
-
-
- {/* Compose button and refresh button */}
-
-
-
-
-
- {/* Accounts Section */}
-
-
-
- {accountsDropdownOpen && (
-
- {accounts.map(account => (
-
-
-
- ))}
-
- )}
-
-
- {/* Navigation */}
- {renderSidebarNav()}
-
-
- {/* Main content area */}
-
- {/* Email list panel */}
- {renderEmailListWrapper()}
+ {/* Sidebar */}
+
+ {/* Courrier Title */}
+
+
+ {/* Compose button and refresh button */}
+
+
+
+
+
+ {/* Accounts Section */}
+
+
+
+ {accountsDropdownOpen && (
+
+ {accounts.map(account => (
+
+
+
+ ))}
+
+ )}
+
+
+ {/* Navigation */}
+ {renderSidebarNav()}
+
+ {/* Main content area */}
+
+ {/* Email list panel */}
+ {renderEmailListWrapper()}
+
+
+
{/* Compose Email Modal */}
diff --git a/components/ComposeEmail.tsx b/components/ComposeEmail.tsx
index 0be0c10c..02c457eb 100644
--- a/components/ComposeEmail.tsx
+++ b/components/ComposeEmail.tsx
@@ -1,18 +1,12 @@
'use client';
-import { useRef, useEffect, useState } from 'react';
+import { useRef, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Paperclip, X } from 'lucide-react';
import { Textarea } from '@/components/ui/textarea';
-// Direction detection utility
-function detectDirection(text: string): 'rtl' | 'ltr' {
- const rtlChars = /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]/;
- return rtlChars.test(text) ? 'rtl' : 'ltr';
-}
-
interface ComposeEmailProps {
showCompose: boolean;
setShowCompose: (show: boolean) => void;
@@ -56,22 +50,17 @@ export default function ComposeEmail({
setAttachments,
handleSend
}: ComposeEmailProps) {
- const editorRef = useRef
(null);
- const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr');
+ const composeBodyRef = useRef(null);
useEffect(() => {
- if (editorRef.current) {
- editorRef.current.innerHTML = composeBody;
- const plainText = editorRef.current.textContent || '';
- setDirection(detectDirection(plainText));
+ if (composeBodyRef.current) {
+ composeBodyRef.current.innerHTML = composeBody;
}
}, [composeBody]);
- const handleInput = () => {
- if (editorRef.current) {
- const plainText = editorRef.current.textContent || '';
- setDirection(detectDirection(plainText));
- setComposeBody(editorRef.current.innerHTML);
+ const handleInput = (e: React.FormEvent) => {
+ if (composeBodyRef.current) {
+ setComposeBody(composeBodyRef.current.innerHTML);
}
};
@@ -223,23 +212,14 @@ export default function ComposeEmail({
{/* Message Body */}
-