Neah/app/api/mail/mark-read/route.ts
2025-04-17 11:39:15 +02:00

155 lines
4.5 KiB
TypeScript

import { NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import Imap from 'imap';
interface StoredCredentials {
email: string;
password: string;
host: string;
port: number;
}
function getStoredCredentials(): StoredCredentials | null {
const cookieStore = cookies();
const credentialsCookie = cookieStore.get('imap_credentials');
if (!credentialsCookie?.value) {
return null;
}
try {
const credentials = JSON.parse(credentialsCookie.value);
if (!credentials.email || !credentials.password || !credentials.host || !credentials.port) {
return null;
}
return credentials;
} catch (error) {
return null;
}
}
export async function POST(request: Request) {
try {
const { emailId, isRead } = await request.json();
if (!emailId || typeof isRead !== 'boolean') {
return NextResponse.json(
{ error: 'Invalid request parameters' },
{ status: 400 }
);
}
// Get the current folder from the request URL
const url = new URL(request.url);
const folder = url.searchParams.get('folder') || 'INBOX';
// Get stored credentials
const credentials = getStoredCredentials();
if (!credentials) {
return NextResponse.json(
{ error: 'No stored credentials found' },
{ status: 401 }
);
}
return new Promise((resolve) => {
const imap = new Imap({
user: credentials.email,
password: credentials.password,
host: credentials.host,
port: credentials.port,
tls: true,
tlsOptions: { rejectUnauthorized: false },
authTimeout: 30000,
connTimeout: 30000
});
const timeout = setTimeout(() => {
console.error('IMAP connection timeout');
imap.end();
resolve(NextResponse.json({ error: 'Connection timeout' }));
}, 30000);
imap.once('error', (err: Error) => {
console.error('IMAP error:', err);
clearTimeout(timeout);
resolve(NextResponse.json({ error: 'IMAP connection error' }));
});
imap.once('ready', () => {
imap.openBox(folder, false, (err, box) => {
if (err) {
console.error(`Error opening box ${folder}:`, err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ error: `Failed to open folder ${folder}` }));
return;
}
// Convert string ID to number
const numericId = parseInt(emailId, 10);
const fetch = imap.fetch(numericId.toString(), {
bodies: '',
struct: true
});
fetch.on('message', (msg) => {
msg.once('attributes', (attrs) => {
const uid = attrs.uid;
if (!uid) {
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ error: 'No UID found for email' }));
return;
}
if (isRead) {
imap.addFlags(uid, ['\\Seen'], (err) => {
if (err) {
console.error('Error marking as read:', err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ error: 'Failed to mark as read' }));
return;
}
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ success: true }));
});
} else {
imap.removeFlags(uid, ['\\Seen'], (err) => {
if (err) {
console.error('Error marking as unread:', err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ error: 'Failed to mark as unread' }));
return;
}
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ success: true }));
});
}
});
});
fetch.on('error', (err) => {
console.error('Error fetching email:', err);
clearTimeout(timeout);
imap.end();
resolve(NextResponse.json({ error: 'Failed to fetch email' }));
});
});
});
imap.connect();
});
} catch (error) {
console.error('Error marking email as read:', error);
return NextResponse.json(
{ error: 'Failed to mark email as read' },
{ status: 500 }
);
}
}