Zum Inhalt springen

Vanilla JavaScript (@frontmail/browser)

@frontmail/browser ist ein winziges (< 3,5 kB gzip), abhängigkeitsfreies SDK für jede Website. Seine API entspricht @emailjs/browser, bestehender Code braucht also nur wenige Änderungen.

Terminal-Fenster
npm install @frontmail/browser
import { init, send, sendForm, getStatus } from '@frontmail/browser';

Einmal aufrufen, vor dem ersten Versand:

init({
publicKey: 'pk_4f2a…',
blockHeadless: true, // optional, siehe Bot-Schutz
blockList: { list: ['spam@example.net'], watchVariable: 'email' },
limitRate: { id: 'contact', throttle: 10_000 }, // höchstens ein Versand pro 10 s
retry: { retries: 3, baseDelayMs: 300 }, // Standard; `false` schaltet Wiederholungen ab
timeoutMs: 15_000, // pro Versuch
apiUrl: 'https://api.frontmail.dev', // Standard
});

init('pk_4f2a…') nur mit dem Schlüssel als String funktioniert ebenfalls.

const result = await send('svc_01J9…', 'tpl_order', {
name: 'Jana',
items: [{ title: 'Zimmer', qty: 2, price: 89 }],
});
// { messageId: 'msg_…', status: 'queued' | 'held', statusToken: '…', status_code: 202, text: 'OK' }
  • serviceId darf null sein, dann wird der Standarddienst der Organisation verwendet.
  • params werden auf dem Server gegen das Schema der Vorlage validiert.
  • options akzeptiert turnstileToken, attachments, idempotencyKey, locale, signal (AbortSignal), einen publicKey pro Aufruf und Schutzfunktionen pro Aufruf (blockHeadless, blockList, limitRate). Ein einfacher String wird wie bei EmailJS als öffentlicher Schlüssel behandelt.
  • locale (z. B. 'de') wählt eine Sprache der Vorlage; eine unbekannte Sprache fällt auf dieselbe Basissprache zurück, danach auf die Standardsprache. result.locale ist die Sprache, in der die E-Mail versendet wurde.

Das Promise wird sowohl bei queued als auch bei held erfüllt – eine zurückgehaltene Nachricht ist angenommen und wird gesendet, sobald Credits verfügbar sind (siehe Warteschlange zurückgehaltener E-Mails). Andernfalls wird es mit einem typisierten Fehler abgelehnt (siehe Fehlerbehandlung).

<form id="contact">
<input name="name" required>
<input name="email" type="email" required>
<textarea name="message"></textarea>
<input type="file" name="attachment">
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></div>
<button>Senden</button>
</form>
<script type="module">
import { init, sendForm } from '@frontmail/browser';
init({ publicKey: 'pk_4f2a…' });
document.getElementById('contact').addEventListener('submit', async (event) => {
event.preventDefault();
const { status } = await sendForm('svc_01J9…', 'tpl_contact', event.target);
// oder: sendForm('svc_01J9…', 'tpl_contact', '#contact')
});
</script>

Das Formular wird als multipart/form-data gesendet. Textfelder werden zu Parametern (umgewandelt in die deklarierten Typen), Dateifelder zu Anhängen, und ein Turnstile-Token in cf-turnstile-response wird automatisch übernommen. Verwenden Sie den Site-Key Ihres eigenen Turnstile-Widgets – siehe Cloudflare Turnstile.

Felder, die Ihre Website nicht verlassen dürfen, werden übersprungen: Passwortfelder (type="password"), die Anti-CSRF-Felder gängiger Frameworks (csrfmiddlewaretoken, _token, authenticity_token, __RequestVerificationToken, _csrf, csrf_token) und reservierte API-Namen (accessToken, privateKey, turnstile_key, …). Mit formFields wählen Sie die Felder selbst aus:

await sendForm('svc_01J9…', 'tpl_contact', '#contact', {
formFields: { include: ['name', 'email', 'message'] }, // nur diese (+ Turnstile-Token)
// oder: formFields: { exclude: ['internal_note'] }
});

Um das Formular in einer Sprache der Vorlage zu senden, übergeben Sie { locale: 'de' } – es wird als reserviertes Feld fm_locale gesendet – oder fügen Sie dem Formular selbst ein Feld fm_locale hinzu (z. B. eine Sprachauswahl <select name="fm_locale">); das Feld des Formulars hat Vorrang. Ein Feld namens locale bleibt ein gewöhnlicher Vorlagenparameter.

const status = await getStatus(result.messageId, { token: result.statusToken });
// { messageId, status: 'sent', createdAt, sentAt, templateId, serviceId, events: [...] }

Mit einem öffentlichen Schlüssel können Sie nur selbst gesendete Nachrichten lesen, und zwar mit dem statusToken aus dem Sendeergebnis. Das SDK sendet ihn im Header X-Frontmail-Status-Token (nicht in der URL, damit er nicht in Logs landet). Siehe Nachrichtenstatus.

Ein <script>-Tag läuft mit vollem Zugriff auf Ihre Seite. Laden Sie eine exakte Version und lassen Sie den Browser deren Hash prüfen – so wird eine veränderte Datei (ein kompromittiertes CDN oder Release) abgelehnt statt ausgeführt:

<script
src="https://cdn.jsdelivr.net/npm/@frontmail/browser@0.1.0/dist/frontmail.umd.js"
integrity="sha384-g2Rxznkz2yb/YYSdVTkXLxZFZ2Nh2+XdhPStxh0stydXFF3gYjDuyHimWIZLJDCc"
crossorigin="anonymous"></script>
  • jsDelivr (npm): Den Hash jedes Releases finden Sie in den GitHub-Release-Notes (und über den Button „Copy HTML + SRI“ bei jsDelivr).
  • Frontmail-CDN: https://cdn.frontmail.dev/v<version>/frontmail.umd.js; der zugehörige Wert für integrity steht in https://cdn.frontmail.dev/v<version>/sri.json.
  • Aktualisieren Sie immer Version und Hash gemeinsam (siehe Changelog).

Wenn Ihre Website CSP verwendet, erlauben Sie:

connect-src https://api.frontmail.dev;
script-src https://cdn.jsdelivr.net https://challenges.cloudflare.com; # CDN-Build (oder cdn.frontmail.dev), Turnstile
frame-src https://challenges.cloudflare.com; # Turnstile