Ein Formular an deine E-Mail senden

Ein Formular an deine E-Mail senden6 Min. Lesezeit

Ein HTML-Formular ohne PHP an E-Mail senden

Ersetze ein contact.php-Skript, das mail() aufruft, durch ein Formular, das an einen gehosteten Endpunkt sendet, mit deinen Feldnamen, deiner Dankeseite und Antworten.

Preet SutharGründer, Ikiform

Ändere die action des Formulars von deinem PHP-Skript auf die URL eines Formular-Backends, behalte die Feldnamen und lösche das Skript. Das Backend macht, was mail() gemacht hat, plus das, was es nie gut gemacht hat: Spamfilter, Speicherung und Mail, die nicht im Spam landet. Es funktioniert auf statischen Hosts, auf denen PHP gar nicht laufen kann.

Was hier anders ist

Die meisten PHP-Kontaktformulare sind dieselben zwanzig Zeilen, vor Jahren aus einem Tutorial kopiert. Sie lesen $_POST, bauen einen String, rufen mail() auf und leiten weiter. Hier ein typisches:

contact.php
<?php
$name = $_POST["name"];
$email = $_POST["email"];
$phone = $_POST["phone"];
$message = $_POST["message"];

$to = "hello@example.com";
$subject = "Website enquiry from $name";
$body = "Name: $name\nEmail: $email\nPhone: $phone\n\n$message";
$headers = "From: $email\r\nReply-To: $email";

if (mail($to, $subject, $body, $headers)) {
  header("Location: /thanks.html");
} else {
  echo "Sorry, something went wrong.";
}

Es sieht harmlos aus und hat funktioniert, als es geschrieben wurde. Heute geht es auf vier Arten kaputt, und nur die erste ist offensichtlich:

ProblemWarum es passiert
Kein PHP beim HostGitHub Pages, Netlify, Vercel, Cloudflare Pages und S3 liefern Dateien aus; sie führen kein PHP aus. Das Formular sendet an eine Datei, die nie ausgeführt wird, und du bekommst 404 oder 405.
Mail landet im Spam oder verschwindetmail() übergibt die Nachricht an das lokale Mailprogramm des Servers. Der From:-Header gibt die Adresse des Besuchers an, aber die Mail verlässt den Server deines Hosts, fällt also bei den SPF- und DMARC-Prüfungen der Domain des Besuchers durch. Gmail und Outlook filtern oder lehnen sie ab, oft stillschweigend.
Header-Injection$email landet ungeprüft in den Headern. Ein Bot, der einen Wert mit Zeilenumbruch sendet, kann eine eigene Bcc:-Zeile hinzufügen und dein Formular zum Spamversand nutzen, wodurch die IP deines Hosts auf Blocklisten landet.
Nichts wird aufbewahrtGeht die E-Mail verloren, ist auch die Nachricht weg. Es gibt keinen Nachweis, keinen Spamfilter und keine Möglichkeit, auf die Anfragen des letzten Monats zurückzublicken.

Du könntest jedes Problem einzeln beheben: jeden Wert validieren, über einen SMTP-Anbieter mit einer Bibliothek wie PHPMailer senden, SPF und DKIM für deine Domain einrichten, einen Honeypot und ein Rate-Limit hinzufügen und in eine Datenbank loggen. Das ist ein vernünftiges Projekt, wenn du ohnehin PHP betreibst. Wenn nicht, verlagere die Arbeit an ein Formular-Backend.

Dasselbe Formular mit PHPs mail() und mit einem Formular-Backendmit contact.phpmit einem Formular-Backenddein Formularaction="/contact.php"mail()From: der Besucher,gesendet von deinemHostSpam-Ordnerfällt bei SPF undDMARC durchdein Formulargleiche Felder,neue actionIkiformfiltert Spam,speichertdein PostfachReply-To: derBesucherPostlokale MailPostE-MailDasselbe Formular mit PHPs mail() und mit einem Formular-Backendmit contact.phpmit einem Formular-Backenddein Formularaction="/contact.php"mail()From: der Besucher, gesendet vondeinem HostSpam-Ordnerfällt bei SPF und DMARC durchdein Formulargleiche Felder, neue actionIkiformfiltert Spam, speichertdein PostfachReply-To: der BesucherPostlokale MailPostE-Mail
  1. Mit contact.php sendet das Formular an deinen Host, und mail() verschickt eine Nachricht, die angeblich vom Besucher kommt. Empfangende Server sehen einen Absender, der nicht zur Domain passt, und sortieren die Mail als Spam aus oder verwerfen sie.
  2. Mit einem Formular-Backend sendet das Formular dieselben Felder an Ikiform. Ikiform verschickt die E-Mail von seiner eigenen Domain und setzt die Adresse des Besuchers in Reply-To, genau wofür Reply-To da ist.
Die Lösung für die Zustellbarkeit ist kein besseres Skript. Sie besteht darin, von einer Domain zu senden, die senden darf.

Das Formular von PHP lösen

Behalte die Feldnamen exakt so, wie sie sind. Nur die action ändert sich, plus zwei versteckte Eingabefelder:

Vorher
<form action="/contact.php" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>
Nachher
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <input type="hidden" name="_redirect" value="https://example.com/thanks.html" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>

Ordne dann jede Aufgabe des Skripts der Stelle zu, wo sie jetzt erledigt wird:

In contact.phpJetzt
$to = "hello@example.com"Empfänger in den Einstellungen Notifications des Formulars
header("Location: /thanks.html")Das versteckte Eingabefeld _redirect oder Redirect after submit in den Einstellungen des Formulars
Reply-To: $emailAutomatisch, weil das Feld email heißt
$subject = "Website enquiry from $name"Fest auf New submission: <form name>. Nenne das Formular „Website enquiry“, um die Formulierung zu behalten
echo "Sorry, something went wrong."Die Fehlerseite von Ikiform bei einem einfachen Post oder deine eigene Meldung mit fetch
Prüfungen, die du nie geschrieben hastDer Honeypot _gotcha, Spam-Bewertung, Rate-Limits und Feldvalidierung
  • Füge deine Domain unter Allowed domains hinzu. _redirect funktioniert nur mit einer https:-URL auf einer dieser Domains.
  • Lösch contact.php vom Server, sobald das neue Formular funktioniert. Ein vergessenes Skript ist für Bots, die sich die URL merken, weiterhin ein offenes Mail-Relay.
  • Wenn du zu einem statischen Host umgezogen bist, existiert die alte URL /contact.php nicht mehr. Bots, die direkt dorthin senden, bekommen einen 404, und das ist in Ordnung.
Wenn dein Formular ein WordPress-Plugin statt eines Skripts war, gilt dasselbe Prinzip. Die WordPress-Anleitung zeigt, wo das Formular in einem Block-Theme hingehört.

Prüfen, ob es funktioniert

  1. Füge unter Allowed domains des Formulars die Domain deiner Site hinzu, plus localhost, während du entwickelst. Lass das Feld leer, um Posts von überall anzunehmen.
  2. Sende das Formular auf deiner Live-Seite ab. Du landest auf deiner alten thanks.html.
  3. Öffne Submissions im Dashboard. Die neue Einsendung ist da, mit jedem Feld, das du gesendet hast.
  4. Öffne die E-Mail. Sie kommt von Ikiform, nicht von der Adresse des Besuchers, und liegt nicht im Spam. Füge den Absender zu deinen Kontakten hinzu, damit auch spätere nicht dort landen.
  5. Klick auf Reply. Die Adresse des Besuchers steht in der Zeile To.
  6. Sende einen Post mit ausgefülltem Honeypot, _gotcha=bot. Er bekommt trotzdem eine Erfolgsantwort, aber die Einsendung wird als Spam gespeichert und löst weder E-Mail noch Webhook aus.

Stolperfallen

  • Alte Formularnamen mit Klammern. PHP-Formulare verwenden oft Namen wie contact[email]. Ikiform speichert sie unverändert, aber das Reply-To kommt nur aus einem Feld namens email oder ein paar nahen Varianten. Benenne das Feld um oder füge _replyto hinzu.
  • Der Betreff kann den Namen nicht enthalten. Die Betreffzeile des Skripts enthielt den Namen des Besuchers. Der Betreff der Benachrichtigung ist fest, und _subject wird an Webhooks und die API weitergegeben, ohne die E-Mail zu ändern.
  • Zeichenkodierung. mail()-Skripte haben Umlaute und Akzente oft verunstaltet, weil sie nie einen Zeichensatz gesetzt haben. Die E-Mail von Ikiform ist UTF-8, Namen in jeder Schrift kommen also unversehrt an.
  • Mehrere Adressen in $to. Eine Komma-Liste im Skript wird im Dashboard zu separaten Empfängern. Externe Adressen bestätigen per Link, bevor sie etwas bekommen. Siehe mehrere Empfänger.

Wenn etwas schiefgeht

ProblemWas zu tun ist
Der Browser landet auf der Dankeseite von Ikiform statt auf deiner_redirect wird ignoriert, außer seine Domain steht unter Allowed domains und es ist eine https:-URL. Füge die Domain hinzu oder setze stattdessen Redirect after submit in den Einstellungen des Formulars.
403 origin_not_allowed, oder jeder Post landet im SpamDie Domain der Seite steht nicht unter Allowed domains des Formulars. Füge sie hinzu, plus localhost für lokale Tests. Subdomains einer eingetragenen Domain sind erlaubt.
Das Formular sendet noch an die PHP-DateiEine gecachte Seite oder eine zweite Kopie des Formulars, etwa ein Footer-Include, hat noch die alte action. Durchsuche die Site nach contact.php.
Die Einsendung ist im Dashboard, aber keine E-Mail und kein Webhook kam anSie wurde als Spam gespeichert. Spam löst nichts aus. Öffne sie unter dem Filter Spam, um die Gründe zu sehen, und markiere sie als kein Spam, um ihre E-Mail und Webhooks zu senden.

Fragen

Hängst du bei einem Schritt fest oder willst eine Anleitung für deinen Fall? Schreib an hello@ikiform.com.