mail page imap connection 13
This commit is contained in:
parent
47f86057b2
commit
f717203e65
@ -41,30 +41,35 @@ interface Email {
|
|||||||
category: string;
|
category: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Improve MIME decoding function
|
// Improved MIME decoding function
|
||||||
const decodeMimeContent = (content: string) => {
|
const decodeMimeContent = (content: string) => {
|
||||||
try {
|
try {
|
||||||
// Extract the actual content after headers
|
// First, try to extract the main content
|
||||||
const contentMatch = content.match(/charset="utf-8"\s*([\s\S]*?)(?=\s*(?:\[LINK:|$))/);
|
let cleanContent = content
|
||||||
if (!contentMatch) return content;
|
|
||||||
|
|
||||||
let cleanContent = contentMatch[1]
|
|
||||||
// Remove MIME headers and metadata
|
// 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, '')
|
.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(/=C2=A0/g, ' ')
|
||||||
.replace(/=\n/g, '')
|
.replace(/=\n/g, '')
|
||||||
.replace(/=([0-9A-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
.replace(/=([0-9A-F]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
|
||||||
// Remove formatting markers
|
|
||||||
.replace(/\[IMG:.*?\]/g, '')
|
.replace(/\[IMG:.*?\]/g, '')
|
||||||
.replace(/\*([^*]+)\*/g, '$1')
|
.replace(/\*([^*]+)\*/g, '$1')
|
||||||
// Clean up links
|
.replace(/\[ ?LINK: ([^\]]+) ?\]/g, '$1')
|
||||||
.replace(/\[ LINK: (.*?) \]/g, '$1')
|
// Clean up whitespace
|
||||||
// Normalize whitespace
|
|
||||||
.replace(/\s+/g, ' ')
|
.replace(/\s+/g, ' ')
|
||||||
.trim();
|
.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;
|
return cleanContent;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error decoding MIME content:', error);
|
console.error('Error decoding MIME content:', error);
|
||||||
@ -100,6 +105,9 @@ export default function MailPage() {
|
|||||||
const [emails, setEmails] = useState<Email[]>([]);
|
const [emails, setEmails] = useState<Email[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [composeSubject, setComposeSubject] = useState('');
|
||||||
|
const [composeRecipient, setComposeRecipient] = useState('');
|
||||||
|
const [composeContent, setComposeContent] = useState('');
|
||||||
|
|
||||||
// Fetch emails from IMAP API
|
// Fetch emails from IMAP API
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -174,15 +182,15 @@ export default function MailPage() {
|
|||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ emailId })
|
body: JSON.stringify({ emailId })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const updatedEmails = emails.map(email =>
|
||||||
|
email.id === emailId ? { ...email, read: true } : email
|
||||||
|
);
|
||||||
|
setEmails(updatedEmails);
|
||||||
|
setSelectedEmail(emailId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error marking email as read:', 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
|
// 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) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[calc(100vh-theme(spacing.12))] items-center justify-center bg-gray-100 mt-12">
|
<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"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
onClick={() => handleReply('reply')}
|
||||||
>
|
>
|
||||||
<Reply className="h-4 w-4 mr-2" />
|
<Reply className="h-4 w-4 mr-2" />
|
||||||
Reply
|
Reply
|
||||||
@ -641,6 +680,7 @@ export default function MailPage() {
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
onClick={() => handleReply('replyAll')}
|
||||||
>
|
>
|
||||||
<ReplyAll className="h-4 w-4 mr-2" />
|
<ReplyAll className="h-4 w-4 mr-2" />
|
||||||
Reply all
|
Reply all
|
||||||
@ -649,6 +689,7 @@ export default function MailPage() {
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
className="text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
onClick={() => handleReply('forward')}
|
||||||
>
|
>
|
||||||
<Forward className="h-4 w-4 mr-2" />
|
<Forward className="h-4 w-4 mr-2" />
|
||||||
Forward
|
Forward
|
||||||
@ -777,6 +818,8 @@ export default function MailPage() {
|
|||||||
<Input
|
<Input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="email@example.com"
|
placeholder="email@example.com"
|
||||||
|
value={composeRecipient}
|
||||||
|
onChange={(e) => setComposeRecipient(e.target.value)}
|
||||||
className="bg-white border-gray-200 py-1.5"
|
className="bg-white border-gray-200 py-1.5"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -825,6 +868,8 @@ export default function MailPage() {
|
|||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Subject"
|
placeholder="Subject"
|
||||||
|
value={composeSubject}
|
||||||
|
onChange={(e) => setComposeSubject(e.target.value)}
|
||||||
className="bg-white border-gray-200 py-1.5"
|
className="bg-white border-gray-200 py-1.5"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -835,6 +880,8 @@ export default function MailPage() {
|
|||||||
<Textarea
|
<Textarea
|
||||||
className="mt-0.5 h-[calc(100%-1.5rem)] min-h-[200px] bg-white border-gray-200 resize-none"
|
className="mt-0.5 h-[calc(100%-1.5rem)] min-h-[200px] bg-white border-gray-200 resize-none"
|
||||||
placeholder="Write your message here..."
|
placeholder="Write your message here..."
|
||||||
|
value={composeContent}
|
||||||
|
onChange={(e) => setComposeContent(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user