/* * NOTE: This endpoint is now mostly for backward compatibility. * The main email list API (/api/courrier) now fetches full email content, * so individual email fetching is typically not needed. * This is kept for cases where individual email access is still required * or when using older client code. */ 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 { simpleParser } from 'mailparser'; // Simple in-memory cache for email content const emailContentCache = new Map(); export async function GET( request: Request, { params }: { params: { id: string } } ) { try { const session = await getServerSession(authOptions); if (!session || !session.user?.id) { return NextResponse.json( { error: "Not authenticated" }, { status: 401 } ); } const { id } = params; if (!id) { return NextResponse.json( { error: "Missing email ID" }, { status: 400 } ); } // Get mail credentials const credentials = await prisma.mailCredentials.findUnique({ where: { userId: session.user.id, }, }); if (!credentials) { return NextResponse.json( { error: "No mail credentials found" }, { status: 404 } ); } const { searchParams } = new URL(request.url); const folder = searchParams.get("folder") || "INBOX"; // Create IMAP client let imapClient: any = null; try { imapClient = new ImapFlow({ host: credentials.host, port: credentials.port, secure: true, auth: { user: credentials.email, pass: credentials.password, }, logger: false, }); await imapClient.connect(); console.log(`Connected to IMAP server to fetch full email ${id}`); // Select mailbox const mailboxData = await imapClient.mailboxOpen(folder); console.log(`Opened mailbox ${folder} to fetch email ${id}`); // Fetch the complete email with its source const message = await imapClient.fetchOne(Number(id), { source: true, envelope: true }); if (!message) { return NextResponse.json( { error: "Email not found" }, { status: 404 } ); } const { source, envelope } = message; // Parse the full email content const parsedEmail = await simpleParser(source.toString()); // Return only the content return NextResponse.json({ id, subject: envelope.subject, content: parsedEmail.html || parsedEmail.textAsHtml || parsedEmail.text || '', contentFetched: true }); } catch (error: any) { console.error("Error fetching email content:", error); return NextResponse.json( { error: "Failed to fetch email content", message: error.message }, { status: 500 } ); } finally { // Close the mailbox and connection if (imapClient) { try { await imapClient.mailboxClose(); await imapClient.logout(); } catch (e) { console.error("Error closing IMAP connection:", e); } } } } catch (error: any) { console.error("Error in GET:", error); return NextResponse.json( { error: "Internal server error", message: error.message }, { status: 500 } ); } } // Add a route to mark email as read export async function POST( request: Request, { params }: { params: { id: string } } ) { try { const session = await getServerSession(authOptions); if (!session || !session.user?.id) { return NextResponse.json( { error: "Not authenticated" }, { status: 401 } ); } const { id } = params; if (!id) { return NextResponse.json( { error: "Missing email ID" }, { status: 400 } ); } const { action } = await request.json(); if (action !== 'mark-read' && action !== 'mark-unread') { return NextResponse.json( { error: "Invalid action. Supported actions: mark-read, mark-unread" }, { status: 400 } ); } // Get mail credentials const credentials = await prisma.mailCredentials.findUnique({ where: { userId: session.user.id, }, }); if (!credentials) { return NextResponse.json( { error: "No mail credentials found" }, { status: 404 } ); } const { searchParams } = new URL(request.url); const folder = searchParams.get("folder") || "INBOX"; // Create IMAP client let imapClient: any = null; try { imapClient = new ImapFlow({ host: credentials.host, port: credentials.port, secure: true, auth: { user: credentials.email, pass: credentials.password, }, logger: false, }); await imapClient.connect(); // Select mailbox await imapClient.mailboxOpen(folder); // Set flag based on action if (action === 'mark-read') { await imapClient.messageFlagsAdd(Number(id), ['\\Seen']); } else { await imapClient.messageFlagsRemove(Number(id), ['\\Seen']); } return NextResponse.json({ success: true }); } catch (error: any) { console.error(`Error ${action === 'mark-read' ? 'marking email as read' : 'marking email as unread'}:`, error); return NextResponse.json( { error: `Failed to ${action === 'mark-read' ? 'mark email as read' : 'mark email as unread'}`, message: error.message }, { status: 500 } ); } finally { // Close the mailbox and connection if (imapClient) { try { await imapClient.mailboxClose(); await imapClient.logout(); } catch (e) { console.error("Error closing IMAP connection:", e); } } } } catch (error: any) { console.error("Error in POST:", error); return NextResponse.json( { error: "Internal server error", message: error.message }, { status: 500 } ); } }