mail page ui correction maj compose 9
This commit is contained in:
parent
eca8d1ee01
commit
c2395e51d1
@ -47,6 +47,13 @@ interface Email {
|
||||
category: string;
|
||||
}
|
||||
|
||||
interface Attachment {
|
||||
name: string;
|
||||
type: string;
|
||||
content: string;
|
||||
encoding: string;
|
||||
}
|
||||
|
||||
// Improved MIME Decoder Implementation for Infomaniak
|
||||
function extractBoundary(headers: string): string | null {
|
||||
const boundaryMatch = headers.match(/boundary="?([^"\r\n;]+)"?/i) ||
|
||||
@ -451,7 +458,7 @@ export default function MailPage() {
|
||||
const [itemToDelete, setItemToDelete] = useState<number | null>(null);
|
||||
const [showCc, setShowCc] = useState(false);
|
||||
const [contentLoading, setContentLoading] = useState(false);
|
||||
const [attachments, setAttachments] = useState<File[]>([]);
|
||||
const [attachments, setAttachments] = useState<Attachment[]>([]);
|
||||
|
||||
// Move getSelectedEmail inside the component
|
||||
const getSelectedEmail = () => {
|
||||
@ -621,7 +628,7 @@ export default function MailPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// Handle reply
|
||||
// Handle reply with MIME encoding
|
||||
const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => {
|
||||
const selectedEmailData = getSelectedEmail();
|
||||
if (!selectedEmailData) return;
|
||||
@ -629,25 +636,158 @@ export default function MailPage() {
|
||||
setShowCompose(true);
|
||||
const subject = `${type === 'forward' ? 'Fwd: ' : 'Re: '}${selectedEmailData.subject}`;
|
||||
let to = '';
|
||||
let cc = '';
|
||||
let content = '';
|
||||
|
||||
// Parse the original email content using MIME decoder
|
||||
const parsedEmail = parseFullEmail(selectedEmailData.body);
|
||||
const decodedBody = parsedEmail.text || parsedEmail.html || selectedEmailData.body;
|
||||
|
||||
// Format the date properly
|
||||
const emailDate = new Date(selectedEmailData.date).toLocaleString('en-US', {
|
||||
weekday: 'short',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: true
|
||||
});
|
||||
|
||||
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> ')}`;
|
||||
content = `\n\nOn ${emailDate}, ${selectedEmailData.fromName} wrote:\n> ${decodedBody.split('\n').join('\n> ')}`;
|
||||
break;
|
||||
|
||||
case 'replyAll':
|
||||
to = selectedEmailData.from;
|
||||
content = `\n\nOn ${new Date(selectedEmailData.date).toLocaleString()}, ${selectedEmailData.fromName} wrote:\n> ${selectedEmailData.body.split('\n').join('\n> ')}`;
|
||||
// Extract CC addresses from the original email, excluding our own address
|
||||
const originalCc = selectedEmailData.cc || '';
|
||||
const ourEmail = accounts.find(acc => acc.id === selectedEmailData.accountId)?.email || '';
|
||||
const ccAddresses = originalCc
|
||||
.split(',')
|
||||
.map(addr => addr.trim())
|
||||
.filter(addr => addr !== ourEmail && addr !== selectedEmailData.from);
|
||||
cc = ccAddresses.join(', ');
|
||||
content = `\n\nOn ${emailDate}, ${selectedEmailData.fromName} wrote:\n> ${decodedBody.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}`;
|
||||
// Include original attachments if any
|
||||
const attachmentInfo = parsedEmail.attachments.length > 0
|
||||
? '\n\n-------- Attachments --------\n' +
|
||||
parsedEmail.attachments.map(att => att.filename).join('\n')
|
||||
: '';
|
||||
|
||||
content = `\n\n---------- Forwarded message ----------\n` +
|
||||
`From: ${selectedEmailData.fromName} <${selectedEmailData.from}>\n` +
|
||||
`Date: ${emailDate}\n` +
|
||||
`Subject: ${selectedEmailData.subject}\n` +
|
||||
`To: ${selectedEmailData.to}\n` +
|
||||
(selectedEmailData.cc ? `Cc: ${selectedEmailData.cc}\n` : '') +
|
||||
`\n\n${decodedBody}${attachmentInfo}`;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set the form state
|
||||
setComposeSubject(subject);
|
||||
setComposeTo(to);
|
||||
setComposeBody(cleanEmailContent(content));
|
||||
setComposeCc(cc);
|
||||
setComposeBody(content);
|
||||
|
||||
// Show CC field if there are CC recipients
|
||||
if (cc) {
|
||||
setShowCc(true);
|
||||
}
|
||||
|
||||
// Handle attachments for forwarded emails
|
||||
if (type === 'forward' && parsedEmail.attachments.length > 0) {
|
||||
// You'll need to implement attachment handling here
|
||||
// This could involve creating File objects from the attachment data
|
||||
// or storing the attachment information to be processed when sending
|
||||
handleForwardedAttachments(parsedEmail.attachments);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle forwarded attachments
|
||||
const handleForwardedAttachments = (attachments: Array<{
|
||||
filename: string;
|
||||
contentType: string;
|
||||
encoding: string;
|
||||
content: string;
|
||||
}>) => {
|
||||
// Store attachment information in state
|
||||
setAttachments(attachments.map(att => ({
|
||||
name: att.filename,
|
||||
type: att.contentType,
|
||||
content: att.content,
|
||||
encoding: att.encoding
|
||||
})));
|
||||
};
|
||||
|
||||
// Modified send function to handle MIME encoding
|
||||
const handleSend = async () => {
|
||||
try {
|
||||
// Create multipart message
|
||||
const boundary = `----=_Part_${Date.now()}`;
|
||||
let mimeContent = [
|
||||
`Content-Type: multipart/mixed; boundary="${boundary}"`,
|
||||
'',
|
||||
`--${boundary}`,
|
||||
'Content-Type: text/plain; charset=utf-8',
|
||||
'Content-Transfer-Encoding: 7bit',
|
||||
'',
|
||||
composeBody,
|
||||
''
|
||||
];
|
||||
|
||||
// Add attachments if any
|
||||
if (attachments.length > 0) {
|
||||
for (const attachment of attachments) {
|
||||
mimeContent = mimeContent.concat([
|
||||
`--${boundary}`,
|
||||
`Content-Type: ${attachment.type}`,
|
||||
`Content-Transfer-Encoding: base64`,
|
||||
`Content-Disposition: attachment; filename="${attachment.name}"`,
|
||||
'',
|
||||
attachment.content,
|
||||
''
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the multipart message
|
||||
mimeContent.push(`--${boundary}--`);
|
||||
|
||||
// Send the email with MIME content
|
||||
await fetch('/api/mail/send', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
to: composeTo,
|
||||
cc: composeCc,
|
||||
bcc: composeBcc,
|
||||
subject: composeSubject,
|
||||
body: mimeContent.join('\r\n'),
|
||||
attachments: attachments
|
||||
})
|
||||
});
|
||||
|
||||
// Clear the form
|
||||
setShowCompose(false);
|
||||
setComposeTo('');
|
||||
setComposeCc('');
|
||||
setComposeBcc('');
|
||||
setComposeSubject('');
|
||||
setComposeBody('');
|
||||
setShowCc(false);
|
||||
setShowBcc(false);
|
||||
setAttachments([]);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBulkDelete = () => {
|
||||
@ -695,7 +835,12 @@ export default function MailPage() {
|
||||
|
||||
const handleFileAttachment = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (e.target.files) {
|
||||
setAttachments(Array.from(e.target.files));
|
||||
setAttachments(Array.from(e.target.files).map(file => ({
|
||||
name: file.name,
|
||||
type: file.type,
|
||||
content: URL.createObjectURL(file),
|
||||
encoding: 'base64'
|
||||
})));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1231,32 +1376,7 @@ export default function MailPage() {
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-blue-600 text-white hover:bg-blue-700"
|
||||
onClick={async () => {
|
||||
try {
|
||||
await fetch('/api/mail/send', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
to: composeTo,
|
||||
cc: composeCc,
|
||||
bcc: composeBcc,
|
||||
subject: composeSubject,
|
||||
body: composeBody
|
||||
})
|
||||
});
|
||||
setShowCompose(false);
|
||||
// Clear form
|
||||
setComposeTo('');
|
||||
setComposeCc('');
|
||||
setComposeBcc('');
|
||||
setComposeSubject('');
|
||||
setComposeBody('');
|
||||
setShowCc(false);
|
||||
setShowBcc(false);
|
||||
} catch (error) {
|
||||
console.error('Error sending email:', error);
|
||||
}
|
||||
}}
|
||||
onClick={handleSend}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user