export const prerender = false; import type { APIRoute } from 'astro'; import { ImapFlow } from 'imapflow'; import { simpleParser } from 'mailparser'; import { getAccount } from '../../../lib/mail-accounts'; export const GET: APIRoute = async ({ url }) => { const id = url.searchParams.get('account'); const uid = url.searchParams.get('uid'); const folder = url.searchParams.get('folder') || 'INBOX'; const acct = id ? getAccount(id) : undefined; if (!acct || !uid) return json({ error: 'Bad request' }, 400); const client = new ImapFlow({ host: acct.imap.host, port: acct.imap.port, secure: true, auth: { user: acct.imap.user, pass: acct.imap.password }, logger: false, }); try { await client.connect(); const lock = await client.getMailboxLock(folder); try { const msg = await client.fetchOne(uid, { source: true, flags: true }, { uid: true }); if (!msg?.source) return json({ error: 'Message not found' }, 404); await client.messageFlagsAdd(uid, ['\\Seen'], { uid: true }).catch(() => {}); const parsed = await simpleParser(msg.source); return json({ uid: msg.uid, subject: parsed.subject || '(no subject)', from: parsed.from?.text || '', to: parsed.to ? (Array.isArray(parsed.to) ? parsed.to.map((a: any) => a.text).join(', ') : (parsed.to as any).text) : '', cc: parsed.cc ? (Array.isArray(parsed.cc) ? parsed.cc.map((a: any) => a.text).join(', ') : (parsed.cc as any).text) : '', date: parsed.date?.toISOString() || null, html: parsed.html || null, text: parsed.text || '', messageId: parsed.messageId || null, attachments: (parsed.attachments || []).map((att: any, i: number) => ({ index: i, filename: att.filename || `attachment-${i}`, contentType: att.contentType || 'application/octet-stream', size: att.size || att.content?.length || 0, contentId: att.cid || null, })), }); } finally { lock.release(); } } catch (e: any) { return json({ error: e.message }, 500); } finally { await client.logout().catch(() => {}); } }; function json(data: object, status = 200) { return new Response(JSON.stringify(data), { status, headers: { 'Content-Type': 'application/json' } }); }