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 index = parseInt(url.searchParams.get('index') || '0'); 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 }, { uid: true }); if (!msg?.source) return json({ error: 'Message not found' }, 404); const parsed = await simpleParser(msg.source); const att = parsed.attachments?.[index]; if (!att) return json({ error: 'Attachment not found' }, 404); return new Response(att.content, { headers: { 'Content-Type': att.contentType || 'application/octet-stream', 'Content-Disposition': `attachment; filename*=UTF-8''${encodeURIComponent(att.filename || 'download')}`, 'Content-Length': String(att.content.length), }, }); } 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' } }); }