Transaktions-E-Mail (für Integratoren)

Zuletzt aktualisiert: Aug 31, 2026Abschnitt: Integrationen

Senden Sie eine ausgehende E-Mail pro Empfänger von einer FORM- oder CONTACT_FORM-Integration unter Verwendung des outboundMail-SMTP dieser Integration. Der Aufruf erfolgt Server-zu-Server mit X-API-Key und der Berechtigung ``transactional.send``.

Dies ist kein zustandsloses SMTP-Relay. Mailoo erstellt einen vollständigen Versand-Lifecycle innerhalb der Integration: TransactionalSend, Message (OUTBOUND), optionaler Subscriber-Sync, Open/Click-Tracking und optionale Delivery-Webhooks. Siehe outbound-smtp{.interpreted-text role="doc"} für die Abgrenzung zur Offenlegung von SMTP-Zugangsdaten an Integratoren.

Verwandt: SMTP-Ebene --- outbound-smtp{.interpreted-text role="doc"}; Abmelde-Tokens --- website-forms{.interpreted-text role="doc"}; OpenAPI --- https://api.mailoo.app/docs/v1.

Architektur

  • Auslöser, kein Relay: Ihr Backend ruft Mailoo auf; Mailoo rendert die Nachricht, speichert Datensätze und versendet über ``integration.config.outboundMail`` (dasselbe SMTP wie Dashboard-Antworten und Willkommensmails).
  • Zugangsdaten: Verwenden Sie ``X-API-Key`` mit ``transactional.send`` (oder FULL) ausschließlich von Ihrem Server oder BFF --- niemals in Browser-Bundles.
  • Idempotenz: Jede Anfrage erfordert ``idempotencyKey`` (max. 256 Zeichen, eindeutig pro Integration). Erster Erfolg gibt 201 zurück; Wiederholungen geben 200 mit idempotentReplay: true zurück.
  • Abonnenten: Mailoo erstellt oder aktualisiert einen Subscriber für die Empfänger-E-Mail. Wenn unsubscribedAt gesetzt ist, wird der Versand übersprungen (409, Status SKIPPED_UNSUBSCRIBED).
  • Zustellungsereignisse: Optionale ausgehende Webhooks (delivered, opened, clicked, unsubscribed, bounced) mit HMAC-Signierung und Wiederholungen --- siehe Delivery-Webhooks unten.

Versand-Endpunkt

``POST {baseUrl}/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send``

Header: Content-Type: application/json, X-API-Key (Berechtigung ``transactional.send`` oder FULL)

Body (JSON):

  • ``idempotencyKey`` (erforderlich) --- stabiler Schlüssel für diesen logischen Versand (z. B. daily-2026-06-20-user123)
  • ``to`` (erforderlich) --- Empfänger-E-Mail
  • ``name`` (optional) --- Anzeigename; wird für {{User.name}} / {{firstName}} verwendet
  • ``templateId`` (optional) --- Kampagnen-ID (Dashboard-Kampagne dieser Integration); verwenden Sie entweder templateId oder Inline-subject + text/html
  • ``vars`` (optional) --- Objekt mit String-/Zahlen-/Boolean-Mustache-Variablen (siehe unten)
  • ``subject``, ``text``, ``html`` (optional) --- Inline-Inhalt ohne templateId; Subject und mindestens text oder html sind für Inline-Versand erforderlich

Antworten:

  • 201 --- E-Mail gesendet (status: SENT, idempotentReplay: false)
  • 200 --- idempotente Wiederholung eines früheren Versands
  • 409 --- Empfänger abgemeldet (status: SKIPPED_UNSUBSCRIBED)
  • 502 --- SMTP-Versand fehlgeschlagen (status: FAILED; Message und BOUNCED-Delivery-Webhook können trotzdem aufgezeichnet werden)
  • 400 --- Validierungsfehler
  • 403 --- API-Schlüssel ohne ``transactional.send``
  • 404 --- Projekt/Integration nicht gefunden oder nicht FORM/CONTACT_FORM

Beispiel (Inline):

curl -X POST "https://api.mailoo.app/api/v1/webhooks/transactional/{projectUid}/{integrationId}/send" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: mai_live_..." \
  -d '{
    "idempotencyKey": "daily-2026-06-20-user1",
    "to": "user@example.com",
    "name": "Jane Doe",
    "subject": "Hi {{firstName}}",
    "html": "<p>{{affirmationText}} <a href=\"{{writeUrl}}\">Write</a></p><p><a href=\"{{unsubLink}}\">Unsubscribe</a></p>",
    "vars": {
      "affirmationText": "You are enough.",
      "writeUrl": "https://app.example.com/write"
    }
  }'

Beispielantwort (201):

{
  "success": true,
  "data": {
    "sendId": "clx...",
    "messageId": "clx...",
    "status": "SENT",
    "idempotentReplay": false
  }
}

Mustache-Variablen

Vorlagen (Kampagnen-templateId oder Inline-subject/text/html) werden vor dem SMTP-Versand mit Mustache gerendert.

Eingebauter Kontext:

  • ``User.email``, ``User.name`` --- aus to / name
  • ``firstName`` --- aus vars.firstName oder erstes Token von name
  • ``unsubLink`` --- Ein-Klick-Abmelde-URL (integrations-eigenes Signier-Secret + API-``MAILOO_PUBLIC_APP_URL``)
  • ``affirmationText``, ``writeUrl``, ``streak`` --- aus vars, wenn angegeben (üblich für Retention-/Nudge-Flows)

Zusätzliche String-/Zahlen-/Boolean-Schlüssel in vars werden in den Kontext eingefügt.

Open- und Click-Tracking

Wenn der HTML-Body nicht leer ist, fügt Mailoo ein:

  • Ein 1×1-Open-Tracking-Pixel
  • Umgeschriebene https://- (und //-)Links über Click-Tracking-Redirects

Öffentliche Routen (kein API-Schlüssel):

  • ``GET /api/v1/public/transactional/open/{trackingToken}`` --- gibt transparentes GIF zurück; zeichnet erstes Öffnen auf
  • ``GET /api/v1/public/transactional/click/{trackingToken}?u={urlencodedTarget}`` --- zeichnet Klick auf, 302-Redirect zum Ziel

Setzen Sie ``MAILOO_PUBLIC_API_URL`` auf dem API-Host, damit Pixel- und Klick-URLs auf Ihre öffentliche API zeigen. Setzen Sie ``MAILOO_PUBLIC_APP_URL``, wenn Abmelde- und App-Links auf den Dashboard-Origin zeigen müssen.

Delivery-Webhooks

Wenn konfiguriert, sendet Mailoo JSON-Ereignisse per POST an Ihren Benachrichtigungs-Endpunkt.

Konfiguration (pro Integration):

integration.config.deliveryWebhook.url und .secret --- im Dashboard (Delivery webhooks auf dem Setup-Reiter der Integration) oder über PATCH …/integrations/{id} mit deliveryWebhook setzen.

Ereignisse: delivered (nach erfolgreichem SMTP), opened, clicked, unsubscribed (nach Abmelde-Webhook), bounced (SMTP-Fehler).

Nutzlastform (JSON):

{
  "event": "delivered",
  "integrationId": "...",
  "messageId": "...",
  "idempotencyKey": "...",
  "recipientEmail": "user@example.com",
  "timestamp": "2026-06-20T12:00:00.000Z",
  "metadata": {}
}

Signierung: Header ``X-Mailoo-Signature: t={unixSeconds},v1={hex}``, wobei v1 HMAC-SHA256 von "{timestamp}.{rawBody}" mit dem Webhook-Secret ist. Header ``X-Mailoo-Event`` wiederholt den Enum-Namen (z. B. DELIVERED).

Wiederholungen: Outbox-Worker (10-Sekunden-Intervall im API-Prozess) wiederholt fehlgeschlagene Zustellungen bis zu 8 Versuche mit exponentiellem Backoff (max. 5 Minuten). Setzen Sie ``DISABLE_DELIVERY_WEBHOOK_WORKER=1`` nur für Tests oder wenn Sie einen separaten Prozessor betreiben.

Voraussetzungen

  • FORM- oder CONTACT_FORM-Integration mit ACTIVE-Status
  • ``outboundMail`` konfiguriert (Dashboard → Connection & settings → Outbound email)
  • ``MAIL_SMTP_ENCRYPTION_KEY`` auf der API, wenn SMTP-Passwort oder Abmelde-Secret verschlüsselt gespeichert wird
  • RESTRICTED- oder FULL-API-Schlüssel mit ``transactional.send``

Abmelde-Signierung

Jede FORM-/CONTACT_FORM-Integration speichert ein verschlüsseltes Abmelde-HMAC-Secret in integration.config. Mailoo generiert {{unsubLink}} automatisch in Transaktionsvorlagen. Eigentümer können das Secret im Dashboard rotieren (macht Links in bereits gesendeten E-Mails ungültig). Externe Backends, die eigene Links signieren, benötigen den rotierten Klartext einmalig, oder sollten stattdessen ``POST /api/v1/webhooks/unsubscribe`` mit einem API-Schlüssel aufrufen.