diff --git a/lib/services/email-service.ts b/lib/services/email-service.ts index abaa0b57..8e6bb09c 100644 --- a/lib/services/email-service.ts +++ b/lib/services/email-service.ts @@ -846,6 +846,18 @@ export async function getEmails( } } +// Map email addresses safely with null checks +function mapAddresses(addresses: any[] | undefined): Array<{ name: string; address: string }> { + if (!addresses || !Array.isArray(addresses)) { + return []; + } + + return addresses.map((addr: any) => ({ + name: addr.name || addr.address || '', + address: addr.address || '' + })); +} + /** * Get a single email with full content */ @@ -894,6 +906,8 @@ export async function getEmailContent( const client = await getImapConnection(userId, effectiveAccountId); try { + await client.mailboxOpen(normalizedFolder); + // Log connection details with account context console.log(`[DEBUG] Fetching email ${emailId} from folder ${normalizedFolder} for account ${effectiveAccountId}`); @@ -926,25 +940,47 @@ export async function getEmailContent( const sequenceNumber = searchResult[0]; console.log(`[DEBUG] Found sequence number ${sequenceNumber} for UID ${numericId} in account ${effectiveAccountId}`); - // Now fetch using the sequence number - const message = await client.fetchOne(sequenceNumber.toString(), { - source: true, - envelope: true, - flags: true, - size: true - }); + // Now fetch using the sequence number with error handling + let message; + try { + message = await client.fetchOne(sequenceNumber.toString(), { + source: true, + envelope: true, + flags: true, + size: true + }); + } catch (fetchError) { + console.error(`Error fetching message with sequence ${sequenceNumber}:`, fetchError); + throw new Error(`Failed to fetch email: ${fetchError instanceof Error ? fetchError.message : 'Unknown error'}`); + } if (!message) { throw new Error(`Email not found with sequence number ${sequenceNumber} in folder ${normalizedFolder} for account ${effectiveAccountId}`); } + // Check if message has required fields + if (!message.source || !message.envelope) { + throw new Error(`Invalid email data received: missing source or envelope data`); + } + const { source, envelope, flags, size } = message; + // Validate envelope data + if (!envelope) { + throw new Error('Email envelope data is missing'); + } + // Parse the email content, ensuring all styles and structure are preserved - const parsedEmail = await simpleParser(source.toString(), { - skipHtmlToText: true, - keepCidLinks: true - }); + let parsedEmail; + try { + parsedEmail = await simpleParser(source.toString(), { + skipHtmlToText: true, + keepCidLinks: true + }); + } catch (parseError) { + console.error(`Error parsing email content for ${emailId}:`, parseError); + throw new Error(`Failed to parse email content: ${parseError instanceof Error ? parseError.message : 'Unknown error'}`); + } // Convert flags from Set to boolean checks const flagsArray = Array.from(flags as Set); @@ -956,22 +992,10 @@ export async function getEmailContent( id: emailId, messageId: envelope.messageId, subject: envelope.subject || "(No Subject)", - from: envelope.from.map((f: any) => ({ - name: f.name || f.address, - address: f.address, - })), - to: envelope.to.map((t: any) => ({ - name: t.name || t.address, - address: t.address, - })), - cc: (envelope.cc || []).map((c: any) => ({ - name: c.name || c.address, - address: c.address, - })), - bcc: (envelope.bcc || []).map((b: any) => ({ - name: b.name || b.address, - address: b.address, - })), + from: mapAddresses(envelope.from), + to: mapAddresses(envelope.to), + cc: mapAddresses(envelope.cc), + bcc: mapAddresses(envelope.bcc), date: envelope.date || new Date(), flags: { seen: flagsArray.includes("\\Seen"),