/** * GET /api/mail/lead-emails/attachment?leadId=&uid=&index= * Partner mode (admin roles): `partnerId=&address=` instead of `leadId`. * Download one attachment of an archived e-mail (mailpiler provider only — the * IMAP provider lists attachments without offering them). The message must * involve the lead's address. Staff only. */ import { gateFromEvent } from '../../../utils/chatAccess' import { fetchArchiveAttachment } from '../../../utils/mail/mailArchive' import { resolveMailTarget } from '../../../utils/mail/leadEmailAddress' export default defineEventHandler(async (event) => { const { token } = await gateFromEvent(event) const q = getQuery(event) const leadId = Number(q.leadId) || 0 const partnerId = Number(q.partnerId) || 0 const uid = Number(q.uid) || 0 const index = Number(q.index) if ((!leadId && !partnerId) || !uid || !Number.isInteger(index) || index < 0) throw createError({ statusCode: 400, statusMessage: 'Missing parameters' }) const { email } = await resolveMailTarget(event, q, token) if (!email) throw createError({ statusCode: 404, statusMessage: 'Not found' }) let upstream: Response try { upstream = await fetchArchiveAttachment(uid, index, email) } catch { throw createError({ statusCode: 502, statusMessage: 'Mail archive unavailable' }) } if (!upstream.ok || !upstream.body) throw createError({ statusCode: upstream.status === 404 ? 404 : 502, statusMessage: 'Attachment not available' }) for (const h of ['content-type', 'content-length', 'content-disposition']) { const v = upstream.headers.get(h) if (v) setResponseHeader(event, h, v) } setResponseHeader(event, 'cache-control', 'private, no-store') setResponseHeader(event, 'x-content-type-options', 'nosniff') return sendStream(event, upstream.body as any) })