import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import { saveUserEmailCredentials, testEmailConnection } from '@/lib/services/email-service'; import { invalidateFolderCache } from '@/lib/redis'; import { prisma } from '@/lib/prisma'; // Define EmailCredentials interface inline since we're having import issues interface EmailCredentials { email: string; password?: string; host: string; port: number; secure?: boolean; smtp_host?: string; smtp_port?: number; smtp_secure?: boolean; display_name?: string; color?: string; } /** * Check if a user exists in the database */ async function userExists(userId: string): Promise { try { const user = await prisma.user.findUnique({ where: { id: userId }, select: { id: true } }); return !!user; } catch (error) { console.error(`Error checking if user exists:`, error); return false; } } export async function POST(request: Request) { try { // Authenticate user const session = await getServerSession(authOptions); if (!session?.user?.id) { return NextResponse.json( { error: 'Unauthorized' }, { status: 401 } ); } // Verify that the user exists in the database const userExistsInDB = await userExists(session.user.id); if (!userExistsInDB) { console.error(`User with ID ${session.user.id} not found in database`); return NextResponse.json( { error: 'User not found in database', details: `The user ID from your session (${session.user.id}) doesn't exist in the database. This may be due to a session/database mismatch.` }, { status: 400 } ); } // Parse request body const body = await request.json().catch(e => { console.error('Error parsing request body:', e); return {}; }); // Log the request (but hide password) console.log('Adding account:', { ...body, password: body.password ? '***' : undefined }); const { email, password, host, port, secure, smtp_host, smtp_port, smtp_secure, display_name, color } = body; // Validate required fields const missingFields = []; if (!email) missingFields.push('email'); if (!password) missingFields.push('password'); if (!host) missingFields.push('host'); if (port === undefined) missingFields.push('port'); if (missingFields.length > 0) { console.error(`Missing required fields: ${missingFields.join(', ')}`); return NextResponse.json( { error: `Required fields missing: ${missingFields.join(', ')}` }, { status: 400 } ); } // Fix common hostname errors - strip http/https prefixes let cleanHost = host; if (cleanHost.startsWith('http://')) { cleanHost = cleanHost.substring(7); } else if (cleanHost.startsWith('https://')) { cleanHost = cleanHost.substring(8); } // Create credentials object const credentials: EmailCredentials = { email, password, host: cleanHost, port: typeof port === 'string' ? parseInt(port) : port, secure: secure ?? true, // Optional SMTP settings ...(smtp_host && { smtp_host }), ...(smtp_port && { smtp_port: typeof smtp_port === 'string' ? parseInt(smtp_port) : smtp_port }), ...(smtp_secure !== undefined && { smtp_secure }), // Optional display settings ...(display_name && { display_name }), ...(color && { color }) }; // Test connection before saving console.log(`Testing connection before saving for user ${session.user.id}`); const testResult = await testEmailConnection(credentials); if (!testResult.imap) { return NextResponse.json( { error: `Connection test failed: ${testResult.error || 'Could not connect to IMAP server'}` }, { status: 400 } ); } // Save credentials to database and cache console.log(`Saving credentials for user: ${session.user.id}`); await saveUserEmailCredentials(session.user.id, email, credentials); console.log(`Email account successfully added for user ${session.user.id}`); // Fetch the created account from the database const createdAccount = await prisma.mailCredentials.findFirst({ where: { userId: session.user.id, email }, select: { id: true, email: true, display_name: true, color: true, } }); // Invalidate all folder caches for this user/account await invalidateFolderCache(session.user.id, email, '*'); return NextResponse.json({ success: true, account: createdAccount, message: 'Email account added successfully' }); } catch (error) { console.error('Error adding email account:', error); return NextResponse.json( { error: 'Failed to add email account', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ); } } export async function DELETE(request: Request) { try { const session = await getServerSession(authOptions); if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { searchParams } = new URL(request.url); const accountId = searchParams.get('accountId'); if (!accountId) { return NextResponse.json({ error: 'Missing accountId' }, { status: 400 }); } // Find the account const account = await prisma.mailCredentials.findFirst({ where: { id: accountId, userId: session.user.id }, }); if (!account) { return NextResponse.json({ error: 'Account not found' }, { status: 404 }); } // Delete from database await prisma.mailCredentials.delete({ where: { id: accountId } }); // Invalidate cache await invalidateFolderCache(session.user.id, account.email, '*'); return NextResponse.json({ success: true, message: 'Account deleted' }); } catch (error) { console.error('Error deleting account:', error); return NextResponse.json({ error: 'Failed to delete account', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 }); } } export async function PATCH(request: Request) { try { // Authenticate user const session = await getServerSession(authOptions); if (!session?.user?.id) { return NextResponse.json( { error: 'Unauthorized' }, { status: 401 } ); } // Parse request body const body = await request.json(); const { accountId, newPassword, display_name, color } = body; if (!accountId) { return NextResponse.json( { error: 'Account ID is required' }, { status: 400 } ); } // Check if at least one of the fields is provided if (!newPassword && !display_name && !color) { return NextResponse.json( { error: 'At least one field to update is required' }, { status: 400 } ); } // Verify the account belongs to the user const account = await prisma.mailCredentials.findFirst({ where: { id: accountId, userId: session.user.id } }); if (!account) { return NextResponse.json( { error: 'Account not found' }, { status: 404 } ); } // Build update data object const updateData: any = {}; // Add password if provided if (newPassword) { updateData.password = newPassword; } // Add display_name if provided if (display_name !== undefined) { updateData.display_name = display_name; } // Add color if provided if (color) { updateData.color = color; } // Update the account await prisma.mailCredentials.update({ where: { id: accountId }, data: updateData }); return NextResponse.json({ success: true, message: 'Account updated successfully' }); } catch (error) { console.error('Error updating account:', error); return NextResponse.json( { error: 'Failed to update account', details: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ); } } const handleAddAccount = async (accountData: AccountData) => { // ... account creation logic ... // setAccounts(prev => [...prev, newAccount]); // setVisibleFolders(prev => ({ // ...prev, // [newAccount.id]: newAccount.folders // })); };