mail page imap connection 13

This commit is contained in:
alma 2025-04-15 21:52:10 +02:00
parent 47f86057b2
commit f717203e65

View File

@ -41,30 +41,35 @@ interface Email {
category: string;
}
// Improve MIME decoding function
// Improved MIME decoding function
const decodeMimeContent = (content: string) => {
try {
// Extract the actual content after headers
const contentMatch = content.match(/charset="utf-8"\s*([\s\S]*?)(?=\s*(?:\[LINK:|$))/);
if (!contentMatch) return content;
let cleanContent = contentMatch[1]
// First, try to extract the main content
let cleanContent = content
// Remove MIME headers and metadata
.replace(/^.*?Content-Type:.*?\n\n/s, '')
.replace(/^This is a multi-part message.*?utf-8"/s, '')
.replace(/---InfomaniakPhpMail.*?Content-Transfer-Encoding:.*?\n/g, '')
// Clean up special characters
.replace(/Content-Type:.*?\n/g, '')
.replace(/Content-Transfer-Encoding:.*?\n/g, '')
// Clean up special characters and formatting
.replace(/=C2=A0/g, ' ')
.replace(/=\n/g, '')
.replace(/=([0-9A-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
// Remove formatting markers
.replace(/\[IMG:.*?\]/g, '')
.replace(/\*([^*]+)\*/g, '$1')
// Clean up links
.replace(/\[ LINK: (.*?) \]/g, '$1')
// Normalize whitespace
.replace(/\[ ?LINK: ([^\]]+) ?\]/g, '$1')
// Clean up whitespace
.replace(/\s+/g, ' ')
.trim();
// Extract just the welcome message and first paragraph if it's the welcome email
if (cleanContent.includes('Welcome to your professional mailbox')) {
const welcomeMatch = cleanContent.match(/Welcome to your professional mailbox!(.+?)(?=\*Getting started\*|$)/s);
if (welcomeMatch) {
return welcomeMatch[0].trim();
}
}
return cleanContent;
} catch (error) {
console.error('Error decoding MIME content:', error);
@ -100,6 +105,9 @@ export default function MailPage() {
const [emails, setEmails] = useState<Email[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [composeSubject, setComposeSubject] = useState('');
const [composeRecipient, setComposeRecipient] = useState('');
const [composeContent, setComposeContent] = useState('');
// Fetch emails from IMAP API
useEffect(() => {
@ -174,15 +182,15 @@ export default function MailPage() {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ emailId })
});
const updatedEmails = emails.map(email =>
email.id === emailId ? { ...email, read: true } : email
);
setEmails(updatedEmails);
setSelectedEmail(emailId);
} catch (error) {
console.error('Error marking email as read:', error);
}
const updatedEmails = emails.map(email =>
email.id === emailId ? { ...email, read: true } : email
);
setEmails(updatedEmails);
setSelectedEmail(emailId);
};
// Toggle starred status
@ -284,6 +292,36 @@ export default function MailPage() {
));
};
// Handle reply
const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => {
const selectedEmailData = getSelectedEmail();
if (!selectedEmailData) return;
setComposeOpen(true);
const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`;
let to = '';
let content = '';
switch (type) {
case 'reply':
to = selectedEmailData.from;
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${selectedEmailData.body.split('\n').join('\n> ')}`;
break;
case 'replyAll':
to = selectedEmailData.from; // You would also need to add CC recipients here
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${selectedEmailData.body.split('\n').join('\n> ')}`;
break;
case 'forward':
content = `\n\n---------- Forwarded message ----------\nFrom: ${selectedEmailData.fromName} <${selectedEmailData.from}>\nDate: ${new Date(selectedEmailData.date).toLocaleString()}\nSubject: ${selectedEmailData.subject}\n\n${selectedEmailData.body}`;
break;
}
// Update compose form state (you'll need to add these state variables)
setComposeSubject(subject);
setComposeRecipient(to);
setComposeContent(content);
};
if (loading) {
return (
<div className="flex h-[calc(100vh-theme(spacing.12))] items-center justify-center bg-gray-100 mt-12">
@ -633,6 +671,7 @@ export default function MailPage() {
variant="ghost"
size="sm"
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={() => handleReply('reply')}
>
<Reply className="h-4 w-4 mr-2" />
Reply
@ -641,6 +680,7 @@ export default function MailPage() {
variant="ghost"
size="sm"
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={() => handleReply('replyAll')}
>
<ReplyAll className="h-4 w-4 mr-2" />
Reply all
@ -649,6 +689,7 @@ export default function MailPage() {
variant="ghost"
size="sm"
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
onClick={() => handleReply('forward')}
>
<Forward className="h-4 w-4 mr-2" />
Forward
@ -777,6 +818,8 @@ export default function MailPage() {
<Input
type="email"
placeholder="email@example.com"
value={composeRecipient}
onChange={(e) => setComposeRecipient(e.target.value)}
className="bg-white border-gray-200 py-1.5"
/>
</div>
@ -825,6 +868,8 @@ export default function MailPage() {
<Input
type="text"
placeholder="Subject"
value={composeSubject}
onChange={(e) => setComposeSubject(e.target.value)}
className="bg-white border-gray-200 py-1.5"
/>
</div>
@ -835,6 +880,8 @@ export default function MailPage() {
<Textarea
className="mt-0.5 h-[calc(100%-1.5rem)] min-h-[200px] bg-white border-gray-200 resize-none"
placeholder="Write your message here..."
value={composeContent}
onChange={(e) => setComposeContent(e.target.value)}
/>
</div>