diff --git a/app/api/courrier/[id]/route.ts b/app/api/courrier/[id]/route.ts index 49c021b6..550aa556 100644 --- a/app/api/courrier/[id]/route.ts +++ b/app/api/courrier/[id]/route.ts @@ -126,6 +126,15 @@ export async function GET( // 9. Parse the email content const parsedEmail = await parseEmail(foundMessage.source.toString()); + // Debug the parsed email structure + console.log('Parsed email data structure:', { + hasHtml: !!parsedEmail.html, + hasText: !!parsedEmail.text, + htmlLength: parsedEmail.html ? parsedEmail.html.length : 0, + textLength: parsedEmail.text ? parsedEmail.text.length : 0, + attachmentsCount: parsedEmail.attachments ? parsedEmail.attachments.length : 0 + }); + // 10. Prepare the full email object with all needed data const fullEmail = { id, @@ -137,6 +146,7 @@ export async function GET( date: foundMessage.envelope.date?.toISOString() || new Date().toISOString(), content: parsedEmail.html || parsedEmail.text || '', textContent: parsedEmail.text || '', + rawContent: foundMessage.source.toString(), // Include raw content for fallback read: foundMessage.flags.has('\\Seen'), starred: foundMessage.flags.has('\\Flagged'), folder: folder, @@ -146,6 +156,15 @@ export async function GET( headers: parsedEmail.headers || {} }; + // Log the structure of the email being returned + console.log('Returning email object with content structure:', { + id: fullEmail.id, + hasContent: !!fullEmail.content, + contentLength: fullEmail.content ? fullEmail.content.length : 0, + hasTextContent: !!fullEmail.textContent, + textContentLength: fullEmail.textContent ? fullEmail.textContent.length : 0 + }); + // 11. Mark as read if not already if (!foundMessage.flags.has('\\Seen')) { try { diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index 7ac93298..e264eb7a 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -49,6 +49,8 @@ export interface Email { subject: string; content: string; body?: string; // For backward compatibility + textContent?: string; + rawContent?: string; // Raw email content for fallback display date: string; read: boolean; starred: boolean; @@ -111,7 +113,33 @@ function EmailContent({ email }: { email: Email }) { setIsLoading(true); try { - if (!email.content) { + // Debug the email object + console.log('EmailContent received email:', { + id: email.id, + subject: email.subject, + hasContent: !!email.content, + contentLength: email.content ? email.content.length : 0, + hasTextContent: !!email.textContent, + hasRawContent: !!email.rawContent, + hasBody: !!email.body + }); + + // First check if we have pre-parsed content + if (email.textContent) { + if (mounted) { + setContent( +
+ {email.textContent} +
+ ); + setIsLoading(false); + setError(null); + } + return; + } + + // Check if we have any content to parse + if (!email.content && !email.body && !email.rawContent) { if (mounted) { setContent(
No content available
); setIsLoading(false); @@ -119,7 +147,8 @@ function EmailContent({ email }: { email: Email }) { return; } - const formattedEmail = email.content.trim(); + // Use the best available content source + const formattedEmail = (email.content || email.body || email.rawContent || '').trim(); if (!formattedEmail) { if (mounted) { setContent(
No content available
); @@ -128,26 +157,60 @@ function EmailContent({ email }: { email: Email }) { return; } - const parsedEmail = await decodeEmail(formattedEmail); + // Debug the formatted email + console.log('Attempting to decode email content, length:', formattedEmail.length); - if (mounted) { - if (parsedEmail.html) { + try { + const parsedEmail = await decodeEmail(formattedEmail); + console.log('Parsed email result:', { + hasHtml: !!parsedEmail.html, + hasText: !!parsedEmail.text, + }); + + if (mounted) { + if (parsedEmail.html) { + setContent( +
+ ); + } else if (parsedEmail.text) { + setContent( +
+ {parsedEmail.text} +
+ ); + } else if (email.rawContent) { + // Use raw content directly if available and nothing else worked + setContent( +
+ {email.rawContent} +
+ ); + } else { + // Fall back to displaying the raw content + setContent( +
+ {formattedEmail} +
+ ); + } + setError(null); + } + } catch (parseError) { + console.error('Error parsing email:', parseError); + // Fallback to displaying raw content on parse error + if (mounted) { setContent( -
- ); - } else if (parsedEmail.text) { - setContent( -
- {parsedEmail.text} +
+ {email.rawContent || formattedEmail}
); - } else { - setContent(
No content available
); } - setError(null); + } + + if (mounted) { setIsLoading(false); } } catch (err) { @@ -165,7 +228,7 @@ function EmailContent({ email }: { email: Email }) { return () => { mounted = false; }; - }, [email?.content]); + }, [email?.content, email?.body, email?.textContent, email?.rawContent]); if (isLoading) { return ( @@ -183,6 +246,28 @@ function EmailContent({ email }: { email: Email }) { } function renderEmailContent(email: Email) { + if (!email) return
No email selected
; + + // Some emails might have content directly in HTML format + if (email.content && (email.content.includes(' + ); + } + + // If we have textContent, display it directly + if (email.textContent) { + return ( +
+ {email.textContent} +
+ ); + } + + // Use EmailContent component for more complex parsing return ; } @@ -620,23 +705,37 @@ export default function CourrierPage() { return account ? account.color : 'bg-gray-500'; }; - // Update handleEmailSelect to set selectedEmail correctly + // Update handleEmailSelect to set selectedEmail correctly and improve error handling const handleEmailSelect = async (emailId: string) => { try { // First, set partial selectedEmail to show something immediately const emailToSelect = emails.find(email => email.id === emailId); if (emailToSelect) { + console.log('Setting preliminary selected email:', { + id: emailToSelect.id, + subject: emailToSelect.subject, + hasContent: !!emailToSelect.content, + }); setSelectedEmail(emailToSelect); } // Then fetch the full content + console.log(`Fetching email content for ID: ${emailId}`); const response = await fetch(`/api/courrier/${emailId}`); if (!response.ok) { - throw new Error('Failed to fetch full email content'); + const errorText = await response.text(); + console.error(`Error response (${response.status}): ${errorText}`); + throw new Error(`Failed to fetch email content: ${response.status} ${response.statusText}`); } const fullEmail = await response.json(); + console.log('Received full email data:', { + id: fullEmail.id, + subject: fullEmail.subject, + hasContent: !!fullEmail.content, + fields: Object.keys(fullEmail), + }); // Set the complete selectedEmail with all content setSelectedEmail(fullEmail); @@ -669,6 +768,10 @@ export default function CourrierPage() { } } catch (error) { console.error('Error fetching email:', error); + // Keep the selected email if it was set initially + if (!selectedEmail) { + setError('Failed to load email content. Please try again.'); + } } };