From 42746fe4f9f7982682bbd6eb185df37c3752c1bf Mon Sep 17 00:00:00 2001 From: alma Date: Sun, 27 Apr 2025 14:00:09 +0200 Subject: [PATCH] courrier redis login --- app/api/mail/login/route.ts | 121 +++++++++++++++--------------------- lib/imap.ts | 23 +++++-- 2 files changed, 69 insertions(+), 75 deletions(-) diff --git a/app/api/mail/login/route.ts b/app/api/mail/login/route.ts index 01491263..685cdd78 100644 --- a/app/api/mail/login/route.ts +++ b/app/api/mail/login/route.ts @@ -3,6 +3,9 @@ import { ImapFlow } from 'imapflow'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import { prisma } from '@/lib/prisma'; +import { saveUserEmailCredentials, testEmailConnection } from '@/lib/services/email-service'; +import { prefetchUserEmailData } from '@/lib/services/prefetch-service'; +import { invalidateUserEmailCache, getCachedEmailCredentials } from '@/lib/redis'; export async function POST(request: Request) { try { @@ -42,71 +45,39 @@ export async function POST(request: Request) { ); } - // Test IMAP connection - const client = new ImapFlow({ - host: host, - port: parseInt(port), - secure: true, - auth: { - user: email, - pass: password, - }, - logger: false, - emitLogs: false, - tls: { - rejectUnauthorized: false // Allow self-signed certificates - } + // Test connection before saving + const connectionSuccess = await testEmailConnection({ + email, + password, + host, + port: parseInt(port) }); - try { - await client.connect(); - await client.mailboxOpen('INBOX'); - - // Store or update credentials in database - await prisma.mailCredentials.upsert({ - where: { - userId: session.user.id - }, - update: { - email, - password, - host, - port: parseInt(port) - }, - create: { - userId: session.user.id, - email, - password, - host, - port: parseInt(port) - } - }); - - return NextResponse.json({ success: true }); - } catch (error) { - if (error instanceof Error) { - if (error.message.includes('Invalid login')) { - return NextResponse.json( - { error: 'Invalid login or password' }, - { status: 401 } - ); - } - return NextResponse.json( - { error: `IMAP connection error: ${error.message}` }, - { status: 500 } - ); - } + if (!connectionSuccess) { return NextResponse.json( - { error: 'Failed to connect to email server' }, - { status: 500 } + { error: 'Failed to connect to email server. Please check your credentials.' }, + { status: 401 } ); - } finally { - try { - await client.logout(); - } catch (e) { - console.error('Error during logout:', e); - } } + + // Invalidate all cached data for this user + await invalidateUserEmailCache(session.user.id); + + // Save credentials using the service that handles both database and Redis + await saveUserEmailCredentials(session.user.id, { + email, + password, + host, + port: parseInt(port) + }); + + // Start prefetching email data in the background + prefetchUserEmailData(session.user.id).catch(err => { + console.error('Background prefetch error:', err); + }); + + return NextResponse.json({ success: true }); + } catch (error) { console.error('Error in login handler:', error); return NextResponse.json( @@ -126,16 +97,26 @@ export async function GET() { ); } - const credentials = await prisma.mailCredentials.findUnique({ - where: { - userId: session.user.id - }, - select: { - email: true, - host: true, - port: true - } - }); + // First try to get from Redis cache + let credentials = await getCachedEmailCredentials(session.user.id); + + // If not in cache, get from database + if (!credentials) { + credentials = await prisma.mailCredentials.findUnique({ + where: { + userId: session.user.id + }, + select: { + email: true, + host: true, + port: true + } + }); + } else { + // Remove password from response + const { password, ...safeCredentials } = credentials; + credentials = safeCredentials; + } if (!credentials) { return NextResponse.json( diff --git a/lib/imap.ts b/lib/imap.ts index 42ac66c3..d29cce65 100644 --- a/lib/imap.ts +++ b/lib/imap.ts @@ -2,6 +2,7 @@ import { ImapFlow } from 'imapflow'; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import { prisma } from '@/lib/prisma'; +import { getCachedEmailCredentials } from '@/lib/redis'; export async function getImapClient() { const session = await getServerSession(authOptions); @@ -9,16 +10,28 @@ export async function getImapClient() { throw new Error('No authenticated user'); } - const credentials = await prisma.mailCredentials.findUnique({ - where: { - userId: session.user.id - } - }); + // First try to get credentials from Redis cache + let credentials = await getCachedEmailCredentials(session.user.id); + + // If not in cache, get from database + if (!credentials) { + console.log(`Credentials not found in cache for ${session.user.id}, checking database`); + credentials = await prisma.mailCredentials.findUnique({ + where: { + userId: session.user.id + } + }); + } 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,