From a4f751ba4bf340266f808c19cfd7cf19e2d5e2f4 Mon Sep 17 00:00:00 2001 From: alma Date: Mon, 21 Apr 2025 16:13:22 +0200 Subject: [PATCH] mail page rest dang --- app/api/courrier/login/route.ts | 135 ++++++++++++++++++++++++++++++++ app/api/courrier/route.ts | 88 +++++++++++++++++++++ app/courrier/page.tsx | 12 +-- 3 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 app/api/courrier/login/route.ts create mode 100644 app/api/courrier/route.ts diff --git a/app/api/courrier/login/route.ts b/app/api/courrier/login/route.ts new file mode 100644 index 00000000..3de134ec --- /dev/null +++ b/app/api/courrier/login/route.ts @@ -0,0 +1,135 @@ +import { NextResponse } from 'next/server'; +import { ImapFlow } from 'imapflow'; +import { getServerSession } from 'next-auth'; +import { authOptions } from '@/app/api/auth/[...nextauth]/route'; +import { prisma } from '@/lib/prisma'; + +export async function POST(request: Request) { + try { + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + const { email, password, host, port } = await request.json(); + + if (!email || !password || !host || !port) { + return NextResponse.json( + { error: 'Missing required fields' }, + { status: 400 } + ); + } + + // 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 + } + }); + + 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 } + ); + } + return NextResponse.json( + { error: 'Failed to connect to email server' }, + { status: 500 } + ); + } finally { + try { + await client.logout(); + } catch (e) { + console.error('Error during logout:', e); + } + } + } catch (error) { + console.error('Error in login handler:', error); + return NextResponse.json( + { error: 'An unexpected error occurred' }, + { status: 500 } + ); + } +} + +export async function GET() { + try { + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + const credentials = await prisma.mailCredentials.findUnique({ + where: { + userId: session.user.id + }, + select: { + email: true, + host: true, + port: true + } + }); + + if (!credentials) { + return NextResponse.json( + { error: 'No stored credentials found' }, + { status: 404 } + ); + } + + return NextResponse.json(credentials); + } catch (error) { + return NextResponse.json( + { error: 'Failed to retrieve credentials' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/api/courrier/route.ts b/app/api/courrier/route.ts new file mode 100644 index 00000000..5ea25bff --- /dev/null +++ b/app/api/courrier/route.ts @@ -0,0 +1,88 @@ +import { NextResponse } from 'next/server'; +import { ImapFlow } from 'imapflow'; +import { getServerSession } from 'next-auth'; +import { authOptions } from '@/app/api/auth/[...nextauth]/route'; +import { prisma } from '@/lib/prisma'; + +export async function GET() { + try { + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + // Get credentials from database + const credentials = await prisma.mailCredentials.findUnique({ + where: { + userId: session.user.id + } + }); + + if (!credentials) { + return NextResponse.json( + { error: 'No mail credentials found. Please configure your email account.' }, + { status: 401 } + ); + } + + // Connect to IMAP server + const client = new ImapFlow({ + host: credentials.host, + port: credentials.port, + secure: true, + auth: { + user: credentials.email, + pass: credentials.password, + }, + logger: false, + emitLogs: false, + tls: { + rejectUnauthorized: false + } + }); + + try { + await client.connect(); + const mailbox = await client.mailboxOpen('INBOX'); + + // Fetch only essential message data + const messages = await client.fetch('1:20', { + envelope: true, + flags: true + }); + + const result = []; + for await (const message of messages) { + result.push({ + id: message.uid.toString(), + from: message.envelope.from[0].address, + subject: message.envelope.subject || '(No subject)', + date: message.envelope.date.toISOString(), + read: message.flags.has('\\Seen'), + starred: message.flags.has('\\Flagged'), + folder: mailbox.path + }); + } + + return NextResponse.json({ + emails: result, + folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Spam'] + }); + } finally { + try { + await client.logout(); + } catch (e) { + console.error('Error during logout:', e); + } + } + } catch (error) { + console.error('Error in courrier route:', error); + return NextResponse.json( + { error: 'An unexpected error occurred' }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/app/courrier/page.tsx b/app/courrier/page.tsx index f632e967..bab5b1ad 100644 --- a/app/courrier/page.tsx +++ b/app/courrier/page.tsx @@ -463,7 +463,7 @@ export default function CourrierPage() { } setError(null); - const response = await fetch(`/api/courrier?folder=${currentView}&page=${page}&limit=${emailsPerPage}`); + const response = await fetch('/api/mail'); if (!response.ok) { throw new Error('Failed to load emails'); } @@ -500,19 +500,15 @@ export default function CourrierPage() { ).length; setUnreadCount(unreadInboxEmails); } - - // Update emails state based on whether we're loading more + if (isLoadMore) { setEmails(prev => [...prev, ...processedEmails]); + setPage(prev => prev + 1); } else { setEmails(processedEmails); + setPage(1); } - - // Update hasMore state based on the number of emails received - setHasMore(processedEmails.length === emailsPerPage); - } catch (err) { - console.error('Error loading emails:', err); setError(err instanceof Error ? err.message : 'Failed to load emails'); } finally { setLoading(false);