How to handle transactional email in Webflow Cloud after Logic was discontinued

So handhaben Sie transaktionale E-Mails in Webflow Cloud, nachdem Logic eingestellt wurde

Erfahren Sie, wie Sie transaktionale E-Mails von jeder Webflow-Website mit Postmark und einem Webflow-Cloud-Route-Handler senden.

So handhaben Sie transaktionale E-Mails in Webflow Cloud, nachdem Logic eingestellt wurde

Table of contents

Seit Webflow Logic im Juni 2025 eingestellt wurde, erfordert das Senden einer echten transaktionalen E-Mail aus einem Webflow-Formular ein echtes Backend. Webflow Cloud macht dieses Backend zu einem Route Handler: ein paar Dutzend Zeilen TypeScript, die Postmarks API aufrufen und in dem Moment, in dem ein Formular abgeschickt wird, zwei E-Mails senden.

Transaktionale E-Mail ist eines der ersten Dinge, um die mich Kund:innen bitten, sobald eine Webflow-Website über eine reine Broschüre hinauswächst. Webflows integrierte Formularbenachrichtigungen werden an die Website-Inhaberin gesendet, ohne Kontrolle über Absenderadresse, Template oder Copy. Webflow Logic, das einen Teil dieser Automatisierung übernahm, wurde am 27. Juni 2025 eingestellt.

Der aktuelle Ansatz ist ein Route Handler einer Webflow-Cloud-App, der Formulardaten empfängt, Postmarks HTTP-API aufruft und markenkonforme E-Mails in beide Richtungen sendet: eine Bestätigung an die absendende Person und eine Benachrichtigung an Ihr Team.

In diesem Leitfaden behandeln wir jeden Schritt: das Verifizieren Ihrer Absender-Domain in Postmark, das Einrichten der Zugangsdaten, das Schreiben eines wiederverwendbaren E-Mail-Helpers, das Bauen des Route Handlers und dessen Verbindung mit einem Webflow-Formular über clientseitiges JavaScript.

Was brauchen Sie, um transaktionale E-Mails von Webflow Cloud zu senden?

Sie brauchen ein Postmark-Konto, eine verifizierte Absender-Domain und eine bereits aufgesetzte Webflow-Cloud-App, bevor Sie mit dem Code beginnen.

Stellen Sie sicher, dass diese Voraussetzungen erfüllt sind, bevor Sie beginnen:

  • Ein Postmark-Konto: Die kostenlose Stufe sendet 100 E-Mails pro Monat, was für Entwicklung und Produktion mit geringem Volumen ausreicht
  • Eine Domain, die Ihnen gehört, mit DNS-Zugriff: Postmark verlangt, dass Sie DNS-Einträge (DKIM + Return-Path) hinzufügen, um Ihre Absender-Domain zu verifizieren
  • EineWebflow-Cloud-App: Führen Sie webflow auth login && webflow cloud init aus, falls noch nicht geschehen.
  • Eine Webflow-Website mit mindestens einem Formular, das eine individuelle E-Mail-Behandlung benötigt

Eine Sache, die Sie vorher wissen sollten: Das offizielle postmark-npm-Paket funktioniert nicht auf Cloudflare Workers. Cloudflares eigene Dokumentation stellt das direkt fest: „Postmark's JavaScript library is currently not supported on Workers." Die HTTP-API funktioniert dagegen einwandfrei über fetch(). Genau die verwendet dieser Leitfaden.

5 Schritte, um transaktionale E-Mails von Webflow Cloud mit Postmark zu senden

Postmark übernimmt die Zustellung. Die Webflow-Cloud-App übernimmt Validierung, Routing und die Formung der Antwort. Diese Schritte bauen die Integration in folgender Reihenfolge auf: Verifizierung der Absender-Domain, Einrichtung der Zugangsdaten, ein wiederverwendbarer E-Mail-Helper und ein Route Handler, an den das Webflow-Formular sendet.

1. Verifizieren Sie Ihre Absender-Domain in Postmark

Postmark blockiert das Senden von unverifizierten Domains. Dieser Schritt kann nicht übersprungen werden, und er ist der mit Abstand häufigste Grund, warum der erste Versand fehlschlägt. Richten Sie ihn ein, bevor Sie Code schreiben.

Melden Sie sich bei Postmark an und navigieren Sie zu Sender Signatures → Add Domain or Signature → Add Domain. Geben Sie Ihre Domain ein und klicken Sie auf Verify Domain.

Postmark-Seite Sender Signatures mit hervorgehobener Schaltfläche Add Domain or Signature, einer bereits gelisteten Domain mit einem DNS-Settings-Link und einem Konto im Test-Modus

Postmark zeigt zwei DNS-Einträge an, die Sie hinzufügen müssen:

  • Ein DKIM-Eintrag (Typ TXT)
  • Ein Return-Path-Eintrag (Typ CNAME)

Fügen Sie beide Einträge bei Ihrem DNS-Anbieter hinzu. Navigieren Sie in Cloudflare zu DNS → Records → Add record und kopieren Sie jeden Wert exakt. Sobald die Einträge propagiert sind (bei Cloudflare typischerweise unter 10 Minuten), kehren Sie zu Postmark zurück und klicken Sie auf die Verify-Schaltflächen.

Sobald die Domain verifiziert ist, holen Sie sich Ihren Server-API-Token. Navigieren Sie zu Servers → My First Server → API Tokens und kopieren Sie den Server-Token. Dieser Wert wird bei jeder API-Anfrage im X-Postmark-Server-TokenAuthentifizierungsheader mitgegeben.

Checkpoint: Nutzen Sie im Postmark-Dashboard die Test-Schaltfläche, um eine Test-E-Mail zu senden. Wenn sie zugestellt wird, ist die Domain verifiziert und der Token funktioniert.

2. Fügen Sie die Postmark-Zugangsdaten zu Ihrer Webflow-Cloud-Umgebung hinzu

Ihre Cloud-App braucht zwei Umgebungsvariablen.

Fügen Sie diese für die lokale Entwicklung zu .env.local hinzu:

# .env.local
POSTMARK_SERVER_TOKEN=your_server_token_here
POSTMARK_FROM_EMAIL=hello@yourdomain.com
OWNER_EMAIL=you@yourdomain.com

Öffnen Sie in Ihren Webflow-Website-Einstellungen Webflow Cloud, wählen Sie Ihre Umgebung aus und fügen Sie dieselben Variablen unter Environment Variables hinzu.

Für lokale Tests ohne den Versand echter E-Mails stellt Postmark einen speziellen Test-Token bereit: POSTMARK_API_TEST. Tauschen Sie lokal Ihren echten Token gegen diesen Wert aus, um das Anfrageformat zu validieren, ohne eine tatsächliche Zustellung auszulösen.

Checkpoint: Führen Sie next dev lokal aus und bestätigen Sie, dass process.env.POSTMARK_SERVER_TOKEN zu Ihrem Token aufgelöst wird.

3. Erstellen Sie den Postmark-E-Mail-Helper

Erstellen Sie lib/postmark.ts in Ihrer Cloud-App. Dieses Modul übernimmt den HTTP-Aufruf an Postmarks /email-Endpoint und formt die Anfrage in das Format, das die API erwartet.

Hier ist, was Sie tun müssen:

// lib/postmark.ts

const POSTMARK_API = 'https://api.postmarkapp.com'

interface EmailParams {
  to: string
  from: string
  subject: string
  htmlBody: string
  textBody?: string
  replyTo?: string
  tag?: string
  messageStream?: string
}

interface PostmarkResponse {
  ErrorCode: number
  Message: string
  MessageID: string
  SubmittedAt: string
  To: string
}

export async function sendEmail(params: EmailParams): Promise<PostmarkResponse> {
  const token = process.env.POSTMARK_SERVER_TOKEN
  if (!token) throw new Error('POSTMARK_SERVER_TOKEN is not set')

  const res = await fetch(`${POSTMARK_API}/email`, {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-Postmark-Server-Token': token,
    },
    body: JSON.stringify({
      From: params.from,
      To: params.to,
      Subject: params.subject,
      HtmlBody: params.htmlBody,
      TextBody: params.textBody ?? params.htmlBody.replace(/<[^>]+>/g, ''),
      ReplyTo: params.replyTo,
      Tag: params.tag,
      TrackOpens: true,
      MessageStream: params.messageStream ?? 'outbound',
    }),
  })

  if (!res.ok) {
    const error = (await res.json()) as PostmarkResponse
    throw new Error(`Postmark error ${error.ErrorCode}: ${error.Message}`)
  }

  return res.json() as Promise<PostmarkResponse>
}

Ich halte den Postmark-Aufruf in einem dedizierten Helper statt inline im Route Handler. Wenn dieselbe App mehrere E-Mail-Typen sendet (Kontaktbestätigung, Bestellbeleg, Passwort-Reset), importiert jeder Route Handler sendEmail() mit seinen eigenen Parametern. Keine duplizierte Fetch-Logik über mehrere Dateien hinweg.

Der TextBody-Fallback entfernt automatisch HTML-Tags, um eine Plain-Text-Version zu erzeugen. Für die Produktion schreiben Sie einen richtigen Plain-Text-Body: E-Mail-Clients, die nur Text rendern (einschließlich vieler unternehmenseigener Spamfilter), erhalten damit eine bessere Erfahrung als mit entferntem HTML.

Checkpoint: Rufen Sie aus einem kurzen Testskript sendEmail() auf, wobei POSTMARK_SERVER_TOKEN auf POSTMARK_API_TEST gesetzt ist. Sie sollten { ErrorCode: 0, Message: "Test job accepted" } zurückerhalten.

4. Bauen Sie den Route Handler für das Kontaktformular

Erstellen Sie app/api/contact/route.ts. Dieser Route Handler empfängt eine JSON-Formularübermittlung, validiert die Eingabe, sendet zwei E-Mails über Postmark (eine Bestätigung an die absendende Person und eine Benachrichtigung an die Website-Inhaberin) und gibt eine JSON-Antwort zurück.

Hier ist der Inhalt:

// app/api/contact/route.ts
export const runtime = 'edge'

import { sendEmail } from '@/lib/postmark'

const SENDER = process.env.POSTMARK_FROM_EMAIL ?? 'hello@yourdomain.com'
const OWNER_EMAIL = process.env.OWNER_EMAIL ?? 'you@yourdomain.com'

interface ContactPayload {
  name: string
  email: string
  message: string
}

function isValidEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}

export async function POST(request: Request) {
  let body: ContactPayload

  try {
    body = (await request.json()) as ContactPayload
  } catch {
    return Response.json({ error: 'Invalid JSON' }, { status: 400 })
  }

  const { name, email, message } = body

  if (!name?.trim() || !email?.trim() || !message?.trim()) {
    return Response.json(
      { error: 'Name, email, and message are required' },
      { status: 422 }
    )
  }

  if (!isValidEmail(email)) {
    return Response.json({ error: 'Invalid email address' }, { status: 422 })
  }

  try {
    // Confirmation to the submitter
    const confirmation = await sendEmail({
      to: email,
      from: SENDER,
      replyTo: OWNER_EMAIL,
      subject: `Thanks for reaching out, ${name}`,
      tag: 'contact-confirmation',
      htmlBody: `
        <p>Hi ${name},</p>
        <p>Thanks for your message. I'll get back to you within one business day.</p>
        <p>Here's what you sent:</p>
        <blockquote>${message}</blockquote>
      `,
    })

    // Notification to the site owner
    await sendEmail({
      to: OWNER_EMAIL,
      from: SENDER,
      replyTo: email,
      subject: `New contact from ${name}`,
      tag: 'contact-notification',
      htmlBody: `
        <p><strong>Name:</strong> ${name}</p>
        <p><strong>Email:</strong> <a href="mailto:${email}">${email}</a></p>
        <p><strong>Message:</strong></p>
        <p>${message}</p>
      `,
    })

    return Response.json({
      success: true,
      messageId: confirmation.MessageID,
    })
  } catch (err) {
    console.error('Email send failed:', err)
    return Response.json({ error: 'Failed to send email' }, { status: 502 })
  }
}

Der Handler validiert, bevor er Postmark aufruft. Ein leerer Name oder eine fehlerhafte E-Mail-Adresse erreichen die API nie, was bedeutet: keine verschwendeten API-Aufrufe und keine verwirrenden 422-Antworten von Postmark, die geparst werden müssen.

Ich setze ReplyTo bei der Bestätigung auf die E-Mail-Adresse der Inhaberin und bei der Benachrichtigung auf die E-Mail-Adresse der absendenden Person. So erreicht die Website-Inhaberin die absendende Person direkt, wenn sie in ihrem E-Mail-Client auf Antworten klickt.

Checkpoint: Sie können den Endpoint mit cURL testen:

curl -X POST http://localhost:3000/app/api/contact \
  -H "Content-Type: application/json" \
  -d '{"name":"Test User","email":"test@example.com","message":"Hello"}'

Mit POSTMARK_SERVER_TOKEN=POSTMARK_API_TEST sollten Sie { "success": true, "messageId": "..." } erhalten. Mit Ihrem echten Token prüfen Sie das Postmark-Aktivitätsprotokoll, um zu bestätigen, dass beide E-Mails erscheinen.

5. Verbinden Sie das Webflow-Formular

Fügen Sie dies zu einem Custom-Code-Block (Before </body>) auf jeder Seite mit einem Kontaktformular hinzu. Das Formular braucht drei Eingabefelder mit den Attributen data-contact-name, data-contact-email und data-contact-message, sowie ein Status-Element mit data-contact-status.

Fügen Sie dem Formularelement selbst ein data-contact-form-Attribut hinzu:

(function () {
  const form = document.querySelector('[data-contact-form]')
  const status = document.querySelector('[data-contact-status]')

  if (!form) return

  form.addEventListener('submit', async function (e) {
    e.preventDefault()

    const name = form.querySelector('[data-contact-name]')?.value.trim()
    const email = form.querySelector('[data-contact-email]')?.value.trim()
    const message = form.querySelector('[data-contact-message]')?.value.trim()

    if (!name || !email || !message) {
      if (status) status.textContent = 'Please fill in all fields.'
      return
    }

    const submitBtn = form.querySelector('[type="submit"]')
    if (submitBtn) submitBtn.disabled = true
    if (status) status.textContent = 'Sending...'

    try {
      const res = await fetch('/app/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, email, message }),
      })

      const data = await res.json()

      if (data.success) {
        if (status) status.textContent = 'Message sent. Check your inbox for a confirmation.'
        form.reset()
      } else {
        if (status) status.textContent = data.error ?? 'Something went wrong. Please try again.'
      }
    } catch {
      if (status) status.textContent = 'Network error. Please try again.'
    } finally {
      if (submitBtn) submitBtn.disabled = false
    }
  })
})()

Ich deaktiviere die Submit-Schaltfläche, während die Anfrage läuft. Ohne das würden doppelte Übermittlungen zwei Bestätigungs-E-Mails an dieselbe Adresse senden. Das data-contact-status-Element gibt Nutzer:innen Feedback, ohne den Seiten-Reload auszulösen, den Webflows Standard-Formularverarbeitung verursachen würde.

Checkpoint: Veröffentlichen Sie Ihre Webflow-Website, füllen Sie das Formular aus und senden Sie es ab. Die Statusmeldung sollte sich aktualisieren, und Sie sollten sowohl die Bestätigungs-E-Mail als auch die Benachrichtigung an die Inhaberin erhalten.

Was verursacht Fehlschläge beim Postmark-E-Mail-Versand in Webflow Cloud?

Die meisten Fehlschläge fallen in drei Kategorien: das npm-SDK wird importiert, obwohl es das nicht sollte, unverifizierte Sender Signatures und inaktive Empfängeradressen.

Hier sehen Sie, wie sich jede davon äußert und wie Sie sie beheben.

Das npm-Paket postmark wirft beim Import einen Fehler

Wenn beim Laden Ihres Route Handlers „Cannot find module 'events'" oder „TypeError: Class extends value undefined" erscheint, ist das postmark-npm-Paket installiert. Entfernen Sie es mit npm uninstall postmark und verwenden Sie den fetch()-basierten Helper aus Schritt 3.

Die Cloudflare-Workers-Dokumentation stellt explizit fest, dass Postmarks JavaScript-Bibliothek auf Workers nicht unterstützt wird. Die HTTP-API deckt jede Operation in diesem Leitfaden ab.

Postmark gibt ErrorCode 400 oder 401 zurück

ErrorCode 400 bedeutet, dass für die From-Adresse keine Sender Signature in Postmark existiert; sie wurde noch nicht erstellt. ErrorCode 401 bedeutet, dass die Sender Signature existiert, aber die Bestätigungs-E-Mail noch nicht angeklickt wurde.

Beide werden im Postmark-Dashboard gelöst: Fügen Sie entweder die From-Adresse als neue Sender Signature hinzu, oder schließen Sie die Domain-Verifizierung unter Sender Signatures ab. Eine einzige verifizierte Domain deckt jede Adresse auf dieser Domain ab, sodass sowohl hello@yourdomain.com als auch no-reply@yourdomain.com funktionieren, sobald die Domain verifiziert ist.

Postmark gibt ErrorCode 406 zurück

ErrorCode 406 bedeutet, dass die Empfängeradresse inaktiv ist. Postmark markiert Empfänger:innen nach einem Hard Bounce oder einer Spam-Beschwerde als inaktiv. Ich behandle 406 im Route Handler, indem ich eine nutzerseitige Fehlermeldung zurückgebe: „Diese E-Mail-Adresse ist zuvor unzustellbar zurückgekommen. Bitte verwenden Sie eine andere Adresse."

Ein erneuter Versand funktioniert nicht. Inaktive Empfänger:innen erfordern eine manuelle Reaktivierung über das Postmark-Aktivitätsprotokoll.

Was Sie bauen sollten, nachdem transaktionale E-Mail in Webflow Cloud läuft

Wenn Sie lieber über SendGrid senden möchten, gilt dieselbe Route-Handler-Struktur, und unser SendGrid-Kontaktformular-Leitfaden behandelt das, einschließlich der serverseitigen Validierung und des Honeypot-Spamschutzes, auf die dieser Walkthrough nicht eingeht.

Mit einer funktionierenden E-Mail-Einrichtung ist die naheliegende nächste Ergänzung: Postmark-Templates. Statt E-Mail-HTML innerhalb des Route Handlers zu bauen, lässt Sie Postmarks Templates API die E-Mail-Copy im Postmark-Dashboard verwalten und zur Sendezeit mit Variablen rendern: ein sendTemplate()-Aufruf, der an /email/withTemplate mit { TemplateAlias: 'contact-confirmation', TemplateModel: { name, message } } postet. Das HTML bleibt außerhalb der Codebase und kann ohne Deploy bearbeitet werden.

Entdecken Sie Webflow + Postmark für eine vollständige Liste der Integrationsoptionen, oder besuchen Sie die Webflow-Cloud-Dokumentation, wenn Sie Ihre Cloud-App zum ersten Mal einrichten.

Häufig gestellte Fragen

Kann ich Postmarks integrierte E-Mail-Templates verwenden?

Ja. Postmarks Templates API akzeptiert einen TemplateAlias (den Identifikator des Templates im Dashboard) und ein TemplateModel (ein JSON-Objekt mit zu ersetzenden Variablen). Ersetzen Sie sendEmail() durch eine sendTemplate()-Funktion, die an /email/withTemplate mit { TemplateAlias: 'your-alias', TemplateModel: { name, message } } postet. Templates werden im Postmark-Dashboard erstellt und bearbeitet, ohne dass ein Code-Deploy nötig ist, um die Copy zu aktualisieren.

Wie löse ich E-Mails über Webflows integrierte Formularübermittlung aus?

Webflows integrierte Formulare feuern einen form_submission-Webhook, wenn eine Besucherin ein Formular absendet. Konfigurieren Sie einen Webhook unter Webflow Settings → Integrations → Webhooks mit dem Trigger form_submission, der auf die URL Ihres Route Handlers zeigt. Der Route Handler empfängt die Formularfelddaten als JSON und ruft sendEmail() genau wie oben auf. Der einzige Unterschied ist die Form der eingehenden Payload: Webflows Webhook liefert ein verschachteltes fieldData-Objekt statt flacher JSON-Felder.

Wie sende ich an mehrere Empfänger:innen?

Postmark akzeptiert durch Kommas getrennte Adressen in den Feldern To, Cc und Bcc, mit einem kombinierten Limit von 50 Empfänger:innen pro Nachricht. Für Versände an mehr als 50 Empfänger:innen nutzen Sie Postmarks Batch-Endpoint unter /email/batch, der bis zu 500 Nachrichten pro API-Aufruf akzeptiert.

Wie teste ich, ohne echte E-Mails zu senden?

Setzen Sie POSTMARK_SERVER_TOKEN=POSTMARK_API_TEST in .env.local. Anfragen gehen an Postmarks API, Ihr JSON-Format wird validiert, und Sie erhalten eine MessageID zurück. Es wird keine E-Mail zugestellt. Das ist der richtige Weg, um Integrationstests gegen den E-Mail-Flow zu schreiben, ohne an echte Postfächer zu senden.


Last Updated
Category

Related articles


verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logoreddit logothe new york times logoideo logoupwork logodiscord logo
verifone logomonday.com logospotify logoted logogreenhouse logoclear logocheckout.com logoreddit logothe new york times logoideo logoupwork logodiscord logo

Jetzt kostenlos loslegen

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.

Get started — it’s free
Get started — it’s free
Demo ansehen
Demo ansehen

Try Webflow for as long as you like with our free Starter plan. Purchase a paid Site plan to publish, host, and unlock additional features.