// Lightweight Postal API client // Sends messages via Postal /api/v1/send/message // Requires env: POSTAL_URL, POSTAL_API_KEY, POSTAL_FROM, optional POSTAL_FROM_NAME, POSTAL_REPLY_TO import dotenv from 'dotenv' dotenv.config() let _fetch = null async function getFetch() { if (typeof globalThis.fetch === 'function') return globalThis.fetch if (_fetch) return _fetch try { const mod = await import('node-fetch') _fetch = mod.default return _fetch } catch (e) { throw new Error('fetch is not available and node-fetch is not installed. Please install node-fetch or use Node 18+.') } } function ensureArray(v) { if (!v) return [] if (Array.isArray(v)) return v if (typeof v === 'string') return v.split(/[;,]/).map(s => s.trim()).filter(Boolean) return [String(v)] } function fmtFromAddress(email, name) { const e = String(email || '').trim() const n = String(name || '').trim() if (!e) return '' return n ? `${n} <${e}>` : e } export async function sendPostalEmail({ to, subject, text, html, cc = [], bcc = [] }) { const base = (process.env.POSTAL_URL || '').replace(/\/$/, '') const apiKey = process.env.POSTAL_API_KEY || '' const fromEmail = process.env.POSTAL_FROM || '' const fromName = process.env.POSTAL_FROM_NAME || '' const replyTo = process.env.POSTAL_REPLY_TO || '' if (!base || !apiKey || !fromEmail) { throw new Error('Postal configuration missing: POSTAL_URL, POSTAL_API_KEY, POSTAL_FROM are required') } const endpoint = `${base}/api/v1/send/message` const payload = { api_key: apiKey, from: fmtFromAddress(fromEmail, fromName), to: ensureArray(to), subject: subject || '', html_body: html || undefined, plain_body: text || undefined, } const ccArr = ensureArray(cc) const bccArr = ensureArray(bcc) if (ccArr.length) payload.cc = ccArr if (bccArr.length) payload.bcc = bccArr if (replyTo) payload.reply_to = replyTo const fetchImpl = await getFetch() const res = await fetchImpl(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }) let data try { data = await res.json() } catch (e) { throw new Error(`Postal response parse error: HTTP ${res.status}`) } if (!res.ok || data?.status !== 'success') { const errMsg = data?.data?.message || data?.message || JSON.stringify(data) throw new Error(`Postal send failed: ${errMsg}`) } return data }