import { ImapFlow } from 'imapflow'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { prisma } from '@/lib/prisma'; import { getCachedEmailCredentials } from '@/lib/redis'; import { EmailCredentials } from '@/lib/types'; export async function getImapClient() { const session = await getServerSession(authOptions); if (!session?.user?.id) { throw new Error('No authenticated user'); } // First try to get credentials from Redis cache let credentials = await getCachedEmailCredentials(session.user.id, 'default'); // If not in cache, get from database if (!credentials) { console.log(`Credentials not found in cache for ${session.user.id}, checking database`); const dbCredentials = await prisma.mailCredentials.findFirst({ where: { userId: session.user.id } }); // Convert database model to EmailCredentials if (dbCredentials) { const dbCreds = dbCredentials as any; credentials = { email: dbCreds.email, password: dbCreds.password || undefined, // Convert null to undefined host: dbCreds.host, port: dbCreds.port, secure: dbCreds.secure, useOAuth: dbCreds.use_oauth, accessToken: dbCreds.access_token || undefined, refreshToken: dbCreds.refresh_token || undefined, smtp_host: dbCreds.smtp_host || undefined, smtp_port: dbCreds.smtp_port || undefined, // Handle null smtp_secure: dbCreds.smtp_secure || undefined, // Handle null display_name: dbCreds.display_name || undefined, color: dbCreds.color || undefined, }; } } if (!credentials) { throw new Error('No mail credentials found. Please configure your email account.'); } // Validate credentials if (!credentials.password) { throw new Error('No password configured for email account'); } return new ImapFlow({ host: credentials.host, port: credentials.port, secure: true, auth: { user: credentials.email, pass: credentials.password, }, logger: false, tls: { rejectUnauthorized: false } }); } export async function moveEmails(emailIds: number[], targetFolder: string) { const imap = await getImapClient(); const lock = await imap.getMailboxLock('INBOX'); try { for (const id of emailIds) { const message = await imap.fetchOne(id.toString(), { uid: true }); if (message) { const uid = typeof message.uid === 'number' ? message.uid.toString() : message.uid; await imap.messageMove(uid, targetFolder); } } } finally { lock.release(); } } export async function markAsRead(emailIds: (string | number)[], isRead: boolean) { const imap = await getImapClient(); try { await imap.connect(); const lock = await imap.getMailboxLock('INBOX'); try { for (const id of emailIds) { const stringId = typeof id === 'number' ? id.toString() : id; const message = await imap.fetchOne(stringId, { uid: true }); if (message) { const uid = typeof message.uid === 'number' ? message.uid.toString() : message.uid; await imap.messageFlagsAdd(uid, isRead ? ['\\Seen'] : [], { uid: true }); } } } finally { lock.release(); } } finally { await imap.logout(); } }