Re: Neuer Formulargenerator
Verfasst: Sa 23. Aug 2025, 08:03
Forum für Mobirise und NOF
https://www.mobirise-tutorials.com/Forum/
https://www.mobirise-tutorials.com/Forum/viewtopic.php?t=1782
Das ist eine längere Sitzung - ich erstelle einen öffentlichen Zugang zu der Antwort und werden Link dann gleich hier posten.CHatGPT hat geschrieben:
Hi Tommy!
Der Fehler „Sicherheitsfehler: Ungültiges Token“ entsteht zu 99 % dadurch, dass die Session-Cookie (PHPSESSID) beim POST an send.php nicht mitgeschickt wird. Dann hat send.php eine leere/andere Session und $_SESSION["csrf_token"] passt nicht zum Hidden-Field.
Hier sind die typischen Ursachen (und die schnellen Fixes):
Code: Alles auswählen
session_start();
Code: Alles auswählen
// Einheitlicher, eigener Session-Name
session_name('FORMSESSID');
// Klare, einheitliche Cookie-Parameter
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
'httponly' => true,
'samesite' => 'Lax', // bei echter Same-Site völlig ok
]);
session_start();
Code: Alles auswählen
$zip->addFromString('captcha.php', $captchaContent);
}
// ----------------------------------------------------
// 3. Erstelle send.php mit erweiterten SMTP-Funktionen
// ----------------------------------------------------
$sendContent = '
<?php
session_start();
// PHPMailer einbinden (falls via Composer installiert)
// require_once "vendor/autoload.php";
// Alternativ: PHPMailer manuell einbinden (falls embedded verwendet wird)
require_once "PHPMailer/src/Exception.php";
require_once "PHPMailer/src/PHPMailer.php";
require_once "PHPMailer/src/SMTP.php";
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// =============================================================
// KONFIGURATION - Hier können Sie Ihre Einstellungen anpassen
// =============================================================
// Grundeinstellungen
$recipient_email = "' . addslashes($settings['recipientEmail']) . '";
$sender_name = "' . addslashes($settings['senderName']) . '";
$success_message = "' . addslashes($settings['successMessage']) . '";
// SMTP-Konfiguration - Nur ausfüllen wenn Sie SMTP verwenden möchten:
// Lassen Sie diese Werte auskommentiert für normalen E-Mail-Versand über PHPMailer ohne SMTP
/*
$smtp_host = "smtp.gmail.com"; // Ihr SMTP-Server
$smtp_port = 587; // SMTP-Port (587 für TLS, 465 für SSL)
$smtp_secure = "tls"; // Verschlüsselung: "tls" oder "ssl"
$smtp_user = "ihre.email@gmail.com"; // Ihr SMTP-Benutzername
$smtp_pass = "ihr_app_passwort"; // Ihr SMTP-Passwort
$smtp_from_name = "Ihr Name"; // Name des Absenders
*/
// Automatische Antwort-Einstellungen
$enable_auto_reply = ' . ($settings['enableAutoReply'] ? 'true' : 'false') . ';
$auto_reply_subject = "' . addslashes($settings['autoReplySubject']) . '";
$auto_reply_message = "' . addslashes($settings['autoReplyMessage']) . '";
$auto_reply_include_original = ' . ($settings['autoReplyIncludeOriginal'] ? 'true' : 'false') . ';
$auto_reply_html_format = ' . ($settings['autoReplyHtmlFormat'] ? 'true' : 'false') . ';
$auto_reply_sender_name = "' . addslashes($settings['autoReplySenderName']) . '";
// Datei-Upload-Einstellungen
$allowed_extensions = ["' . implode('", "', explode(',', $settings['allowedExtensions'])) . '"];
$max_filesize_mb = ' . $settings['maxFilesize'] . ';
$uploads_dir = "uploads/";
// =============================================================
// HILFSFUNKTIONEN
// =============================================================
// Funktion zur Bereinigung von Eingabedaten
function sanitize_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data, ENT_QUOTES, "UTF-8");
return $data;
}
// Funktion zur Validierung der SMTP-Konfiguration
function validateSmtpConfig() {
global $smtp_host, $smtp_user, $smtp_pass, $smtp_port, $smtp_secure;
$required_fields = ["smtp_host", "smtp_user", "smtp_pass"];
foreach ($required_fields as $field) {
if (!isset($GLOBALS[$field]) || empty($GLOBALS[$field])) {
return false;
}
}
// Port-Validierung
if (isset($smtp_port) && (!is_numeric($smtp_port) || $smtp_port < 1 || $smtp_port > 65535)) {
return false;
}
// Verschlüsselung-Validierung
if (isset($smtp_secure) && !in_array($smtp_secure, ["tls", "ssl"])) {
return false;
}
return true;
}
// Funktion zur Konfiguration des PHPMailer-Objekts
function configurePHPMailer($mail, $sender_name, $recipient_email) {
global $smtp_host, $smtp_user, $smtp_pass, $smtp_port, $smtp_secure, $smtp_from_name;
try {
// SMTP-Konfiguration prüfen
if (validateSmtpConfig()) {
// SMTP verwenden
$mail->isSMTP();
$mail->Host = $smtp_host;
$mail->SMTPAuth = true;
$mail->Username = $smtp_user;
$mail->Password = $smtp_pass;
// Debugging (nur für Entwicklung aktivieren)
// $mail->SMTPDebug = SMTP::DEBUG_SERVER;
$mail->SMTPOptions = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
"allow_self_signed" => true
)
);
// Verschlüsselung und Port
if (isset($smtp_secure) && $smtp_secure === "ssl") {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = isset($smtp_port) ? (int)$smtp_port : 465;
} else {
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = isset($smtp_port) ? (int)$smtp_port : 587;
}
// Timeout-Einstellungen
$mail->Timeout = 30;
$mail->SMTPKeepAlive = false;
// Absender für SMTP
$from_name = isset($smtp_from_name) ? $smtp_from_name : $sender_name;
$mail->setFrom($smtp_user, $from_name);
return "smtp";
} else {
// Standard-Mail verwenden
$mail->isMail();
$mail->setFrom($recipient_email, $sender_name);
return "mail";
}
} catch (Exception $e) {
// Bei SMTP-Fehlern auf Standard-Mail zurückfallen
error_log("SMTP Configuration Error: " . $e->getMessage());
$mail->isMail();
$mail->setFrom($recipient_email, $sender_name);
return "fallback";
}
}
// =============================================================
// HAUPTVERARBEITUNG
// =============================================================
// Überprüfen, ob Daten gesendet wurden
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Anti-Spam: CSRF-Token-Überprüfung
if (!isset($_POST["csrf_token"]) || $_POST["csrf_token"] !== ($_SESSION["csrf_token"] ?? null)) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Sicherheitsfehler: Ungültiges Token."]);
exit;
}
// Anti-Spam: Honeypot-Überprüfung
if (!empty($_POST["name_hp"])) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Honeypot-Feld ausgefüllt, dies ist ein Spam-Versuch."]);
exit;
}
// Anti-Spam: Zeitbasierte Überprüfung (mind. 3 Sekunden)
$time_diff = time() - ($_SESSION["form_start_time"] ?? 0);
if ($time_diff < 3) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Formular zu schnell ausgefüllt."]);
exit;
}
// Validierung der Pflichtfelder und E-Mail-Validierung
$required_fields = [' . implode(', ', array_filter(array_map(function($field) {
return $field['required'] ? '"' . addslashes($field['name']) . '"' : null;
}, $fields))) . '];
$email_field_name = "";
// E-Mail-Feldname suchen
foreach ($_POST as $key => $value) {
if (strpos(strtolower($key), "email") !== false || strpos(strtolower($key), "mail") !== false) {
$email_field_name = $key;
break;
}
}
$errors = [];
foreach ($required_fields as $field_name) {
if (!empty($field_name) && (empty($_POST[$field_name]) && empty($_FILES[$field_name]["tmp_name"]))) {
$errors[] = $field_name;
}
}
// Zusätzliche E-Mail-Validierung, falls ein E-Mail-Feld gefunden wurde
if (!empty($email_field_name)) {
$email_value = $_POST[$email_field_name] ?? "";
if (!empty($email_value) && !filter_var($email_value, FILTER_VALIDATE_EMAIL)) {
$errors[] = $email_field_name; // Fügt das E-Mail-Feld zu den Fehlern hinzu
}
}
// CAPTCHA-Überprüfung
' . ($settings['useCaptcha'] === 'simple' ? '
if (!isset($_POST["captcha"]) || intval($_POST["captcha"]) !== ($_SESSION["captcha_sum"] ?? null)) {
$errors[] = "captcha";
}
' : '') . ($settings['useCaptcha'] === 'image' ? '
if (!isset($_POST["captcha"]) || strtoupper($_POST["captcha"]) !== ($_SESSION["captcha_code"] ?? null)) {
$errors[] = "captcha";
// Neuen CAPTCHA-Code generieren nach falschem Versuch
$captcha_code = "";
$characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ($i = 0; $i < 5; $i++) {
$captcha_code .= $characters[rand(0, strlen($characters) - 1)];
}
$_SESSION["captcha_code"] = $captcha_code;
}
' : '') . '
if (!empty($errors)) {
http_response_code(400);
echo json_encode(["success" => false, "message" => "Bitte füllen Sie alle Pflichtfelder korrekt aus.", "errors" => $errors]);
exit;
}
// Absender-E-Mail ermitteln (für automatische Antwort und Kopie)
$sender_email = "";
foreach ($_POST as $key => $value) {
if (strpos(strtolower($key), "email") !== false || strpos(strtolower($key), "mail") !== false) {
$sanitized_value = filter_var(sanitize_input($value), FILTER_SANITIZE_EMAIL);
if (filter_var($sanitized_value, FILTER_VALIDATE_EMAIL)) {
$sender_email = $sanitized_value;
break;
}
}
}
// Kopie an Absender gewünscht prüfen
$send_copy_to_sender = isset($_POST["send_copy_to_sender"]) && $_POST["send_copy_to_sender"] === "1";
// E-Mail-Betreff basierend auf den ersten beiden sichtbaren Feldern (Anti-Spam-Felder überspringen)
$subject = "Neue Nachricht aus dem Formular";
if (!empty($_POST)) {
$skip_keys = ["csrf_token", "name_hp", "captcha", "send_copy_to_sender"];
$visible_values = [];
foreach ($_POST as $key => $value) {
if (in_array($key, $skip_keys, true)) continue;
if (is_array($value)) continue;
if (trim((string)$value) === "") continue;
$visible_values[] = $value;
}
$first_value = $visible_values[0] ?? reset($_POST);
$second_value = $visible_values[1] ?? next($_POST);
if (!empty($first_value)) {
$subject = "Nachricht von " . sanitize_input($first_value);
if (!empty($second_value) && $second_value !== $first_value) {
$subject .= " (" . sanitize_input($second_value) . ")";
}
}
}
// E-Mail-Inhalt als HTML-Tabelle erstellen
$mail_content_html = "
<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;\">
<h2 style=\"color: #333; border-bottom: 2px solid #007bff; padding-bottom: 10px;\">
Neue Nachricht aus dem Formular
</h2>
<p>Hallo,</p>
<p>Sie haben eine neue Nachricht aus dem Kontaktformular erhalten:</p>
<table style=\"border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;\">
<tbody>
";
Code: Alles auswählen
// ----------------------------------------------------
// 1. Erstelle index.php
// ----------------------------------------------------
$indexContent = '
<?php
session_start();
' . ($settings['useCaptcha'] === 'simple' ? '
$captcha_num1 = mt_rand(1, 9);
$captcha_num2 = mt_rand(1, 9);
$_SESSION["captcha_sum"] = $captcha_num1 + $captcha_num2;
' : '') . ($settings['useCaptcha'] === 'image' ? '
// Bild-CAPTCHA Code generieren
$captcha_code = "";
$characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ($i = 0; $i < 5; $i++) {
$captcha_code .= $characters[rand(0, strlen($characters) - 1)];
}
$_SESSION["captcha_code"] = $captcha_code;
' : '') . '
// Anti-Spam: CSRF-Token und Zeitstempel erstellen
if (empty($_SESSION["csrf_token"])) {
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
}
$_SESSION["form_start_time"] = time();
?>
Code: Alles auswählen
session_start();
Code: Alles auswählen
<?php
// Einheitlicher, eigener Session-Name
session_name('FORMSESSID');
// Klare, einheitliche Cookie-Parameter
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
'httponly' => true,
'samesite' => 'Lax', // bei echter Same-Site völlig ok
]);
session_start();
Code: Alles auswählen
const response = await fetch(form.action, {
method: form.method,
body: formData,
credentials: "same-origin" // <— wichtig!
});
Code: Alles auswählen
header('Content-Type: application/json; charset=UTF-8');
CAPTCHA-Hinweise:
- Das Bild-CAPTCHA verwendet die PHP GD-Extension
- Die Datei captcha.php generiert die CAPTCHA-Bilder dynamisch
- CAPTCHA-Codes werden in der PHP-Session gespeichert
- Nach jedem fehlgeschlagenen Versuch wird ein neuer Code generiert
Kein Problem Tommy, ich hab Zeit, bin ja noch JungTommy Herrmann hat geschrieben: Sa 23. Aug 2025, 14:27 Ich kann gerade noch nicht ...
... versuche etwas später zu testen