Gästebuch ohne Datenbank

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Volker »

Hier mal ein Code mit PHPMailer.
Das was kommentiert ist auskommentieren und Daten eintrage.
Den PHPMailer bitte runter laden und in das Verzeichnis de GB kopieren.

Bitte auch den unteren Teil im Script beachten und dort den Kommentar entfernen das /* weg nehmen.

Hier der Code eintragsformular.php mit PHPMailer Optional:



Fehlerhaften Code entfernt
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Moin Volker,

also Dein Skript funktioniert so nicht.

Ich habe es von `ChatGPT` überarbeiten lassen und ein Fallback auf PHP mail() mit einbauen lassen, falls SMTP fehlschlägt.

Hattest du das geprüft, denn so kann es eigentlich nicht funktionieren, meint zumindest ChatGPT. Bitte stelle deine Skripte immer erst nach erfolgreicher Prüfung hier ein - oder vermerke es als "nicht geprüft".

Ich habe das Skript (bei mir ist es der Hoster `IONOS`) hier mehrfach erfolgreich getestet:

https://www.mobirise-tutorials.com/Tuto ... Volker.php

Bitte übernehme das Skript in deinen Download und füge auch den PHPMailer im Download hinzu. Bitte teile mir auch mit, ob und wann du das umbaust, damit ich meine Tutorialseite und deine neue `lies_mich` Datei entsprechen anpassen kann und lasse mich bitte auch wissen, falls du ein neues Video erstellen solltest.




@ Dieter,

bitte verwende mein Skript unten und trage oben deine Mail-Adresse, die bei deinem Provider angelegt sein muss, ein. Also ab Zeile 11. Trage auch die die SMTP-Host-Adresse von deinem Provider ein, wo jetzt beispielhaft die von meinem Provider IONOS steht ( 'smtp.ionos.de' ). Passe dabei auf, dass du nicht versehentlich dabei irgendwelche anderen Zeichen wie ' Hochstriche löscht.

Ich habe unten alle einzutragenden Daten fett markiert. Deine SMTP-Daten erfährst du auch im Kundenmenü von Deinem Provider oder rufe dort an und frage:


/* =========================
KONFIGURATION
========================= */
$SITE_NAME = 'Gästebuch-Volker';
$ADMIN_EMAIL = 'Mail@DeineDomain.de'; // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS = 'Mail@DeineDomain.de'; // ← Deine Mailbox beim Provider
$FROM_NAME = $SITE_NAME; // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP = true; // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST = 'smtp.ionos.de'; // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT = 587; // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH = true;
$SMTP_USERNAME = 'Mail@DeineDomain.de'; // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******'; // Dein echtes Passwort eintragen
$SMTP_SECURE = 'tls'; // 'tls' oder 'ssl'


Kopiere hier also das gesamte und korrigierte Skript `eintragsformular.php` - trage deine Mailadresse und SMTP-Daten ein - und speichere es auch genau mit diesem Namen ab:

Code: Alles auswählen

<?php
/*******************************************************
 * Gästebuch – Eintrag + Admin-Benachrichtigung
 * Stand: 2025-09-16
 * Mit SMTP-Option für PHPMailer + mail()-Fallback
 *******************************************************/

session_start();
date_default_timezone_set('Europe/Berlin');

/* =========================
   KONFIGURATION
   ========================= */
$SITE_NAME            = 'Gästebuch-Volker';
$ADMIN_EMAIL          = 'Mail@DeineDomain.de';              // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS  = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS         = 'Mail@DeineDomain.de';              // ← Deine Mailbox beim Provider
$FROM_NAME            = $SITE_NAME;                         // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP      = true;                   // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST     = 'smtp.ionos.de';        // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT     = 587;                    // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH     = true;
$SMTP_USERNAME = 'Mail@DeineDomain.de';  // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******';              // Dein echtes Passwort eintragen
$SMTP_SECURE   = 'tls';                  // 'tls' oder 'ssl'

// Datendateien
$entries_file = __DIR__ . '/entries.json';
$pending_file = __DIR__ . '/pending.json';

/* =========================
   HILFSFUNKTIONEN
   ========================= */
function loadEntries(string $file): array {
    if (!file_exists($file)) return [];
    $content = @file_get_contents($file);
    if ($content === false || $content === '') return [];
    $data = json_decode($content, true);
    return is_array($data) ? $data : [];
}

function saveEntries(array $entries, string $file): void {
    $json = json_encode($entries, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    $fp = @fopen($file, 'c+');
    if ($fp === false) {
        error_log("Gästebuch: Datei kann nicht geöffnet werden: $file");
        return;
    }
    if (flock($fp, LOCK_EX)) {
        ftruncate($fp, 0);
        fwrite($fp, $json);
        fflush($fp);
        flock($fp, LOCK_UN);
    }
    fclose($fp);
}

function sanitizeInput(?string $input): string {
    return htmlspecialchars(trim((string)$input), ENT_QUOTES, 'UTF-8');
}

/* =========================
   MAIL-FUNKTIONEN (PHPMailer + Fallback mail())
   ========================= */

/**
 * SMTP-Versand per PHPMailer
 */
function sendAdminNotificationSMTP(array $entry, string $admin_email, string $site_name, string $from_address, string $from_name): bool
{
    // PHPMailer laden – Pfade ggf. anpassen
    require_once __DIR__ . '/PHPMailer/src/Exception.php';
    require_once __DIR__ . '/PHPMailer/src/PHPMailer.php';
    require_once __DIR__ . '/PHPMailer/src/SMTP.php';

    // FIX: KEINE use-Statements innerhalb der Funktion!
    // => Vollqualifizierte Klassennamen verwenden:
    // \PHPMailer\PHPMailer\PHPMailer, \PHPMailer\PHPMailer\Exception

    global $SMTP_HOST, $SMTP_PORT, $SMTP_AUTH, $SMTP_USERNAME, $SMTP_PASSWORD, $SMTP_SECURE;

    $mail = new \PHPMailer\PHPMailer\PHPMailer(true);

    try {
        // Optionales Debugging ohne HTML-Ausgabe (bei Bedarf aktivieren)
        // $mail->SMTPDebug = \PHPMailer\PHPMailer\SMTP::DEBUG_SERVER;
        // $mail->Debugoutput = function($str, $level){ error_log("PHPMailer[$level]: $str"); };

        // SMTP-Konfiguration
        $mail->isSMTP();
        $mail->Host       = $SMTP_HOST;
        $mail->SMTPAuth   = $SMTP_AUTH;
        $mail->Username   = $SMTP_USERNAME;
        $mail->Password   = $SMTP_PASSWORD;
        $mail->SMTPSecure = $SMTP_SECURE; // 'tls' (587) oder 'ssl' (465)
        $mail->Port       = $SMTP_PORT;

        // Charset und Encoding
        $mail->CharSet  = 'UTF-8';
        $mail->Encoding = 'base64';

        // Absender (IONOS: echte Mailbox derselben Domain!)
        $mail->setFrom($from_address, $from_name);

        // Empfänger (Admin)
        $mail->addAddress($admin_email);

        // Reply-To (nur wenn valide Nutzeradresse vorhanden)
        if (!empty($entry['email']) && filter_var($entry['email'], FILTER_VALIDATE_EMAIL)) {
            $mail->addReplyTo($entry['email'], $entry['name'] ?? '');
        } else {
            $mail->addReplyTo($from_address, $from_name);
        }

        // Admin-URL bauen
        $is_https  = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on');
        $protocol  = $is_https ? 'https' : 'http';
        $host      = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $baseDir   = rtrim(dirname($_SERVER['REQUEST_URI'] ?? '/'), '/\\');
        $admin_url = $protocol . '://' . $host . $baseDir . '/admin.php';

        // Inhalt (Plain Text)
        $mail->isHTML(false);
        $mail->Subject = "[$site_name] Neuer Gästebucheintrag wartet auf Freischaltung";

        $mail->Body =
            "Hallo Administrator,\n\n" .
            "ein neuer Eintrag in Ihr Gästebuch wartet auf Freischaltung:\n\n" .
            "═══════════════════════════════════════════════════════════════════\n\n" .
            "Name: " . ($entry['name'] ?? '-') . "\n" .
            "E-Mail: " . (!empty($entry['email']) ? $entry['email'] : 'Nicht angegeben') . "\n" .
            "Datum: " . ($entry['date'] ?? '-') . "\n\n" .
            "Kommentar:\n" . ($entry['comment'] ?? '-') . "\n\n" .
            "═══════════════════════════════════════════════════════════════════\n\n" .
            "Freischalten können Sie den Eintrag hier:\n" . $admin_url . "\n\n" .
            "Viele Grüße\nIhr Gästebuch-System";

        $mail->send();
        error_log("Gästebuch: E-Mail erfolgreich per SMTP gesendet an $admin_email");
        return true;

    } catch (\PHPMailer\PHPMailer\Exception $e) {
        error_log("Gästebuch: SMTP-Fehler: " . $e->getMessage());
        return false;
    }
}

/**
 * Fallback: Versand per PHP mail() – (IONOS) mit Envelope-Sender
 */
function sendAdminNotification(array $entry, string $admin_email, string $site_name, string $from_address, string $from_name): bool
{
    // Empfänger/From prüfen
    if (!filter_var($admin_email, FILTER_VALIDATE_EMAIL)) {
        error_log("Gästebuch: Ungültige Admin E-Mail-Adresse: $admin_email");
        return false;
    }
    if (!filter_var($from_address, FILTER_VALIDATE_EMAIL)) {
        error_log("Gästebuch: Ungültige FROM-Adresse: $from_address");
        return false;
    }

    // Betreff (UTF-8, MIME)
    $raw_subject = "[$site_name] Neuer Gästebucheintrag wartet auf Freischaltung";
    if (function_exists('mb_encode_mimeheader')) {
        $subject = mb_encode_mimeheader($raw_subject, 'UTF-8', 'B', "\r\n");
    } else {
        $subject = "=?UTF-8?B?" . base64_encode($raw_subject) . "?=";
    }

    // Admin-URL bauen
    $is_https  = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on');
    $protocol  = $is_https ? 'https' : 'http';
    $host      = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $baseDir   = rtrim(dirname($_SERVER['REQUEST_URI'] ?? '/'), '/\\');
    $admin_url = $protocol . '://' . $host . $baseDir . '/admin.php';

    // Nachricht (CRLF verwenden)
    $message =
        "Hallo Administrator,\r\n\r\n" .
        "ein neuer Eintrag in Ihr Gästebuch wartet auf Freischaltung:\r\n\r\n" .
        "═══════════════════════════════════════════════════════════════════\r\n\r\n" .
        "Name: " . ($entry['name'] ?? '-') . "\r\n" .
        "E-Mail: " . (!empty($entry['email']) ? $entry['email'] : 'Nicht angegeben') . "\r\n" .
        "Datum: " . ($entry['date'] ?? '-') . "\r\n\r\n" .
        "Kommentar:\r\n" . ($entry['comment'] ?? '-') . "\r\n\r\n" .
        "═══════════════════════════════════════════════════════════════════\r\n\r\n" .
        "Freischalten können Sie den Eintrag hier:\r\n" . $admin_url . "\r\n\r\n" .
        "Viele Grüße\r\nIhr Gästebuch-System";

    // Reply-To: wenn Nutzer-Mail valide, dorthin – sonst From
    $reply_to = (!empty($entry['email']) && filter_var($entry['email'], FILTER_VALIDATE_EMAIL))
        ? $entry['email']
        : $from_address;

    // Absender-Anzeigename MIME-encoden
    $from_display = function_exists('mb_encode_mimeheader')
        ? mb_encode_mimeheader($from_name, 'UTF-8', 'B', "\r\n")
        : "=?UTF-8?B?" . base64_encode($from_name) . "?=";

    // Header (Textmail, UTF-8)
    $headers = [
        "MIME-Version: 1.0",
        "Content-Type: text/plain; charset=UTF-8",
        "From: {$from_display} <{$from_address}>",
        "Reply-To: {$reply_to}",
        "X-Mailer: PHP/" . phpversion(),
    ];
    $headers_str = implode("\r\n", $headers);

    // IONOS: Envelope-Sender (Return-Path) MUSS echte Mailbox sein!
    $additional_params = '-f' . $from_address;

    // Senden
    $success = @mail($admin_email, $subject, $message, $headers_str, $additional_params);

    if ($success) {
        error_log("Gästebuch: mail() erfolgreich an $admin_email");
    } else {
        error_log("Gästebuch: FEHLER bei mail() an $admin_email (From: $from_address)");
    }

    return $success;
}

/* =========================
   FORMULARVERARBEITUNG
   ========================= */
$message = '';
$error   = '';

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST' && ($_POST['action'] ?? '') === 'add_entry') {

    // CAPTCHA prüfen
    $captcha_input   = sanitizeInput($_POST['captcha'] ?? '');
    $captcha_correct = isset($_SESSION['captcha']) && (mb_strtolower($captcha_input) === mb_strtolower($_SESSION['captcha']));

    // Spam-Schutz (Honeypot + Mindestzeit)
    $honeypot_ok = empty($_POST['website'] ?? '');
    $time_ok     = (isset($_POST['form_start_time']) && (time() - (int)$_POST['form_start_time'] >= 3));

    if (!$honeypot_ok || !$time_ok || !$captcha_correct) {
        $error = 'Ihre Anfrage konnte nicht verarbeitet werden. Bitte stellen Sie sicher, dass das CAPTCHA korrekt ausgefüllt ist.';
    } else {
        $name    = sanitizeInput($_POST['name'] ?? '');
        $email   = sanitizeInput($_POST['email'] ?? '');
        $comment = sanitizeInput($_POST['comment'] ?? '');

        if ($name === '' || $comment === '') {
            $error = 'Name und Kommentar sind Pflichtfelder.';
        } else {
            $pending  = loadEntries($pending_file);
            $newEntry = [
                'id'      => bin2hex(random_bytes(8)),
                'name'    => $name,
                'email'   => $email,
                'comment' => $comment,
                'date'    => date('d.m.Y H:i:s'),
            ];
            $pending[] = $newEntry;
            saveEntries($pending, $pending_file);

            // E-Mail an Admin
            $email_sent = false; // FIX: initialisieren, um Notice zu vermeiden
            if ($EMAIL_NOTIFICATIONS && !empty($ADMIN_EMAIL)) {

                if ($USE_SMTP === true) {
                    // 1) SMTP versuchen
                    $email_sent = sendAdminNotificationSMTP(
                        $newEntry,
                        $ADMIN_EMAIL,
                        $SITE_NAME,
                        $FROM_ADDRESS,
                        $FROM_NAME
                    );

                    // 2) Fallback auf mail(), wenn SMTP fehlschlägt
                    if (!$email_sent) { // Fallback
                        $email_sent = sendAdminNotification(
                            $newEntry,
                            $ADMIN_EMAIL,
                            $SITE_NAME,
                            $FROM_ADDRESS,
                            $FROM_NAME
                        );
                    }
                } else {
                    // SMTP deaktiviert → direkt mail()
                    $email_sent = sendAdminNotification(
                        $newEntry,
                        $ADMIN_EMAIL,
                        $SITE_NAME,
                        $FROM_ADDRESS,
                        $FROM_NAME
                    );
                }

                if ($email_sent) {
                    $message = 'Ihr Eintrag wurde übermittelt und der Administrator wurde per E-Mail benachrichtigt. Ihr Eintrag wartet auf Freischaltung.';
                } else {
                    $message = 'Ihr Eintrag wurde übermittelt und wartet auf Freischaltung. (E-Mail-Benachrichtigung fehlgeschlagen - bitte Admin kontaktieren)';
                    error_log("Gästebuch: E-Mail-Benachrichtigung konnte nicht gesendet werden");
                }
            } else {
                $message = 'Ihr Eintrag wurde übermittelt und wartet auf Freischaltung durch den Administrator.';
            }
        }
    }
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gästebuch - Eintrag verfassen</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.10.0/font/bootstrap-icons.min.css" rel="stylesheet">
    <script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@1/index.js"></script>
    <style>
        body { margin-bottom: 50px; }
        .form-card { box-shadow: 0 10px 30px rgba(0,0,0,0.1); border: none; }
        .honeypot { position: absolute; left: -9999px; visibility: hidden; }
    </style>
    <!-- Resize-Skript -->
    <script>
        window.addEventListener("load", fenster);
        window.addEventListener("resize", fenster);
        function fenster() {
          if (parent.document.getElementsByTagName("iframe")[0]) {
            parent.document.getElementsByTagName("iframe")[0].style.height =
              document.getElementsByTagName("html")[0].offsetHeight +'px';
          }
        }
    </script>
</head>
<body class="bg-light">
    <div class="container my-5">
        <div class="row justify-content-center">
            <div class="col-lg-8">
                <div class="d-flex justify-content-between mb-4">
                    <a href="index.php" class="btn btn-outline-primary">
                        <i class="bi bi-arrow-left"></i> Zurück zum Gästebuch
                    </a>
                    <a href="admin.php" class="btn btn-outline-secondary">
                        <i class="bi bi-shield-lock"></i> Admin-Bereich
                    </a>
                </div>

                <?php if (!empty($message)): ?>
                    <div class="alert alert-success alert-dismissible fade show" role="alert">
                        <i class="bi bi-check-circle"></i> <?= $message ?>
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    </div>
                <?php endif; ?>

                <?php if (!empty($error)): ?>
                    <div class="alert alert-danger alert-dismissible fade show" role="alert">
                        <i class="bi bi-exclamation-circle"></i> <?= $error ?>
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    </div>
                <?php endif; ?>

                <div class="card mb-5 form-card">
                    <div class="card-header bg-primary text-white">
                        <h5 class="mb-0"><i class="bi bi-plus-circle"></i> Neuen Eintrag verfassen</h5>
                    </div>
                    <div class="card-body p-4">
                        <form method="POST" novalidate>
                            <input type="hidden" name="action" value="add_entry">
                            <input type="hidden" name="form_start_time" value="<?= time() ?>">

                            <div class="row">
                                <div class="col-md-6 mb-3">
                                    <label for="name" class="form-label fw-semibold">Name *</label>
                                    <input type="text" class="form-control form-control-lg" id="name" name="name" required>
                                </div>
                                <div class="col-md-6 mb-3">
                                    <label for="email" class="form-label fw-semibold">E-Mail (optional, nur für Admin sichtbar)</label>
                                    <input type="email" class="form-control form-control-lg" id="email" name="email">
                                </div>
                            </div>

                            <div class="honeypot">
                                <label for="website">Website (nicht ausfüllen)</label>
                                <input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
                            </div>

                            <div class="mb-4">
                                <label for="comment" class="form-label fw-semibold">Kommentar *</label>
                                <textarea class="form-control" id="comment" name="comment" rows="5"
                                          placeholder="Schreibe deinen Kommentar" required></textarea>
                                <div class="mt-2">
                                    <emoji-picker></emoji-picker>
                                </div>
                            </div>

                            <div class="mb-4">
                                <label for="captcha" class="form-label fw-semibold">Sicherheitscode eingeben *</label>
                                <div class="row g-3 align-items-center">
                                    <div class="col-6">
                                        <img src="captcha.php" alt="CAPTCHA Bild" class="img-fluid border rounded"
                                             onclick="this.src='captcha.php?v='+Math.random()">
                                    </div>
                                    <div class="col-6">
                                        <input type="text" class="form-control form-control-lg" id="captcha" name="captcha" required>
                                    </div>
                                </div>
                                <small class="form-text text-muted mt-2 d-block">
                                    Klicke auf den Code, um das Captcha neu zu laden
                                </small>
                            </div>

                            <div class="d-grid">
                                <button type="submit" class="btn btn-primary btn-lg">
                                    <i class="bi bi-send"></i> Eintrag senden
                                </button>
                            </div>
                        </form>
                    </div>
                </div>

                <div class="text-center mt-5 pt-4 border-top">
                    <p class="text-muted">
                        <i class="bi bi-heart-fill text-danger"></i>
                        Vielen Dank für Deinen Besuch!
                    </p>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
    <script>
        // Emojis einfügen
        document.querySelector('emoji-picker')?.addEventListener('emoji-click', event => {
            const textarea = document.getElementById('comment');
            if (!textarea) return;
            const emoji = event.detail.unicode;
            const startPos = textarea.selectionStart || 0;
            const endPos = textarea.selectionEnd || 0;
            textarea.value = textarea.value.substring(0, startPos) + emoji + textarea.value.substring(endPos);
            textarea.selectionStart = textarea.selectionEnd = startPos + emoji.length;
            textarea.focus();
        });
    </script>
</body>
</html>

Du benötigst nun auch den sehr bekannten "PHPMailer", neue Version 6.10.0, den ich dir hier als ZIP-Archiv dazu packe.

Downloaden, entpacken und dann nur das gesamte Verzeichnis mit diesem Namen "PHPMailer" unverändert auf deinen Server in das gleiche Verzeichnis, in dem dein Projekt liegt, kopieren:

PHPMailer-von-Tommy.zip
(143.96 KiB) 8-mal heruntergeladen

Hier geht es zum direkten Download auf GitHUB (ist aber genau die gleiche Version):

https://github.com/PHPMailer/PHPMailer/ ... ag/v6.10.0
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Volker »

Moin Tommy,

hatte ich natürlich nicht geprüft :(
Hatte ich auf die schnelle eingebaut- sorry dafür, aber der Stress mit Youtube und und und. Gestern war nicht mein Tag.

Liegt jetzt in der ZIP mit deinem Script
Gruß Volker
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Volker »

Aber noch mal zum Thema PHP mail ()

Es handelt sich um eine Mail von meinem Server an mich selbst. Also an meine E-Mailadress die dem Server bekannt ist.
Das mit SMTP und PHPMailer zu machen ist und bleibt übertrieben meiner Meinung nach.

Das sagt Google (KI)
Ja, mit DomainFactory ist PHP Mail erlaubt und wird unterstützt, da es als deutscher Hosting-Anbieter verschiedene PHP-Versionen anbietet und den Safe Mode auf OFF gesetzt hat, was für die Ausführung von PHP-Skripten wie E-Mail-Formularen nötig ist. DomainFactory bietet auf seinen Servern die Nutzung von PHP an und stellt verschiedene Versionen zur Verfügung, um die Funktionalität von Webseiten und Kontaktformularen zu ermöglichen.
Warum PHP Mail auf DomainFactory funktioniert:
Unterstützung für PHP:
DomainFactory bietet die Nutzung der Skriptsprache PHP auf seinen Servern an.
Konfiguration für E-Mail-Versand:
Der Safe Mode ist auf "OFF" gesetzt, was notwendig ist, damit PHP-Skripte E-Mails versenden können, wie z. B. Kontaktformulare auf einer Webseite.
CGI-Ausführung:
PHP wird auf den Servern von DomainFactory als CGI ausgeführt, was eine sichere Ausführung ohne Sicherheitslücken ermöglicht.
Sollte also auch da laufen.

Ich kann meine Scripte nur auf meinem Server testen und lokal hier auf dem PC. Ich kann und will auch nicht jede mögliche Serverkonfiguration nach stellen. Wer Hoster hat die alles verbieten - dann ist das eben so.
Ich achte darauf das die Scripte PHP 8.x kompatibel sind, was meiner Meinung nach ausreicht.
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Das sehe ich gar nicht so - schon aus Sicherheitsgründen.

Offensichtlich lässt zum Beispiel der Server von Dieter eben nicht PHP mail() zu. PHP selbst wird unterstützt, jedoch Mail nur als SMTP. So hatte ich das zumindest gestern gegoogelt.


Das schreibt gerade eben nun mein ChatGPT dazu:

ChatGPT hat geschrieben:
Ich hab recherchiert — es gibt keine offizielle Bestätigung, dass DomainFactory explizit mail() unterdrückt, aber einige Hinweise und Erfahrungsberichte deuten darauf hin, dass es Einschränkungen und Probleme geben kann. Ich fasse zusammen:

Was man über DomainFactory weiß / Hinweise aus Nutzererfahrungen

1. SMTP / IMAP Postfächer werden unterstützt
User können E-Mails über Clients einrichten über SMTP/IMAP. Mailspring

2. Migration zu Microsoft 365 / MyMail Änderungen
DomainFactory migriert sein Mail-System / Postfächer teilweise zu Microsoft 365. Das kann Einfluss haben auf das Verhalten von SMTP und wie Postfächer verwaltet werden. BornCity+2hostingVZ+2

3. Support-Artikel zu häufigen Fehlern bei E-Mail-Konfiguration
In den FAQs von DomainFactory gibt es Artikel wie „Die häufigsten 10 Fehler bei der E-Mail-Konfiguration vermeiden“. Diese deuten darauf hin, dass viele Kunden Probleme haben — etwa mit falschem Absender, fehlendem SPF, Problems mit DKIM, oder dass E-Mails im Spam landen etc. df.eu

4. Erfahrungsberichte, dass PHP mail() nicht so zuverlässig funktioniert
In Foren / Reddit-Kreisen berichten Kunden, dass mail() manchmal nicht funktioniert oder nicht zugestellt wird, besonders wenn Absenderadresse, Envelope-Sender oder From nicht passend sind. Einige sagen auch, dass SMTP zwingend verlangt wird. Reddit+1

Mögliche Gründe, warum mail() bei DomainFactory fehlschlägt
Wenn bei deinem Formular unter DomainFactory mail() nicht funktioniert, könnten diese Gründe eine Rolle spielen:

Grund.jpg


Fazit

DomainFactory erlaubt vermutlich grundsätzlich die Nutzung von mail(), aber mit Einschränkungen und Bedingungen.

Es ist sehr wahrscheinlich, dass korrekte From-Adresse + Envelope-Sender, + Domain & DNS-Einträge (SPF/DKIM), + guter Content erforderlich sind, sonst wird eine E-Mail nicht versandt oder kaum zugestellt.

Viele nutzen daher SMTP (authentifiziert), weil es besser kontrollierbar ist und größere Zuverlässigkeit bietet.


Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Frage an ChatGPT:

Sind dir denn überhaupt Provider bekannt, die mail() nicht mehr unterstützen und nur noch SMTP verlangen? Du musst diese jetzt nicht aufführen, ich will nur ganz generell wissen, ob es solche Provider gibt.

ChatGPT hat geschrieben:
Ja 👍 – es gibt tatsächlich Provider, die mail() gar nicht mehr erlauben und ausschließlich SMTP verlangen.

Das hat verschiedene Gründe:

> Sicherheit: Mit mail() können leicht Spam-Skripte gebaut werden, da es keinen Authentifizierungszwang gibt.

> Missbrauch auf Shared-Hosting: Wenn ein Nachbaraccount massenhaft Spam über mail() verschickt, leidet die ganze Server-IP (Blacklist).

> Nachvollziehbarkeit: Bei SMTP lässt sich eindeutig nachvollziehen, welcher Kunde welche Mail verschickt hat.

> Kompatibilität mit SPF/DKIM/DMARC: Authentifizierte SMTP-Mails erfüllen die Anforderungen viel besser.


Viele große Hoster behalten mail() zwar (weil viele alte Skripte darauf basieren), schränken es aber stark ein:

Envelope-Sender muss exakt zum Account passen.

Limit pro Stunde/Tag.

Keine Weiterleitung über fremde Domains.

Und einige Hoster haben es komplett abgeschaltet – da geht nur noch SMTP.



👉 Kurz gesagt: Ja, es gibt Provider, die nur SMTP erlauben. Immer häufiger wird mail() außerdem so stark reglementiert, dass es praktisch nicht mehr nutzbar ist.
Nachtfalke
Mitglied (Level 10)
Mitglied (Level 10)
Beiträge: 177
Registriert: Mi 16. Dez 2020, 18:48
Wohnort: Main-Kinzig-Kreis, Hessen
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Nachtfalke »

Oh mein Gott… was ist denn nur mit der doofen Mailadresse los :confused:

Jetzt kann ich die Mailadresse noch nicht einmal in Outlook hinterlegen. Timeout usw.
Ich glaube, ich sollte mal die Kiste ausmachen, meinen Aussie Scully nehmen und für 2 Stunden mal an die frische Luft gehen und dann noch einmal von vorne beginnen.
Also mit der // SMTP-Konfiguration und so.
Ich werde Berichten.
Mobirise v6.1.4

Gruß
Dieter
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Ich würde Dir raten mal bei Deinem Provider anzurufen und zu fragen, ob mit Deiner Mail-Adresse alles OK ist, oder ob der Provider da was gesperrt hat?!
Nachtfalke
Mitglied (Level 10)
Mitglied (Level 10)
Beiträge: 177
Registriert: Mi 16. Dez 2020, 18:48
Wohnort: Main-Kinzig-Kreis, Hessen
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Nachtfalke »

Da werden ich wohl anrufen müssen. Da geht irgendwie was überhaupt nichts.
Mobirise v6.1.4

Gruß
Dieter
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Volker »

Tommy Herrmann hat geschrieben: Di 16. Sep 2025, 09:04 Das sehe ich gar nicht so - schon aus Sicherheitsgründen.
Unabhängig der Probleme die Dieter hat,
ist auch meine jetzige Version mit PHP mail() so sicher wie möglich. 100% wird es nie geben ;)

Gründe :
1. Feste Absenderadresse: Anstatt die E-Mail-Adresse des Benutzers in den From-Header einzufügen, wird eine feste, hardcodierte Adresse (noreply@domain.de) verwendet.

2. Sichere Header-Konstruktion: Die E-Mail-Header werden als Array ($headers = [...]) definiert und dann mit implode() korrekt zu einem String zusammengefügt. Dadurch kann ein Angreifer keine neuen Header-Zeilen mehr einschleusen.

Aber das ist nur meine Bescheidene Meinung als PHP Laie. Natürlich empfehle ich auch in allen Scripten die Mails an andere versenden, immer den SMTP Versand und PHPMailer. Habe ich auch in den Scripten Newsletter, Formular Generator, Vereinsverwaltung eingebaut und erwähne ich auch in den Videos.

Aber jetzt ist es ja dank Dir und Chat GPT sicherer mit dem PHPMailer ;)

PS: Das sagt die KI zu dem Script wegen Gefahr :
Verbleibende Risiken
DoS-Angriffe durch Spam: Obwohl Ihr Skript bereits einen Honeypot, eine Zeitprüfung und ein CAPTCHA verwendet, könnte ein sehr entschlossener Angreifer (oder ein menschlicher Spammer) das Formular weiterhin massenhaft absenden. Das würde zwar nicht Ihren Server direkt kompromittieren, aber die pending.json-Datei könnte mit Tausenden von Spam-Einträgen gefüllt werden, was die Verwaltung mühsam macht.

Kein CSRF-Schutz: Ihr Formular verwendet kein CSRF-Token (Cross-Site Request Forgery). Ein CSRF-Angriff wäre nur dann eine Gefahr, wenn ein Angreifer einen eingeloggten Admin dazu bringen könnte, eine schädliche Aktion auf Ihrer Website durchzuführen, ohne es zu wissen. In diesem Fall ist das Risiko gering, da das Formular nur neue Einträge hinzufügt. Bei Formularen mit sensiblen Aktionen (wie dem Löschen von Daten) wäre dies aber kritisch.
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Moin Volker,

es wäre sehr hilfreich, wenn Du mich künftig eindeutig darüber informierst, sobald Du Änderungen am Download vorgenommen hast, damit ich nicht erst danach suchen muss oder zufällig eine Andeutung in den Posts finde.

Die Datei "Gastbuch-V1.0.txt" wurde von Dir nicht aktualisiert, sodass niemand über die vorgenommenen Änderungen informiert ist. Außerdem fehlt der komplette "PHPMailer" in Deinem Download, was insbesondere für unerfahrene Benutzer zu Problemen führt, zumal Du diesen nirgends überhaupt erwähnst. Leute, die davon keine Ahnung haben, können das aus den Quellcodes der Skripte doch nicht erkennen :eek:

Ich habe alle Anpassungen auf meiner Tutorialseite ergänzt. Es ist ärgerlich, wenn dort etwas anderes steht als das, was die Benutzer tatsächlich bei Dir vorfinden.

https://www.mobirise-tutorials.com/Tuto ... Volker.php
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Volker,

bitte tausche das Skript "eintragsformular.php" von Deinem Gästebuch nochmals - ich poste es unten.

Es ist zwar kein echter Fehler, das Fallback hat aber unzuverlässig funktioniert. Bei mir kam die Mail erst nach 20 Minuten über das Fallback an. Jetzt unmittelbar:

Code: Alles auswählen

/**
 * Fallback: Versand per PHP mail() – versucht mehrere Varianten
 * 1) mit additional_params "-f<from>"
 * 2) ohne 5. Parameter
 * 3) ohne 5. Parameter + zusätzliche Sender/Return-Path Header
 */ 
Daran kann man auch schon die Problematik mit PHP mail() heutzutage sehen, das von den unterschiedlichen Providern sehr unterschiedlich behandelt wird. Bei so einer Situation wird die Mail vielleicht zurückgestellt und noch anderen Prüfungen unterzogen, sodass die Zustellung sogar Stunden dauern kann oder ganz ausbleibt.

ChatGPT hat geschrieben:
Warum kam die Fallback-Mail „verspätet“?

Wenn SMTP mit falschem Passwort fehlschlägt, springt dein Fallback (mail()) an. Bei Shared-Hostern (auch IONOS) werden mail()-Mails jedoch häufig:

> gegreylistet (Empfänger lehnt erst ab, akzeptiert beim 2. Versuch),

> gedrosselt oder intern in eine Queue gestellt,

> von Spamfiltern verzögert zugestellt.

Ergebnis: Die Mail taucht erst Minuten bis Stunden später auf – obwohl dein Skript korrekt durchlief.


Testen kann man das auch, indem man z.B. einfach bei dem SMTP-Passwort die Sterne drinnen lässt:

$SMTP_PASSWORD = '*******';

... dadurch ist die SMTP-Konfiguration ungültig und das Fallback greift.

Hier das neue Skript (10 x getestet) - vergiss den PHPMailer nicht auch mit in das ZIP zu packen.

eintragsformular.php

Code: Alles auswählen

<?php
/*******************************************************
 * Gästebuch – Eintrag + Admin-Benachrichtigung
 * Stand: 2025-09-17
 * Mit SMTP-Option für PHPMailer + mail()-Fallback
 *******************************************************/

session_start();
date_default_timezone_set('Europe/Berlin');

/* =========================
   KONFIGURATION
   ========================= */
$SITE_NAME            = 'Gästebuch-Volker';
$ADMIN_EMAIL          = 'Mail@DeineDomain.de';              // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS  = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS         = 'Mail@DeineDomain.de';              // ← Deine Mailbox beim Provider
$FROM_NAME            = $SITE_NAME;                         // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP      = true;                   // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST     = 'smtp.ionos.de';        // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT     = 587;                    // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH     = true;
$SMTP_USERNAME = 'Mail@DeineDomain.de';  // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******';              // Dein echtes Passwort eintragen
$SMTP_SECURE   = 'tls';                  // 'tls' oder 'ssl'

// Datendateien
$entries_file = __DIR__ . '/entries.json';
$pending_file = __DIR__ . '/pending.json';

/* =========================
   HILFSFUNKTIONEN
   ========================= */
function loadEntries(string $file): array {
    if (!file_exists($file)) return [];
    $content = @file_get_contents($file);
    if ($content === false || $content === '') return [];
    $data = json_decode($content, true);
    return is_array($data) ? $data : [];
}

function saveEntries(array $entries, string $file): void {
    $json = json_encode($entries, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    $fp = @fopen($file, 'c+');
    if ($fp === false) {
        error_log("Gästebuch: Datei kann nicht geöffnet werden: $file");
        return;
    }
    if (flock($fp, LOCK_EX)) {
        ftruncate($fp, 0);
        fwrite($fp, $json);
        fflush($fp);
        flock($fp, LOCK_UN);
    }
    fclose($fp);
}

function sanitizeInput(?string $input): string {
    return htmlspecialchars(trim((string)$input), ENT_QUOTES, 'UTF-8');
}

/* =========================
   MAIL-FUNKTIONEN (PHPMailer + Fallback mail())
   ========================= */

/**
 * SMTP-Versand per PHPMailer
 * (Änderung: Rückgabewert von $mail->send() wird geprüft; bei false -> Fallback möglich)
 */
function sendAdminNotificationSMTP(array $entry, string $admin_email, string $site_name, string $from_address, string $from_name): bool
{
    // PHPMailer laden – Pfade ggf. anpassen
    require_once __DIR__ . '/PHPMailer/src/Exception.php';
    require_once __DIR__ . '/PHPMailer/src/PHPMailer.php';
    require_once __DIR__ . '/PHPMailer/src/SMTP.php';

    // FIX: KEINE use-Statements innerhalb der Funktion!
    // => Vollqualifizierte Klassennamen verwenden:
    // \PHPMailer\PHPMailer\PHPMailer, \PHPMailer\PHPMailer\Exception

    global $SMTP_HOST, $SMTP_PORT, $SMTP_AUTH, $SMTP_USERNAME, $SMTP_PASSWORD, $SMTP_SECURE;

    $mail = new \PHPMailer\PHPMailer\PHPMailer(true);

    try {
        // Optionales Debugging ohne HTML-Ausgabe (bei Bedarf aktivieren)
        // $mail->SMTPDebug = \PHPMailer\PHPMailer\SMTP::DEBUG_SERVER;
        // $mail->Debugoutput = function($str, $level){ error_log("PHPMailer[$level]: $str"); };

        // SMTP-Konfiguration
        $mail->isSMTP();
        $mail->Host       = $SMTP_HOST;
        $mail->SMTPAuth   = $SMTP_AUTH;
        $mail->Username   = $SMTP_USERNAME;
        $mail->Password   = $SMTP_PASSWORD;
        $mail->SMTPSecure = $SMTP_SECURE; // 'tls' (587) oder 'ssl' (465)
        $mail->Port       = $SMTP_PORT;

        // Charset und Encoding
        $mail->CharSet  = 'UTF-8';
        $mail->Encoding = 'base64';

        // Absender (IONOS: echte Mailbox derselben Domain!)
        $mail->setFrom($from_address, $from_name);

        // Empfänger (Admin)
        $mail->addAddress($admin_email);

        // Reply-To (nur wenn valide Nutzeradresse vorhanden)
        if (!empty($entry['email']) && filter_var($entry['email'], FILTER_VALIDATE_EMAIL)) {
            $mail->addReplyTo($entry['email'], $entry['name'] ?? '');
        } else {
            $mail->addReplyTo($from_address, $from_name);
        }

        // Admin-URL bauen
        $is_https  = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on');
        $protocol  = $is_https ? 'https' : 'http';
        $host      = $_SERVER['HTTP_HOST'] ?? 'localhost';
        $baseDir   = rtrim(dirname($_SERVER['REQUEST_URI'] ?? '/'), '/\\');
        $admin_url = $protocol . '://' . $host . $baseDir . '/admin.php';

        // Inhalt (Plain Text)
        $mail->isHTML(false);
        $mail->Subject = "[$site_name] Neuer Gästebucheintrag wartet auf Freischaltung";

        $mail->Body =
            "Hallo Administrator,\n\n" .
            "ein neuer Eintrag in Ihr Gästebuch wartet auf Freischaltung:\n\n" .
            "═══════════════════════════════════════════════════════════════════\n\n" .
            "Name: " . ($entry['name'] ?? '-') . "\n" .
            "E-Mail: " . (!empty($entry['email']) ? $entry['email'] : 'Nicht angegeben') . "\n" .
            "Datum: " . ($entry['date'] ?? '-') . "\n\n" .
            "Kommentar:\n" . ($entry['comment'] ?? '-') . "\n\n" .
            "═══════════════════════════════════════════════════════════════════\n\n" .
            "Freischalten können Sie den Eintrag hier:\n" . $admin_url . "\n\n" .
            "Viele Grüße\nIhr Gästebuch-System";

        // >>> Änderung: send() Ergebnis prüfen
        $ok = $mail->send();
        if (!$ok) {
            error_log("Gästebuch: SMTP send() lieferte false: " . $mail->ErrorInfo);
            return false; // -> Fallback wird ausgelöst
        }

        error_log("Gästebuch: E-Mail erfolgreich per SMTP gesendet an $admin_email");
        return true;

    } catch (\PHPMailer\PHPMailer\Exception $e) {
        error_log("Gästebuch: SMTP-Fehler: " . $e->getMessage());
        return false; // -> Fallback wird ausgelöst
    }
}

/**
 * Fallback: Versand per PHP mail() – versucht mehrere Varianten
 * 1) mit additional_params "-f<from>"
 * 2) ohne 5. Parameter
 * 3) ohne 5. Parameter + zusätzliche Sender/Return-Path Header
 */
function sendAdminNotification(array $entry, string $admin_email, string $site_name, string $from_address, string $from_name): bool
{
    // Empfänger/From prüfen
    if (!filter_var($admin_email, FILTER_VALIDATE_EMAIL)) {
        error_log("Gästebuch: Ungültige Admin E-Mail-Adresse: $admin_email");
        return false;
    }
    if (!filter_var($from_address, FILTER_VALIDATE_EMAIL)) {
        error_log("Gästebuch: Ungültige FROM-Adresse: $from_address");
        return false;
    }

    // Betreff (UTF-8, MIME)
    $raw_subject = "[$site_name] Neuer Gästebucheintrag wartet auf Freischaltung";
    if (function_exists('mb_encode_mimeheader')) {
        $subject = mb_encode_mimeheader($raw_subject, 'UTF-8', 'B', "\r\n");
    } else {
        $subject = "=?UTF-8?B?" . base64_encode($raw_subject) . "?=";
    }

    // Admin-URL bauen
    $is_https  = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on');
    $protocol  = $is_https ? 'https' : 'http';
    $host      = $_SERVER['HTTP_HOST'] ?? 'localhost';
    $baseDir   = rtrim(dirname($_SERVER['REQUEST_URI'] ?? '/'), '/\\');
    $admin_url = $protocol . '://' . $host . $baseDir . '/admin.php';

    // Nachricht (CRLF verwenden)
    $message =
        "Hallo Administrator,\r\n\r\n" .
        "ein neuer Eintrag in Ihr Gästebuch wartet auf Freischaltung:\r\n\r\n" .
        "═══════════════════════════════════════════════════════════════════\r\n\r\n" .
        "Name: " . ($entry['name'] ?? '-') . "\r\n" .
        "E-Mail: " . (!empty($entry['email']) ? $entry['email'] : 'Nicht angegeben') . "\r\n" .
        "Datum: " . ($entry['date'] ?? '-') . "\r\n\r\n" .
        "Kommentar:\r\n" . ($entry['comment'] ?? '-') . "\r\n\r\n" .
        "═══════════════════════════════════════════════════════════════════\r\n\r\n" .
        "Freischalten können Sie den Eintrag hier:\r\n" . $admin_url . "\r\n\r\n" .
        "Viele Grüße\r\nIhr Gästebuch-System";

    // Reply-To: wenn Nutzer-Mail valide, dorthin – sonst From
    $reply_to = (!empty($entry['email']) && filter_var($entry['email'], FILTER_VALIDATE_EMAIL))
        ? $entry['email']
        : $from_address;

    // Absender-Anzeigename MIME-encoden
    $from_display = function_exists('mb_encode_mimeheader')
        ? mb_encode_mimeheader($from_name, 'UTF-8', 'B', "\r\n")
        : "=?UTF-8?B?" . base64_encode($from_name) . "?=";

    // Basis-Header
    $base_headers = [
        "MIME-Version: 1.0",
        "Content-Type: text/plain; charset=UTF-8",
        "From: {$from_display} <{$from_address}>",
        "Reply-To: {$reply_to}",
        "X-Mailer: PHP/" . phpversion(),
    ];
    $headers_str = implode("\r\n", $base_headers);

    // Variante A: mit additional_params (-f)
    $params = '-f' . $from_address;
    $okA = @mail($admin_email, $subject, $message, $headers_str, $params);
    error_log("GB mail(): Variante A (-f) => " . ($okA ? "OK" : "FEHLER"));

    if ($okA) return true;

    // Variante B: ohne 5. Parameter
    $okB = @mail($admin_email, $subject, $message, $headers_str);
    error_log("GB mail(): Variante B (ohne -f) => " . ($okB ? "OK" : "FEHLER"));

    if ($okB) return true;

    // Variante C: ohne 5. Parameter + zusätzliche Sender/Return-Path Header
    $headers_str_c = $headers_str . "\r\n" .
        "Sender: {$from_address}\r\n" .
        "Return-Path: {$from_address}";
    $okC = @mail($admin_email, $subject, $message, $headers_str_c);
    error_log("GB mail(): Variante C (Sender/Return-Path Header) => " . ($okC ? "OK" : "FEHLER"));

    if ($okC) return true;

    // Alles fehlgeschlagen
    error_log("Gästebuch: FEHLER bei mail() (alle Varianten) an $admin_email (From: $from_address)");
    return false;
}

/* =========================
   FORMULARVERARBEITUNG
   ========================= */
$message = '';
$error   = '';

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST' && ($_POST['action'] ?? '') === 'add_entry') {

    // CAPTCHA prüfen
    $captcha_input   = sanitizeInput($_POST['captcha'] ?? '');
    $captcha_correct = isset($_SESSION['captcha']) && (mb_strtolower($captcha_input) === mb_strtolower($_SESSION['captcha']));

    // Spam-Schutz (Honeypot + Mindestzeit)
    $honeypot_ok = empty($_POST['website'] ?? '');
    $time_ok     = (isset($_POST['form_start_time']) && (time() - (int)$_POST['form_start_time'] >= 3));

    if (!$honeypot_ok || !$time_ok || !$captcha_correct) {
        $error = 'Ihre Anfrage konnte nicht verarbeitet werden. Bitte stellen Sie sicher, dass das CAPTCHA korrekt ausgefüllt ist.';
    } else {
        $name    = sanitizeInput($_POST['name'] ?? '');
        $email   = sanitizeInput($_POST['email'] ?? '');
        $comment = sanitizeInput($_POST['comment'] ?? '');

        if ($name === '' || $comment === '') {
            $error = 'Name und Kommentar sind Pflichtfelder.';
        } else {
            $pending  = loadEntries($pending_file);
            $newEntry = [
                'id'      => bin2hex(random_bytes(8)),
                'name'    => $name,
                'email'   => $email,
                'comment' => $comment,
                'date'    => date('d.m.Y H:i:s'),
            ];
            $pending[] = $newEntry;
            saveEntries($pending, $pending_file);

            // E-Mail an Admin
            $email_sent = false; // FIX: initialisieren, um Notice zu vermeiden
            if ($EMAIL_NOTIFICATIONS && !empty($ADMIN_EMAIL)) {

                if ($USE_SMTP === true) {
                    // 1) SMTP versuchen
                    $email_sent = sendAdminNotificationSMTP(
                        $newEntry,
                        $ADMIN_EMAIL,
                        $SITE_NAME,
                        $FROM_ADDRESS,
                        $FROM_NAME
                    );

                    // 2) Fallback auf mail(), wenn SMTP fehlschlägt
                    if (!$email_sent) { // Fallback
                        $email_sent = sendAdminNotification(
                            $newEntry,
                            $ADMIN_EMAIL,
                            $SITE_NAME,
                            $FROM_ADDRESS,
                            $FROM_NAME
                        );
                    }
                } else {
                    // SMTP deaktiviert → direkt mail()
                    $email_sent = sendAdminNotification(
                        $newEntry,
                        $ADMIN_EMAIL,
                        $SITE_NAME,
                        $FROM_ADDRESS,
                        $FROM_NAME
                    );
                }

                if ($email_sent) {
                    $message = 'Ihr Eintrag wurde übermittelt und der Administrator wurde per E-Mail benachrichtigt. Ihr Eintrag wartet auf Freischaltung.';
                } else {
                    $message = 'Ihr Eintrag wurde übermittelt und wartet auf Freischaltung. (E-Mail-Benachrichtigung fehlgeschlagen - bitte Admin kontaktieren)';
                    error_log("Gästebuch: E-Mail-Benachrichtigung konnte nicht gesendet werden");
                }
            } else {
                $message = 'Ihr Eintrag wurde übermittelt und wartet auf Freischaltung durch den Administrator.';
            }
        }
    }
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gästebuch - Eintrag verfassen</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.10.0/font/bootstrap-icons.min.css" rel="stylesheet">
    <script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@1/index.js"></script>
    <style>
        body { margin-bottom: 50px; }
        .form-card { box-shadow: 0 10px 30px rgba(0,0,0,0.1); border: none; }
        .honeypot { position: absolute; left: -9999px; visibility: hidden; }
        ::placeholder { color: black; opacity: 0.5!important; font-size: 1.0rem; }
    </style>
    <!-- Resize-Skript -->
    <script>
        window.addEventListener("load", fenster);
        window.addEventListener("resize", fenster);
        function fenster() {
          if (parent.document.getElementsByTagName("iframe")[0]) {
            parent.document.getElementsByTagName("iframe")[0].style.height =
              document.getElementsByTagName("html")[0].offsetHeight +'px';
          }
        }
    </script>
</head>
<body class="bg-light">
    <div class="container my-5">
        <div class="row justify-content-center">
            <div class="col-lg-8">
                <div class="d-flex justify-content-between mb-4">
                    <a href="index.php" class="btn btn-outline-primary">
                        <i class="bi bi-arrow-left"></i> Zurück zum Gästebuch
                    </a>
                    <a href="admin.php" class="btn btn-outline-secondary">
                        <i class="bi bi-shield-lock"></i> Admin-Bereich
                    </a>
                </div>

                <?php if (!empty($message)): ?>
                    <div class="alert alert-success alert-dismissible fade show" role="alert">
                        <i class="bi bi-check-circle"></i> <?= $message ?>
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    </div>
                <?php endif; ?>

                <?php if (!empty($error)): ?>
                    <div class="alert alert-danger alert-dismissible fade show" role="alert">
                        <i class="bi bi-exclamation-circle"></i> <?= $error ?>
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    </div>
                <?php endif; ?>

                <div class="card mb-5 form-card">
                    <div class="card-header bg-primary text-white">
                        <h5 class="mb-0"><i class="bi bi-plus-circle"></i> Neuen Eintrag verfassen</h5>
                    </div>
                    <div class="card-body p-4">
                        <form method="POST" novalidate>
                            <input type="hidden" name="action" value="add_entry">
                            <input type="hidden" name="form_start_time" value="<?= time() ?>">

                            <div class="row">
                                <div class="col-md-6 mb-3">
                                    <label for="name" class="form-label fw-semibold">Name *</label>
                                    <input type="text" class="form-control form-control-lg" id="name" name="name" placeholder="Dein Name" required>
                                </div>
                                <div class="col-md-6 mb-3">
                                    <label for="email" class="form-label fw-semibold">E-Mail (optional, nur für Admin sichtbar)</label>
                                    <input type="email" class="form-control form-control-lg" id="email" name="email" placeholder="Deine E-Mail optional">
                                </div>
                            </div>

                            <div class="honeypot">
                                <label for="website">Website (nicht ausfüllen)</label>
                                <input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
                            </div>

                            <div class="mb-4">
                                <label for="comment" class="form-label fw-semibold">Kommentar *</label>
                                <textarea class="form-control" id="comment" name="comment" rows="5"
                                          placeholder="Schreibe deinen Kommentar" required></textarea>
                                <div class="mt-2">
                                    <emoji-picker></emoji-picker>
                                </div>
                            </div>

                            <div class="mb-4">
                                <label for="captcha" class="form-label fw-semibold">Sicherheitscode eingeben *</label>
                                <div class="row g-3 align-items-center">
                                    <div class="col-6">
                                        <img src="captcha.php" alt="CAPTCHA Bild" class="img-fluid border rounded"
                                             onclick="this.src='captcha.php?v='+Math.random()">
                                    </div>
                                    <div class="col-6">
                                        <input type="text" class="form-control form-control-lg" id="captcha" name="captcha" required>
                                    </div>
                                </div>
                                <small class="form-text text-muted mt-2 d-block">
                                    Klicke auf den Code, um das Captcha neu zu laden
                                </small>
                            </div>

                            <div class="d-grid">
                                <button type="submit" class="btn btn-primary btn-lg">
                                    <i class="bi bi-send"></i> Eintrag senden
                                </button>
                            </div>
                        </form>
                    </div>
                </div>

                <div class="text-center mt-5 pt-4 border-top">
                    <p class="text-muted">
                        <i class="bi bi-heart-fill text-danger"></i>
                        Vielen Dank für Deinen Besuch!
                    </p>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
    <script>
        // Emojis einfügen
        document.querySelector('emoji-picker')?.addEventListener('emoji-click', event => {
            const textarea = document.getElementById('comment');
            if (!textarea) return;
            const emoji = event.detail.unicode;
            const startPos = textarea.selectionStart || 0;
            const endPos = textarea.selectionEnd || 0;
            textarea.value = textarea.value.substring(0, startPos) + emoji + textarea.value.substring(endPos);
            textarea.selectionStart = textarea.selectionEnd = startPos + emoji.length;
            textarea.focus();
        });
    </script>
</body>
</html>
Volker
Moderator
Moderator
Beiträge: 1431
Registriert: Sa 12. Dez 2020, 22:35

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Volker »

PHPMailer, überarbeitete eintragsformular.php und neue Readme.txt sind nun im Download:


https://www.niederastroth.de/gästebuch.7z
Gruß Volker
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Moin,

danke -na bestens :tu:

Nun hoffen wir mal, dass auch Dieter Erfolg haben wird. Im Moment kann ich mir nicht vorstellen wo es da noch haken könnte.

@ Dieter,

lies Dir auch nochmals mein Tutorial zum Gästebuch durch - da habe ich noch vieles angepasst:

https://www.mobirise-tutorials.com/Tuto ... Volker.php
Nachtfalke
Mitglied (Level 10)
Mitglied (Level 10)
Beiträge: 177
Registriert: Mi 16. Dez 2020, 18:48
Wohnort: Main-Kinzig-Kreis, Hessen
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Nachtfalke »

OK... Danke
Ich mache mich gleich mal dran zu Testen.
Mobirise v6.1.4

Gruß
Dieter
Nachtfalke
Mitglied (Level 10)
Mitglied (Level 10)
Beiträge: 177
Registriert: Mi 16. Dez 2020, 18:48
Wohnort: Main-Kinzig-Kreis, Hessen
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Nachtfalke »

So- Test abgeschlossen.
Meldung: Ihr Eintrag wurde übermittelt und der Administrator wurde per E-Mail benachrichtigt. Ihr Eintrag wartet auf Freischaltung. Das ist ja schon einmal sehr gut.

Was aber nicht gut ist, dass nach dem Klick auf "Eintrag senden" es ca. 2 Minuten dauert bis die Meldung kommt, dass Eintrag an den Administrator übermittelt wurde.

Das ist definitiv zu lange. Könnte das bitte mal einer Testen ?

https://aussie-scully.de/gaestebuch.php
Mobirise v6.1.4

Gruß
Dieter
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Moin,

zunächst beantworte bitte mal diese Fragen:

1) Hast Du das neueste Skript "eintragsformular.php" von HEUTE verwende?

2) Hast Du die korrekten Daten für SMTP oben eingetragen?

3) Kopiere doch bitte mal diese Zeilen der Konfiguration und entferne zuvor Dein Passwort:


Code: Alles auswählen

/* =========================
   KONFIGURATION
   ========================= */
$SITE_NAME            = 'Gästebuch-Volker';
$ADMIN_EMAIL          = 'Mail@DeineDomain.de';              // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS  = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS         = 'Mail@DeineDomain.de';              // ← Deine Mailbox beim Provider
$FROM_NAME            = $SITE_NAME;                         // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP      = true;                   // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST     = 'smtp.ionos.de';        // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT     = 587;                    // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH     = true;
$SMTP_USERNAME = 'Mail@DeineDomain.de';  // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******';              // Dein echtes Passwort eintragen
$SMTP_SECURE   = 'tls';                  // 'tls' oder 'ssl'

Für mich hört sich diese Verzögerung der Zustellung eben genauso an, wie es auch mir bei meinem Test vorhin ergangen ist. Das SMTP scheint falsch konfiguriert und dann wird anstelle dessen mit PHP mail() gesendet, was Dein Server nur bedingt zulässt oder was dann zu längeren Verzögerungen kommt.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Da stimmt was überhaupt nicht bei Deinem Einbau.

Ich bekomme keine Anzeige, dass der Eintrag vorgenommen wurde. Die Seite bleibt hängen.

Da scheinst Du etwas falsch gemacht zu haben.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 7752
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Tommy Herrmann »

Die mittels iFrame verlinkte Seite ist auch so nicht aufrufbar - das darf hier nicht sein:

https://aussie-scully.de/gaestebuch/index.php

Du hast wahrscheinlich das Skript mit der Umleitung oben eingebaut aber mit einem falschen Link. Entferne das mal zunächst, damit man auch die geframte Seite prüfen kann (ohne die Mobirise-Seite).
Nachtfalke
Mitglied (Level 10)
Mitglied (Level 10)
Beiträge: 177
Registriert: Mi 16. Dez 2020, 18:48
Wohnort: Main-Kinzig-Kreis, Hessen
Kontaktdaten:

Re: Gästebuch ohne Datenbank

Ungelesener Beitrag von Nachtfalke »

Tommy Herrmann hat geschrieben: Mi 17. Sep 2025, 09:59 Moin,

zunächst beantworte bitte mal diese Fragen:

1) Hast Du das neueste Skript "eintragsformular.php" von HEUTE verwende?

2) Hast Du die korrekten Daten für SMTP oben eingetragen?

3) Kopiere doch bitte mal diese Zeilen der Konfiguration und entferne zuvor Dein Passwort:


Code: Alles auswählen

/* =========================
   KONFIGURATION
   ========================= */
$SITE_NAME            = 'Gästebuch-Volker';
$ADMIN_EMAIL          = 'Mail@DeineDomain.de';              // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS  = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS         = 'Mail@DeineDomain.de';              // ← Deine Mailbox beim Provider
$FROM_NAME            = $SITE_NAME;                         // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP      = true;                   // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST     = 'smtp.ionos.de';        // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT     = 587;                    // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH     = true;
$SMTP_USERNAME = 'Mail@DeineDomain.de';  // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******';              // Dein echtes Passwort eintragen
$SMTP_SECURE   = 'tls';                  // 'tls' oder 'ssl'

Für mich hört sich diese Verzögerung der Zustellung eben genauso an, wie es auch mir bei meinem Test vorhin ergangen ist. Das SMTP scheint falsch konfiguriert und dann wird anstelle dessen mit PHP mail() gesendet, was Dein Server nur bedingt zulässt oder was dann zu längeren Verzögerungen kommt.

Ich glaub ich habe den Fehler gefunden.

Diesen PORT Eintrag hatte ich für ssl:
$SMTP_PORT = 465; // 587 = STARTTLS (tls), 465 = SMTPS (ssl)

Aber diesen auf tsl:
$SMTP_SECURE = 'tsl'; // 'tls' oder 'ssl'


Und so habe ich das jetzt eingetragen:
/* =========================
KONFIGURATION
========================= */
$SITE_NAME = 'Gästebuch-Scully';
$ADMIN_EMAIL = 'wuff@aussie-scully.de'; // ← Empfänger (Admin)
$EMAIL_NOTIFICATIONS = true;

// From/Envelope-Sender MUSS eine echte Mailbox derselben Domain sein!
$FROM_ADDRESS = 'wuff@aussie-scully.de'; // ← Deine Mailbox beim Provider
$FROM_NAME = $SITE_NAME; // Anzeigename im From-Header

// SMTP-Konfiguration
$USE_SMTP = true; // SMTP verwenden (true) – bei false wird direkt mail() genutzt
$SMTP_HOST = 'sslout.df.eu'; // SMTP Host eintragen - hier beispielhaft von IONOS
$SMTP_PORT = 465; // 587 = STARTTLS (tls), 465 = SMTPS (ssl)
$SMTP_AUTH = true;
$SMTP_USERNAME = 'wuff@aussie-scully.de'; // Richtiger Login (meist identisch mit From-Adresse)
$SMTP_PASSWORD = '*******'; // Dein echtes Passwort eintragen
$SMTP_SECURE = 'ssl'; // 'tls' oder 'ssl'

Jetzt sollte da auch nix mehr hängen. Kannst Du das bitte noch einmal Testen ?
Mobirise v6.1.4

Gruß
Dieter
Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste