From d9b8177038f1f7e9eee603ff5f6cbfc2b75ead43 Mon Sep 17 00:00:00 2001 From: eclipse Date: Mon, 3 Mar 2025 12:11:49 +0100 Subject: [PATCH] rewrote logic in newsletter scripts, refactored code, moved file locations, --- content/pages/termine.md.metadata | 2 +- content/php/confirm.php | 85 ++++++-------- content/php/settings.php | 109 ++++++++++++------ content/php/subscribe.php | 54 +++++---- content/php/unsubscribe.php | 68 +++++------ pelicanconf.py | 10 +- theme/templates/contact.html | 2 +- theme/templates/includes/subscribe.html | 2 +- theme/templates/includes/unsubscribe.html | 2 +- theme/templates/index.html | 5 +- .../{termine.noformat.html => termine.html} | 2 +- 11 files changed, 187 insertions(+), 154 deletions(-) rename theme/templates/{termine.noformat.html => termine.html} (81%) diff --git a/content/pages/termine.md.metadata b/content/pages/termine.md.metadata index 1ad4c95..9d1fae6 100644 --- a/content/pages/termine.md.metadata +++ b/content/pages/termine.md.metadata @@ -1,7 +1,7 @@ title: Termine author: Tobias Radloff summary: Lesungen und Veranstaltungen -template: termine.noformat +template: termine lang: de category: Termine slug: termine diff --git a/content/php/confirm.php b/content/php/confirm.php index 91e43b6..79fde37 100644 --- a/content/php/confirm.php +++ b/content/php/confirm.php @@ -5,62 +5,51 @@ require(dirname(__FILE__) . '/settings.php'); $successURL = '/newsletter/confirmed.html'; $errorURL = '/newsletter/confirm-error.html'; +$err = 'Bestätigung fehlgeschlagen'; // Adds new subscriber to database. Returns an error message on failure, TRUE on success. function AddSubscriberToDB($subscriberAddress, $subscriberName = NULL) { - global $general; - - try { - $pdo = getPDO(); - - // create table if it doesn't exist already - $query = $pdo->prepare($general['sql']['create_table']); - if ( ! $query->execute() ) { - error_log('Datenbankfehler beim Prüfen/Erzeugen der Tabelle.'); - return "Ein Fehler ist aufgetreten."; - } - - // check if record exists - $query = $pdo->prepare($general['sql']['read_record']); - if ( ! $query->execute([':e' => $subscriberAddress]) ) { - error_log("Datenbankfehler: Adresscheck für Emailadresse {$subscriberAddress} ergab einen Fehler."); - return 'Datenbankfehler.'; - } - if ( $query->fetch() ) { - error_log("Datenbankfehler: Emailadresse {$subscriberAddress} ist bereits eingetragen."); - return "Emailadresse ist bereits eingetragen."; - } + $pdo = getPDO(); - // create record - $query = $pdo->prepare($general['sql']['create_record']); - if ( ( ! $query->execute([':e' => $subscriberAddress, ':n' => $subscriberName]) ) or ( $query->fetch() ) ) { - error_log("Datenbankfehler: Einfügen von Emailadresse {$subscriberAddress} ergab einen Fehler."); - return 'Datenbankfehler.'; - } - } catch(\PDOException $e) { - error_log("Datenbankfehler: {$e->getMessage()}"); - return $e->getMessage(); + // check if record exists + $check = NotAlreadySubscribed($subscriberAddress, $pdo); + if ( gettype($check) == 'string' ) { + return $check; + } + + // create record + global $general; + $query = $pdo->prepare($general['sql']['create_record']); + if ( ( ! $query->execute([':e' => $subscriberAddress, ':n' => $subscriberName]) ) or ( $query->fetch() ) ) { +// error_log("Datenbankfehler: Einfügen von Emailadresse {$subscriberAddress} ergab einen Fehler."); + return 'Fehler beim Eintragen in die Datenbank'; } return TRUE; } -if (isset($_GET['c']) && isset($_GET['e'])) { - $c = filter_var($_GET['c'], FILTER_SANITIZE_STRING); - $e = filter_var($_GET['e'], FILTER_SANITIZE_STRING); - if ( GetConfirmationHash($e) === $c ) { - $result = AddSubscriberToDB($e); - if ($result === TRUE) { - GracefulExit($successURL, 'Bestätigung erfolgt: Newsletter-Anmeldung bestätigt'); - } elseif (gettype($result == 'string')) { - GracefulExit($errorURL, "Bestätigung fehlgeschlagen: {$result}"); - } else { - GracefulExit($errorURL, 'Bestätigung fehlgeschlagen: Unbekannter Fehler'); - } - } else { - GracefulExit($errorURL, 'Bestätigung fehlgeschlagen: Fehlerhafter Hash'); - } -} else { - GracefulExit($errorURL, 'Bestätigung fehlgeschlagen: Fehlende Emailadresse oder Hash'); +// check if hash and email parameters are both set +if ( ! (isset($_GET['c']) and isset($_GET['e'])) ) { + GracefulExit($errorURL, "{$err}: Fehlende Emailadresse oder Hash"); } + +// check if hash is correct +$c = filter_var($_GET['c'], FILTER_SANITIZE_STRING); +$e = filter_var($_GET['e'], FILTER_SANITIZE_STRING); +if ( GetConfirmationHash($e) != $c ) { + GracefulExit($errorURL, "{$err}: Fehlerhafter Hash"); +} + +// add email to database +try { + $result = AddSubscriberToDB($e); + if ( gettype($result) == 'string' ) { + GracefulExit($errorURL, "{$err}: {$result}"); + } +} catch(\PDOException $e) { + GracefulExit($errorURL, "{$err}: {$e->getMessage()}"); +} + +// success +GracefulExit($successURL, 'Bestätigung erfolgt: Newsletter-Anmeldung bestätigt'); ?> \ No newline at end of file diff --git a/content/php/settings.php b/content/php/settings.php index 44979e6..d4215e6 100644 --- a/content/php/settings.php +++ b/content/php/settings.php @@ -5,9 +5,9 @@ use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; $dname = dirname(__FILE__); -require $dname . '/Exception.php'; -require $dname . '/PHPMailer.php'; -require $dname . '/SMTP.php'; +require $dname . '/../Exception.php'; +require $dname . '/../PHPMailer.php'; +require $dname . '/../SMTP.php'; // general constants $general = [ @@ -17,7 +17,7 @@ $general = [ // string concatenated with email address to create a non-recreatable md5 hash 'uniqueKey' => '***REMOVED***', // works like password salt // file name of confirm script - 'confirmScript' => '/confirm.php', + 'confirmScript' => '/newsletter/confirm.php', // status code to be used when redirection to success or error page 'statusCode' => 'HTTP/1.1 303 See Other', // array of SQL statements used @@ -61,7 +61,7 @@ $mailConfirmation = [ // database information $db = [ 'sqlite' => [ - 'dsn' => 'sqlite:../newsletter.sqlite', + 'dsn' => 'sqlite:../../newsletter.sqlite', ], 'mysql' => [ 'dsn' => '', @@ -74,7 +74,7 @@ $db = [ function GetConfirmationHash($confEmail) { global $general; - return md5($confEmail . $general['uniqueKey'] ); + return md5($confEmail . $general['uniqueKey']); } // connects to database and returns PDO object @@ -83,47 +83,79 @@ function getPDO($dbType = 'sqlite') { return new \PDO($db[$dbType]['dsn']); } -// Sends an email to single recipient with subject and body specified in an array. Returns an error message on failure, TRUE on success. +// Sends an email to single recipient with subject and body specified in an array function SendEmail($recipientAddress, $mailContents, $link = NULL) { global $general, $smtp; - $mail = new PHPMailer(true); - try { - //Server settings -// $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output - $mail->isSMTP(); - $mail->Host = $smtp["host"]; - $mail->SMTPAuth = $smtp["auth"]; - $mail->Username = $smtp["username"]; - $mail->Password = $smtp["password"]; - //$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption - $mail->Port = $smtp["port"]; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` + //Server settings + // $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output + $mail->isSMTP(); + $mail->Host = $smtp["host"]; + $mail->SMTPAuth = $smtp["auth"]; + $mail->Username = $smtp["username"]; + $mail->Password = $smtp["password"]; + //$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption + $mail->Port = $smtp["port"]; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` - //Recipients - $mail->setFrom($smtp["fromAddress"], $smtp["fromName"]); - $mail->addAddress($recipientAddress); //Add a recipient + //Recipients + $mail->setFrom($smtp["fromAddress"], $smtp["fromName"]); + $mail->addAddress($recipientAddress); //Add a recipient - //Content - if (isset($link)) { - $mailContents["bodyHTML"] = str_replace("%Placeholder%", $link, $mailContents["bodyHTML"]); - $mailContents["bodyText"] = str_replace("%Placeholder%", $link, $mailContents["bodyText"]); - } - $mail->CharSet = "UTF-8"; - $mail->isHTML(true); - $mail->Subject = $mailContents["subject"]; - $mail->Body = $mailContents["bodyHTML"]; - $mail->AltBody = $mailContents["bodyText"]; - - $mail->send(); - return TRUE; - } catch (Exception $e) { - error_log("Message error: {$e}"); - return FALSE; + //Content + if (isset($link)) { + $mailContents["bodyHTML"] = str_replace("%Placeholder%", $link, $mailContents["bodyHTML"]); + $mailContents["bodyText"] = str_replace("%Placeholder%", $link, $mailContents["bodyText"]); } + $mail->CharSet = "UTF-8"; + $mail->isHTML(true); + $mail->Subject = $mailContents["subject"]; + $mail->Body = $mailContents["bodyHTML"]; + $mail->AltBody = $mailContents["bodyText"]; + + $mail->send(); } -// redirects to specified URL via GET request and conveys an optional message + +function MakeSureTableExists($pdo) { + global $general; + $query = $pdo->prepare($general['sql']['create_table']); + if ( ! $query->execute() ) { +// error_log('Unbekannter Datenbankfehler beim Prüfen/Erzeugen der Tabelle.'); + return "Unbekannter Datenbankfehler"; + } + return TRUE; +} + +// returns true if record does not yet exist in database; error string otherwise +function NotAlreadySubscribed($email, $pdo = NULL) { + if (!isset($pdo)) { + $pdo = getPDO(); + } + + $result = MakeSureTableExists($pdo); + if ( gettype($result) == "string" ) { +// error_log("Datenbankfehler beim Adresscheck: {$result}"); + return $result; + } + + global $general; + $query = $pdo->prepare($general['sql']['read_record']); + if ( ! $query->execute([':e' => $email]) ) { +// error_log("Datenbankfehler: Adresscheck für Emailadresse {$email} ergab einen Fehler."); + return "Fehler beim Zugriff auf Datenbank"; + } + + if ( $query->fetch() ) { +// error_log("Adresscheck: Emailadresse {$email} ist bereits eingetragen."); + return "Emailadresse {$email} ist bereits eingetragen"; + } + + // success + return TRUE; +} + +// redirects to specified URL via GET request and conveys an optional message; then exits function GracefulExit($location, $message = NULL) { global $general; header($general['statusCode']); @@ -132,5 +164,6 @@ function GracefulExit($location, $message = NULL) { error_log($location); } header("Location: {$location}"); + exit; } ?> \ No newline at end of file diff --git a/content/php/subscribe.php b/content/php/subscribe.php index 9ca2276..1ac071a 100644 --- a/content/php/subscribe.php +++ b/content/php/subscribe.php @@ -1,28 +1,42 @@ GetConfirmationHash($email), 'e' => $email]); - $confirmLink = $general['siteURL'] . $general['confirmScript'] . "?" . $confirmQuery; - - $result = SendEmail($email, $mailConfirmation, $confirmLink); - if ( $result === TRUE ) { - GracefulExit($successURL, 'Anmeldung wird fortgesetzt: Email mit Bestätigungslink wurde versandt.'); - } else { - GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Fehler beim Versenden der Bestätigungs-Email.'); - } - } else { - GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Ungültige Emailadresse.'); - } -} else { - GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Keine Emailadresse angegeben.'); +// check if email parameter is set +if ( ! isset($_POST['email']) ) { + GracefulExit($errorURL, "{$err}: Keine Emailadresse angegeben."); } + +// check if it's a well-formed email address +$email = filter_var(trim($_POST['email'], FILTER_SANITIZE_STRING)); +if ( ! filter_var($email, FILTER_VALIDATE_EMAIL)) { + GracefulExit($errorURL, "{$err}: Ungültige Emailadresse {$email}"); +} + +// check whether address is already subscribed +try { + $check = NotAlreadySubscribed($email); + if ( gettype($check) == 'string' ) { + GracefulExit($errorURL, "{$err}: {$check}."); + } +} catch (\PDOException $e) { + GracefulExit($errorURL, "{$err}: {$e->getMessage()}"); +} + +// send email with confirmation link +$confirmQuery = http_build_query(['c' => GetConfirmationHash($email), 'e' => $email]); +$confirmLink = $general['siteURL'] . $general['confirmScript'] . "?" . $confirmQuery; +try { + SendEmail($email, $mailConfirmation, $confirmLink); +} catch (Exception $e) { + GracefulExit($errorURL, "{$err}: {$e->getMessage()}"); +} + +// success +GracefulExit($successURL, "Anmeldung erfolgreich: Email mit Bestätigungslink wurde an {$email} versandt."); ?> \ No newline at end of file diff --git a/content/php/unsubscribe.php b/content/php/unsubscribe.php index 1786cd1..30a1d73 100644 --- a/content/php/unsubscribe.php +++ b/content/php/unsubscribe.php @@ -4,49 +4,45 @@ require(dirname(__FILE__) . '/settings.php'); $successURL = '/newsletter/unsubscribed.html'; $errorURL = '/newsletter/unsubscribe-error.html'; - +$err = "Abmeldung fehlgeschlagen"; function RemoveSubscriberFromDB($subscriberAddress) { + $pdo = getPDO(); + + // make sure record exists + $check = NotAlreadySubscribed($subscriberAddress, $pdo); + if ( gettype($check) == 'string' ) { + return $check; + } + + // delete record global $general; - - try { - $pdo = getPDO(); - - // make sure record exists - $query = $pdo->prepare($general['sql']['read_record']); - if ( ! $query->execute([':e' => $subscriberAddress]) ) { - error_log("Datenbankfehler: Adresscheck für {$subscriberAddress} ergab einen Fehler."); - return 'Datenbankfehler.'; - } - if ( ! $query->fetch() ) { - error_log("Datenbankfehler: Emailadresse {$subscriberAddress} nicht in Datenbank vorhanden."); - return "Emailadresse nicht bekannt."; - } - - // delete record - $query = $pdo->prepare($general['sql']['delete_record']); - if ( ! $query->execute([':e' => $subscriberAddress])) { - error_log("Datenbankfehler: Löschen von Emailadresse {$subscriberAddress} ergab einen Fehler."); - return 'Fehler beim Löschen des Datenbankeintrags.'; - } - } catch(\PDOException $e) { - error_log("Datenbankfehler: {$e->getMessage()}"); - return $e->getMessage(); + $query = $pdo->prepare($general['sql']['delete_record']); + if ( ! $query->execute([':e' => $subscriberAddress])) { + return "Fehler beim Löschen des Datenbankeintrags für {$subscriberAddress}."; } return TRUE; } -if (isset($_GET['e'])) { - $e = filter_var($_GET["e"], FILTER_SANITIZE_STRING); +// check if hash and email parameters are both set +if ( ! (isset($_GET['c']) and isset($_GET['e'])) ) { + GracefulExit($errorURL, "{$err}: Fehlende Emailadresse oder Hash"); +} + +// check if hash is correct +$c = filter_var($_GET['c'], FILTER_SANITIZE_STRING); +$e = filter_var($_GET['e'], FILTER_SANITIZE_STRING); +if ( ! GetConfirmationHash($e) === $c ) { + GracefulExit($errorURL, "{$err}: Fehlerhafter Hash"); +} + +// remove email from database +try { $result = RemoveSubscriberFromDB($e); - if ($result === TRUE) { - GracefulExit($successURL, "Abmeldung für {$e} erfolgreich."); - } elseif (gettype($result == 'string')) { - GracefulExit($errorURL, "Abmeldung fehlgeschlagen: {$result}"); - } else { - GracefulExit($errorURL, 'Abmeldung fehlgeschlagen: Unbekannter Fehler'); - } -} else { - GracefulExit($errorURL, 'Abmeldung fehlgeschlagen: Fehlerhafte Emailadresse'); + if (gettype($result) == 'string') { + GracefulExit($errorURL, "{$err}: {$result}"); + } +} catch(\PDOException $e) { + GracefulExit($error, "{$err}: {$e->getMessage()}"); } ?> \ No newline at end of file diff --git a/pelicanconf.py b/pelicanconf.py index e198f18..eb8953b 100644 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -27,11 +27,11 @@ IGNORE_FILES = ['**/.*', '__pycache__', 'favicon-from-svg.sh', '*.metadata'] EXTRA_PATH_METADATA = { 'favicon/favicon.ico': {'path': 'favicon.ico'}, - 'php/settings.php': {'path': 'settings.php'}, - 'php/subscribe.php': {'path': 'subscribe.php'}, - 'php/confirm.php': {'path': 'confirm.php'}, - 'php/unsubscribe.php': {'path': 'unsubscribe.php'}, - 'php/contact.php': {'path': 'contact.php'}, + 'php/settings.php': {'path': 'newsletter/settings.php'}, + 'php/subscribe.php': {'path': 'newsletter/subscribe.php'}, + 'php/confirm.php': {'path': 'newsletter/confirm.php'}, + 'php/unsubscribe.php': {'path': 'newsletter/unsubscribe.php'}, + 'php/contact.php': {'path': 'kontakt/contact.php'}, 'php/Exception.php': {'path': 'Exception.php'}, 'php/PHPMailer.php': {'path': 'PHPMailer.php'}, 'php/SMTP.php': {'path': 'SMTP.php'}, diff --git a/theme/templates/contact.html b/theme/templates/contact.html index dcafa12..bc64feb 100644 --- a/theme/templates/contact.html +++ b/theme/templates/contact.html @@ -1,6 +1,6 @@ {% extends "page.html" %} {% block content_body %} -
+