From b24e266187320bda15e4b645fbcd789fc5d2126b Mon Sep 17 00:00:00 2001 From: alma Date: Fri, 25 Apr 2025 16:28:28 +0200 Subject: [PATCH] panel 2 courier api --- app/api/courrier/[id]/route.ts | 147 +++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 app/api/courrier/[id]/route.ts diff --git a/app/api/courrier/[id]/route.ts b/app/api/courrier/[id]/route.ts new file mode 100644 index 00000000..bd846eb8 --- /dev/null +++ b/app/api/courrier/[id]/route.ts @@ -0,0 +1,147 @@ +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'; +import { parseEmail } from '@/lib/server/email-parser'; +import { LRUCache } from 'lru-cache'; + +// Simple in-memory cache for email content +const emailContentCache = new LRUCache({ + max: 100, + ttl: 1000 * 60 * 15, // 15 minutes +}); + +export async function GET( + request: Request, + { params }: { params: { id: string } } +) { + try { + // 1. Get email ID from params + const { id } = params; + + // 2. Authentication check + const session = await getServerSession(authOptions); + if (!session?.user?.id) { + return NextResponse.json( + { error: 'Unauthorized' }, + { status: 401 } + ); + } + + // 3. Check cache first + const cacheKey = `email:${session.user.id}:${id}`; + const cachedEmail = emailContentCache.get(cacheKey); + if (cachedEmail) { + return NextResponse.json(cachedEmail); + } + + // 4. 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 } + ); + } + + // 5. Get the current folder from the request URL + const url = new URL(request.url); + const folder = url.searchParams.get('folder') || 'INBOX'; + + // 6. Create IMAP client + 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 + }, + disableAutoIdle: true + }); + + try { + await client.connect(); + + // 7. Open the folder + await client.mailboxOpen(folder); + + // 8. Fetch the email with UID + const options = { + uid: true, // This is crucial - we must specify uid:true to fetch by UID + source: true, + envelope: true, + bodyStructure: true, + flags: true + }; + + // Fetch by UID + const message = await client.fetchOne(id, options); + + if (!message) { + return NextResponse.json( + { error: 'Email not found' }, + { status: 404 } + ); + } + + // 9. Parse the email content + const parsedEmail = await parseEmail(message.source.toString()); + + // 10. Prepare the full email object with all needed data + const fullEmail = { + id: message.uid.toString(), + from: message.envelope.from?.[0]?.address || '', + fromName: message.envelope.from?.[0]?.name || + message.envelope.from?.[0]?.address?.split('@')[0] || '', + to: message.envelope.to?.map((addr: any) => addr.address).join(', ') || '', + subject: message.envelope.subject || '(No subject)', + date: message.envelope.date?.toISOString() || new Date().toISOString(), + content: parsedEmail.html || parsedEmail.text || '', + textContent: parsedEmail.text || '', + read: message.flags.has('\\Seen'), + starred: message.flags.has('\\Flagged'), + folder: folder, + hasAttachments: message.bodyStructure?.type === 'multipart', + attachments: parsedEmail.attachments || [], + flags: Array.from(message.flags), + headers: parsedEmail.headers || {} + }; + + // 11. Mark as read if not already + if (!message.flags.has('\\Seen')) { + await client.messageFlagsAdd(id, ['\\Seen'], { uid: true }); + } + + // 12. Cache the email content + emailContentCache.set(cacheKey, fullEmail); + + // 13. Return the full email + return NextResponse.json(fullEmail); + } finally { + // 14. Close the connection + try { + await client.logout(); + } catch (e) { + console.error('Error during IMAP logout:', e); + } + } + } catch (error) { + console.error('Error fetching email:', error); + return NextResponse.json( + { error: 'Failed to fetch email' }, + { status: 500 } + ); + } +} \ No newline at end of file