import { NextResponse } from 'next/server'; import { cookies } from 'next/headers'; import Imap from 'imap'; interface StoredCredentials { email: string; password: string; host: string; port: number; } function getStoredCredentials(): StoredCredentials | null { const cookieStore = cookies(); const credentialsCookie = cookieStore.get('imap_credentials'); if (!credentialsCookie?.value) { return null; } try { const credentials = JSON.parse(credentialsCookie.value); if (!credentials.email || !credentials.password || !credentials.host || !credentials.port) { return null; } return credentials; } catch (error) { return null; } } export async function POST(request: Request) { try { const { emailIds, action } = await request.json(); if (!emailIds || !Array.isArray(emailIds) || !action) { return NextResponse.json( { error: 'Invalid request parameters' }, { status: 400 } ); } // Get the current folder from the request URL const url = new URL(request.url); const folder = url.searchParams.get('folder') || 'INBOX'; // Get stored credentials const credentials = getStoredCredentials(); if (!credentials) { return NextResponse.json( { error: 'No stored credentials found' }, { status: 401 } ); } return new Promise((resolve) => { const imap = new Imap({ user: credentials.email, password: credentials.password, host: credentials.host, port: credentials.port, tls: true, tlsOptions: { rejectUnauthorized: false }, authTimeout: 30000, connTimeout: 30000 }); const timeout = setTimeout(() => { console.error('IMAP connection timeout'); imap.end(); resolve(NextResponse.json({ error: 'Connection timeout' })); }, 30000); imap.once('error', (err: Error) => { console.error('IMAP error:', err); clearTimeout(timeout); resolve(NextResponse.json({ error: 'IMAP connection error' })); }); imap.once('ready', () => { imap.openBox(folder, false, (err, box) => { if (err) { console.error(`Error opening box ${folder}:`, err); clearTimeout(timeout); imap.end(); resolve(NextResponse.json({ error: `Failed to open folder ${folder}` })); return; } // Convert string IDs to numbers const numericIds = emailIds.map(id => parseInt(id, 10)); // Process each email let processedCount = 0; const totalEmails = numericIds.length; const processNextEmail = (index: number) => { if (index >= totalEmails) { clearTimeout(timeout); imap.end(); resolve(NextResponse.json({ success: true })); return; } const id = numericIds[index]; const fetch = imap.fetch(id.toString(), { bodies: '', struct: true }); fetch.on('message', (msg) => { msg.once('attributes', (attrs) => { const uid = attrs.uid; if (!uid) { processedCount++; processNextEmail(index + 1); return; } switch (action) { case 'delete': imap.move(uid, 'Trash', (err) => { if (err) console.error('Error moving to trash:', err); processedCount++; processNextEmail(index + 1); }); break; case 'mark-read': imap.addFlags(uid, ['\\Seen'], (err) => { if (err) console.error('Error marking as read:', err); processedCount++; processNextEmail(index + 1); }); break; case 'mark-unread': imap.removeFlags(uid, ['\\Seen'], (err) => { if (err) console.error('Error marking as unread:', err); processedCount++; processNextEmail(index + 1); }); break; case 'archive': imap.move(uid, 'Archive', (err) => { if (err) console.error('Error moving to archive:', err); processedCount++; processNextEmail(index + 1); }); break; } }); }); fetch.on('error', (err) => { console.error('Error fetching email:', err); processedCount++; processNextEmail(index + 1); }); }; processNextEmail(0); }); }); imap.connect(); }); } catch (error) { console.error('Error in bulk actions:', error); return NextResponse.json( { error: 'Failed to perform bulk action' }, { status: 500 } ); } }