Przejdź do głównej zawartości

Node.js (@frontmail/node)

@frontmail/node jest przeznaczony dla serwerów, funkcji serverless i skryptów. Uwierzytelnia się kluczem prywatnym, więc nie obowiązują go sprawdzenia originu ani Turnstile, a do tego udostępnia wysyłki zbiorcze, historię i schematy szablonów.

Okno terminala
npm install @frontmail/node

Wymaga Node.js 20+ (korzysta z wbudowanego fetch). Działa też w Bunie, Deno i środowiskach edge, które udostępniają fetch.

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'
});

Bez privateKey klient odczytuje FRONTMAIL_PRIVATE_KEY (oraz FRONTMAIL_API_URL) ze zmiennych środowiskowych. Nigdy nie umieszczaj klucza prywatnego w bundlu dla przeglądarki – trzymaj go w zmiennych środowiskowych albo w menedżerze sekretów. Zobacz Klucze publiczne i prywatne.

Pakiet odmawia działania w przeglądarce: przy imporcie wypisuje ostrzeżenie, a new Frontmail() rzuca private_key_in_browser (można to wyłączyć opcją dangerouslyAllowPrivateKeyInBrowser: true, ale tylko dla wewnętrznych narzędzi na zaufanych komputerach). W przeglądarce używaj @frontmail/browser z kluczem publicznym.

const result = await frontmail.send({
serviceId: 'svc_01J9…', // opcjonalne – bez niego zostanie użyta domyślna usługa
templateId: 'tpl_order',
params: {
order_id: 'A-1042',
items: [{ title: 'Pokój', qty: 2, price: 89 }],
total: 178,
currency: 'EUR',
},
});
console.log(result.messageId, result.status); // 'queued' | 'held'

Inne pola wejściowe: idempotencyKey (zalecany, gdy wysyłkę wyzwala coś, co może się powtórzyć, np. webhook – użyj ID jego zdarzenia), attachments, locale, signal.

locale (np. 'de') wysyła e-mail w tym języku szablonu – najpierw dokładne dopasowanie, potem ten sam język bazowy (de-AT → de), w przeciwnym razie język domyślny. result.locale to użyty język:

const { locale } = await frontmail.send({ templateId: 'tpl_order', params: { order_id: 'A-1042' }, locale: user.language });

Wyślij do 100 wiadomości w jednym żądaniu. Każda wiadomość jest walidowana i rozliczana osobno – jedna nieprawidłowa wiadomość nie psuje pozostałych. sendBatch nie rzuca wyjątku z powodu błędów poszczególnych wiadomości; sprawdzaj ok w każdym wyniku.

const results = await frontmail.sendBatch([
{ serviceId: 'svc_01J9…', templateId: 'tpl_reminder', params: { name: 'Jana' }, idempotencyKey: 'reminder-42-jana' },
{ serviceId: 'svc_01J9…', templateId: 'tpl_reminder', params: { name: 'Petr' }, idempotencyKey: 'reminder-42-petr' },
]);
for (const r of results) {
if (!r.ok) console.error(r.index, r.error.code);
else console.log(r.index, r.messageId, r.status);
}

Do rate limitów paczka liczy się jako jedno żądanie. Więcej niż 100 wiadomości podziel na kilka paczek. Każda wiadomość może mieć własne locale; udane wyniki zawierają użyte locale.

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);
// Następna strona
if (page.nextCursor) await frontmail.history({ cursor: page.nextCursor });
// Albo przejdź przez wszystko
for await (const m of frontmail.history({ status: 'bounced' })) console.log(m.to);

Filtry: status, templateId, serviceId, from, to, q (wyszukiwanie po odbiorcy), limit (≤ 100), cursor. await history() zwraca jedną stronę; for await leniwie przechodzi przez wszystkie strony. Historia obejmuje okres przechowywania danych w twoim planie.

const msg = await frontmail.getMessage('msg_01J9Z3K7Q2');
// { messageId, status, createdAt, sentAt, templateId, serviceId, events: [{ type, at }, …] }
const templates = await frontmail.templates.list(); // schematy parametrów, używa ich `frontmail types`
const contact = await frontmail.templates.get('tpl_contact');
contact.locales; // ['en', 'de', 'pt-BR'] – najpierw język domyślny, potem tłumaczenia

frontmail types dopisuje języki każdego szablonu do jego komentarza dokumentacyjnego i generuje typ unii dla opcji 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";

Pakiet zawiera CLI frontmail – zobacz Typowane parametry.

Przykładowy projekt: examples/node.