diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 1616e3cc..886d0a0b 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -1557,56 +1557,75 @@ export default function CourrierPage() { }; // Add handleReply function - const handleReply = (type: 'reply' | 'replyAll' | 'forward') => { - if (!selectedEmail) return; + const handleReply = async (type: 'reply' | 'replyAll' | 'forward') => { + // First, ensure we have the full email content + if (!selectedEmail) { + setError('No email selected'); + return; + } - const getReplySubject = () => { - const subject = selectedEmail.subject; - if (type === 'forward') { - return subject.startsWith('Fwd:') ? subject : `Fwd: ${subject}`; - } - return subject.startsWith('Re:') ? subject : `Re: ${subject}`; - }; - - const getReplyTo = () => { - switch (type) { - case 'reply': - return selectedEmail.from; - case 'replyAll': - // For Reply All, only put the original sender in To - return selectedEmail.from; - case 'forward': - return ''; - } - }; - - const getReplyCc = () => { - if (type === 'replyAll') { - // For Reply All, put all other recipients in CC, excluding the sender and current user - const allRecipients = new Set([ - ...(selectedEmail.to?.split(',') || []), - ...(selectedEmail.cc?.split(',') || []) - ]); - // Remove the sender and current user from CC - allRecipients.delete(selectedEmail.from); - allRecipients.delete(accounts[1]?.email); - return Array.from(allRecipients) - .map(email => email.trim()) - .filter(email => email) // Remove empty strings - .join(', '); - } - return ''; - }; - - const getReplyBody = () => { + if (!selectedEmail.body) { try { + // Fetch the full email content + const response = await fetch(`/api/mail/${selectedEmail.id}`); + if (!response.ok) { + throw new Error('Failed to fetch email content'); + } + const emailData = await response.json(); + + // Update the selected email with the full content + setSelectedEmail(prev => { + if (!prev) return null; + return { + ...prev, + body: emailData.body, + to: emailData.to, + cc: emailData.cc, + bcc: emailData.bcc + }; + }); + } catch (error) { + console.error('Error fetching email content:', error); + // Show error to user + setError('Failed to load email content. Please try again.'); + return; + } + } + + // Helper functions for reply composition + const getReplySubject = (): string => { + if (!selectedEmail) return ''; + const prefix = type === 'forward' ? 'Fwd:' : 'Re:'; + return `${prefix} ${selectedEmail.subject}`; + }; + + const getReplyTo = (): string => { + if (!selectedEmail) return ''; + if (type === 'forward') return ''; + return selectedEmail.from; + }; + + const getReplyCc = (): string => { + if (!selectedEmail) return ''; + if (type === 'forward' || type === 'reply') return ''; + return selectedEmail.cc || ''; + }; + + const getReplyBody = (): string => { + if (!selectedEmail?.body) return ''; + + try { + // Now we can safely parse the full email content const parsed = parseFullEmail(selectedEmail.body); let originalContent = ''; // Get the content from either HTML or text part if (parsed.html) { + // Use the existing MIME decoding for HTML content + originalContent = decodeMIME(parsed.html, 'quoted-printable', 'utf-8'); + // Convert HTML to plain text for the reply - originalContent = parsed.html + originalContent = originalContent .replace(/]*>[\s\S]*?<\/style>/gi, '') .replace(/]*>[\s\S]*?<\/script>/gi, '') .replace(//gi, '\n') @@ -1631,12 +1650,15 @@ export default function CourrierPage() { .replace(/\n{3,}/g, '\n\n') .trim(); } else if (parsed.text) { - originalContent = parsed.text.trim(); + // Use the existing MIME decoding for plain text content + originalContent = decodeMIME(parsed.text, 'quoted-printable', 'utf-8').trim(); } else { - // Fallback to raw body if parsing fails - originalContent = selectedEmail.body - .replace(/<[^>]+>/g, '') - .trim(); + // Fallback to raw body if parsing fails, but still try to decode it + originalContent = decodeMIME( + selectedEmail.body.replace(/<[^>]+>/g, ''), + 'quoted-printable', + 'utf-8' + ).trim(); } // Clean up the content @@ -1690,27 +1712,30 @@ export default function CourrierPage() { replyHeader = `\n\nOn ${formattedDate}, ${selectedEmail.from} wrote:\n`; } - // Indent the original content - const indentedContent = originalContent - .split('\n') - .map(line => line ? `> ${line}` : '>') // Keep empty lines as '>' for better readability - .join('\n'); - - return `${replyHeader}${indentedContent}`; + return replyHeader + originalContent; } catch (error) { - console.error('Error formatting reply:', error); - return `\n\nOn ${new Date(selectedEmail.date).toLocaleString()}, ${selectedEmail.from} wrote:\n> ${selectedEmail.body}`; + console.error('Error preparing reply body:', error); + return ''; } }; - // Open compose modal with reply details - setShowCompose(true); - setComposeTo(getReplyTo()); - setComposeSubject(getReplySubject()); - setComposeBody(getReplyBody()); - setComposeCc(getReplyCc()); + // Prepare the reply email + const replyEmail = { + to: getReplyTo(), + cc: getReplyCc(), + subject: getReplySubject(), + body: getReplyBody() + }; + + // Update the compose form with the reply content + setComposeTo(replyEmail.to); + setComposeCc(replyEmail.cc); + setComposeSubject(replyEmail.subject); + setComposeBody(replyEmail.body); setComposeBcc(''); - // Show CC field automatically for Reply All + + // Show the compose form and CC field for Reply All + setShowCompose(true); setShowCc(type === 'replyAll'); setShowBcc(false); setAttachments([]);