131 lines
3.7 KiB
TypeScript
131 lines
3.7 KiB
TypeScript
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';
|
|
|
|
// Get the email list cache from main API route
|
|
// This is a hack - ideally we'd use a shared module or Redis for caching
|
|
declare global {
|
|
var emailListCache: { [key: string]: { data: any, timestamp: number } };
|
|
}
|
|
|
|
// Helper function to invalidate cache for a specific folder
|
|
const invalidateCache = (userId: string, folder?: string) => {
|
|
if (!global.emailListCache) return;
|
|
|
|
Object.keys(global.emailListCache).forEach(key => {
|
|
// If folder is provided, only invalidate that folder's cache
|
|
if (folder) {
|
|
if (key.includes(`${userId}:${folder}`)) {
|
|
delete global.emailListCache[key];
|
|
}
|
|
} else {
|
|
// Otherwise invalidate all user's caches
|
|
if (key.startsWith(`${userId}:`)) {
|
|
delete global.emailListCache[key];
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
// Mark email as read
|
|
export async function POST(
|
|
request: Request,
|
|
{ params }: { params: { id: string } }
|
|
) {
|
|
try {
|
|
// Get session
|
|
const session = await getServerSession(authOptions);
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
}
|
|
|
|
// Properly await the params object before accessing its properties
|
|
const { id: emailId } = await Promise.resolve(params);
|
|
if (!emailId) {
|
|
return NextResponse.json({ error: 'Email ID is required' }, { status: 400 });
|
|
}
|
|
|
|
// 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' }, { 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();
|
|
|
|
// Find which folder contains this email
|
|
const mailboxes = await client.list();
|
|
let emailFolder = 'INBOX'; // Default to INBOX
|
|
let foundEmail = false;
|
|
|
|
// Search through folders to find the email
|
|
for (const box of mailboxes) {
|
|
try {
|
|
await client.mailboxOpen(box.path);
|
|
|
|
// Search for the email by UID
|
|
const message = await client.fetchOne(emailId, { flags: true });
|
|
if (message) {
|
|
emailFolder = box.path;
|
|
foundEmail = true;
|
|
|
|
// Mark as read if not already
|
|
if (!message.flags.has('\\Seen')) {
|
|
await client.messageFlagsAdd(emailId, ['\\Seen']);
|
|
}
|
|
break;
|
|
}
|
|
} catch (error) {
|
|
console.log(`Error searching in folder ${box.path}:`, error);
|
|
// Continue with next folder
|
|
}
|
|
}
|
|
|
|
if (!foundEmail) {
|
|
return NextResponse.json(
|
|
{ error: 'Email not found' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
// Invalidate the cache for this folder
|
|
invalidateCache(session.user.id, emailFolder);
|
|
|
|
return NextResponse.json({ success: true });
|
|
} finally {
|
|
try {
|
|
await client.logout();
|
|
} catch (e) {
|
|
console.error('Error during logout:', e);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Error marking email as read:', error);
|
|
return NextResponse.json(
|
|
{ error: 'Failed to mark email as read' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|