import { NextResponse } from 'next/server'; import Imap from 'imap'; import { simpleParser } from 'mailparser'; // Debug logging for environment variables console.log('Environment Variables:', { IMAP_USER: process.env.IMAP_USER, IMAP_HOST: process.env.IMAP_HOST, IMAP_PORT: process.env.IMAP_PORT, IMAP_PASSWORD: process.env.IMAP_PASSWORD ? '***' : undefined, NODE_ENV: process.env.NODE_ENV }); // Helper function to get stored credentials function getStoredCredentials() { if (typeof window === 'undefined') { // Server-side: use environment variables return { user: process.env.IMAP_USER, password: process.env.IMAP_PASSWORD, host: process.env.IMAP_HOST, port: process.env.IMAP_PORT }; } // Client-side: use localStorage const stored = localStorage.getItem('imapCredentials'); return stored ? JSON.parse(stored) : null; } // IMAP configuration const getImapConfig = () => { const credentials = getStoredCredentials(); if (!credentials?.user || !credentials?.password) { throw new Error('Email credentials not found. Please log in first.'); } return { user: credentials.user, password: credentials.password, host: credentials.host || 'mail.infomaniak.com', port: parseInt(credentials.port || '993', 10), tls: true, tlsOptions: { rejectUnauthorized: false, servername: credentials.host || 'mail.infomaniak.com' }, authTimeout: 10000, connTimeout: 10000, debug: console.log }; }; // Debug logging for IMAP configuration console.log('IMAP Configuration:', { user: getImapConfig().user, host: getImapConfig().host, port: getImapConfig().port, tls: getImapConfig().tls, hasPassword: !!getImapConfig().password, authTimeout: getImapConfig().authTimeout, connTimeout: getImapConfig().connTimeout }); interface ImapMessage { header: { from?: string[]; to?: string[]; subject?: string[]; date?: string[]; [key: string]: string[] | undefined; }; body: string; attributes: { flags: string[]; }; } interface ImapError extends Error { type?: string; textCode?: string; source?: string; } // Helper function to create a promise-based IMAP connection function createImapConnection(imapConfig: Imap.Config) { return new Promise((resolve, reject) => { console.log('Creating new IMAP connection with config:', { user: imapConfig.user, host: imapConfig.host, port: imapConfig.port, tls: imapConfig.tls }); const imap = new Imap(imapConfig); imap.once('ready', () => { console.log('IMAP connection established successfully'); resolve(imap); }); imap.once('error', (err: ImapError) => { console.error('IMAP connection error:', err); console.error('Error details:', { type: err.type, textCode: err.textCode, source: err.source }); reject(err); }); imap.once('end', () => { console.log('IMAP connection ended'); }); try { console.log('Attempting to connect to IMAP server...'); imap.connect(); } catch (err) { console.error('Error during IMAP connection:', err); reject(err); } }); } // Helper function to promisify the message fetching function fetchMessages(imap: Imap, box: string): Promise { return new Promise((resolve, reject) => { imap.openBox(box, false, (err, mailbox) => { if (err) { reject(err); return; } // Search for all messages imap.search(['ALL'], (err, results) => { if (err) { reject(err); return; } // No messages found if (!results || !results.length) { resolve([]); return; } const fetch = imap.fetch(results, { bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)', 'TEXT'], struct: true }); const messages: ImapMessage[] = []; fetch.on('message', (msg) => { const message: Partial = {}; msg.on('body', (stream, info) => { let buffer = ''; stream.on('data', (chunk) => { buffer += chunk.toString('utf8'); }); stream.once('end', () => { if (info.which === 'TEXT') { message.body = buffer; } else { message.header = Imap.parseHeader(buffer); } }); }); msg.once('attributes', (attrs) => { message.attributes = attrs; }); msg.once('end', () => { messages.push(message as ImapMessage); }); }); fetch.once('error', (err) => { reject(err); }); fetch.once('end', () => { resolve(messages); }); }); }); }); } export async function GET(request: Request) { try { console.log('Starting email fetch process...'); const imapConfig = getImapConfig(); console.log('IMAP Configuration:', { user: imapConfig.user, host: imapConfig.host, port: imapConfig.port, tls: imapConfig.tls, hasPassword: !!imapConfig.password }); console.log('Creating IMAP connection...'); const imap = await createImapConnection(imapConfig) as Imap; console.log('Fetching messages...'); const messages = await fetchMessages(imap, 'INBOX'); console.log(`Successfully fetched ${messages.length} messages`); // Process messages into the format expected by the frontend const processedMessages = messages.map((msg: ImapMessage, index: number) => ({ id: index + 1, accountId: 1, from: msg.header.from?.[0] || '', fromName: (msg.header.from?.[0] || '').split('<')[0].trim(), to: msg.header.to?.[0] || '', subject: msg.header.subject?.[0] || '', body: msg.body || '', date: msg.header.date?.[0] || new Date().toISOString(), read: !(msg.attributes.flags.indexOf('\\Seen') < 0), starred: !(msg.attributes.flags.indexOf('\\Flagged') < 0), category: 'inbox' })); imap.end(); return NextResponse.json({ messages: processedMessages }); } catch (error) { console.error('Error in GET handler:', error); return NextResponse.json({ error: 'Failed to fetch emails', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 }); } } // Add endpoint to get mailboxes export async function POST(request: Request) { try { const imap = await createImapConnection(getImapConfig()) as Imap; const mailboxes = await new Promise((resolve, reject) => { imap.getBoxes((err, boxes) => { if (err) reject(err); resolve(boxes); }); }); imap.end(); return NextResponse.json({ mailboxes }); } catch (error) { console.error('Error fetching mailboxes:', error); return NextResponse.json({ error: 'Failed to fetch mailboxes' }, { status: 500 }); } }