Node.js (@frontmail/node)
@frontmail/node è pensato per server, funzioni serverless e script. Si autentica con una
chiave privata, quindi i controlli sull’origine e Turnstile non si applicano, e sblocca gli
invii in batch, la cronologia e gli schemi dei modelli.
npm install @frontmail/nodeRichiede Node.js 20+ (usa il fetch integrato). Funziona anche in Bun, Deno e nei runtime edge che
forniscono fetch.
Creare un client
Sezione intitolata “Creare un client”import { Frontmail } from '@frontmail/node';
const frontmail = new Frontmail({ privateKey: process.env.FRONTMAIL_PRIVATE_KEY!, // sk_… // retry: { retries: 3 }, timeoutMs: 15_000, apiUrl: 'https://api.frontmail.dev'});Senza privateKey, il client legge FRONTMAIL_PRIVATE_KEY (e FRONTMAIL_API_URL) dall’ambiente.
Non esporre mai la chiave privata in un bundle per il browser – tienila nelle variabili d’ambiente
o in un secret manager. Vedi Chiavi pubbliche e private.
Il pacchetto si rifiuta di funzionare in un browser web: importarlo lì registra un avviso e
new Frontmail() lancia private_key_in_browser (puoi disattivare il controllo con
dangerouslyAllowPrivateKeyInBrowser: true solo per strumenti interni su macchine fidate). Nel
browser usa @frontmail/browser con la chiave pubblica.
const result = await frontmail.send({ serviceId: 'svc_01J9…', // facoltativo – se lo ometti viene usato il servizio predefinito templateId: 'tpl_order', params: { order_id: 'A-1042', items: [{ title: 'Camera', qty: 2, price: 89 }], total: 178, currency: 'EUR', },});console.log(result.messageId, result.status); // 'queued' | 'held'Altri campi di input: idempotencyKey (consigliato quando l’invio è attivato da qualcosa che può
ripetersi, ad es. un webhook – usa il suo ID evento), attachments, locale, signal.
locale (ad es. 'de') invia l’email in quella lingua del modello –
corrispondenza esatta, poi la stessa lingua di base (de-AT → de), altrimenti la lingua
predefinita. result.locale è la lingua usata:
const { locale } = await frontmail.send({ templateId: 'tpl_order', params: { order_id: 'A-1042' }, locale: user.language });Invio in batch
Sezione intitolata “Invio in batch”Invia fino a 100 messaggi in una sola richiesta. Ogni messaggio viene validato e addebitato
separatamente: un messaggio non valido non fa fallire gli altri. sendBatch non lancia eccezioni
per gli errori dei singoli messaggi; controlla ok in ogni risultato.
const results = await frontmail.sendBatch([ { serviceId: 'svc_01J9…', templateId: 'tpl_reminder', params: { name: 'Giulia' }, idempotencyKey: 'reminder-42-giulia' }, { serviceId: 'svc_01J9…', templateId: 'tpl_reminder', params: { name: 'Marco' }, idempotencyKey: 'reminder-42-marco' },]);
for (const r of results) { if (!r.ok) console.error(r.index, r.error.code); else console.log(r.index, r.messageId, r.status);}Un batch conta come una sola richiesta per i rate limit. Per più di
100 messaggi, dividili in blocchi. Ogni messaggio può avere il suo locale; i risultati riusciti
includono il locale usato.
Cronologia
Sezione intitolata “Cronologia”const page = await frontmail.history({ status: 'failed', templateId: 'tpl_order', from: '2026-09-01T00:00:00Z', limit: 50,});
for (const m of page.items) console.log(m.messageId, m.status, m.to, m.subject);
// Pagina successivaif (page.nextCursor) await frontmail.history({ cursor: page.nextCursor });
// Oppure scorri tuttofor await (const m of frontmail.history({ status: 'bounced' })) console.log(m.to);Filtri: status, templateId, serviceId, from, to, q (ricerca per destinatario), limit
(≤ 100), cursor. Con await history() ottieni una pagina; for await scorre tutte le pagine in
modo lazy. La cronologia copre il periodo di conservazione del tuo piano.
Stato del messaggio
Sezione intitolata “Stato del messaggio”const msg = await frontmail.getMessage('msg_01J9Z3K7Q2');// { messageId, status, createdAt, sentAt, templateId, serviceId, events: [{ type, at }, …] }Modelli
Sezione intitolata “Modelli”const templates = await frontmail.templates.list(); // schemi dei parametri, usati da `frontmail types`const contact = await frontmail.templates.get('tpl_contact');contact.locales; // ['en', 'de', 'pt-BR'] – prima la lingua predefinita, poi le traduzionifrontmail types aggiunge le lingue di ogni modello al suo commento di documentazione e genera un
tipo unione per l’opzione locale:
/** Contact form (tpl_contact) – languages: en (default), de, pt-BR */export interface ContactFormParams { /* … */ }/** Languages of tpl_contact (default first) – for the `locale` send option. */export type ContactFormLocale = "en" | "de" | "pt-BR";Il pacchetto include la CLI frontmail – vedi Parametri tipizzati.
Progetto di esempio: examples/node.