added DB functions

This commit is contained in:
eclipse 2025-03-02 19:50:47 +01:00
parent cfb6879b32
commit 973d4b0345
4 changed files with 113 additions and 36 deletions

View File

@ -1,31 +1,56 @@
<?php <?php
// inspired by https://www.mailgun.com/blog/email/double-opt-in-with-php-mailgun/ // inspired by https://www.mailgun.com/blog/email/double-opt-in-with-php-mailgun/
$statusCode = 'HTTP/1.1 303 See Other';
require(dirname(__FILE__) . '/settings.php');
$successURL = '/newsletter/confirmed.html'; $successURL = '/newsletter/confirmed.html';
$errorURL = '/newsletter/confirm-error.html'; $errorURL = '/newsletter/confirm-error.html';
// return TRUE when successful, message string on failure // Adds new subscriber to database. Returns an error message on failure, TRUE on success.
// e.g. Adresse schon vorhanden, Datenbank-Fehler, was noch? function AddSubscriberToDB($subscriberAddress, $subscriberName = NULL) {
function AddSubscriberToDB($recipientAddress) { global $general;
global $db;
echo 'ah jup'; 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.";
}
// 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();
}
return TRUE; return TRUE;
} }
function CheckConfirmationHash($confEmail, $confCode) {
global $general;
return (md5($confEmail . $general['uniqueKey']) === $confCode);
}
require(dirname(__FILE__) . '/settings.php');
if (isset($_GET['c']) && isset($_GET['e'])) { if (isset($_GET['c']) && isset($_GET['e'])) {
$c = filter_var($_GET['c'], FILTER_SANITIZE_STRING); $c = filter_var($_GET['c'], FILTER_SANITIZE_STRING);
$e = filter_var($_GET['e'], FILTER_SANITIZE_STRING); $e = filter_var($_GET['e'], FILTER_SANITIZE_STRING);
if (CheckConfirmationHash($e, $c)) { if ( GetConfirmationHash($e) === $c ) {
$result = AddSubscriberToDB($e); $result = AddSubscriberToDB($e);
if ($result == TRUE) { if ($result === TRUE) {
GracefulExit($successURL, 'Bestätigung erfolgt: Newsletter-Anmeldung bestätigt'); GracefulExit($successURL, 'Bestätigung erfolgt: Newsletter-Anmeldung bestätigt');
} elseif (gettype($result == 'string')) { } elseif (gettype($result == 'string')) {
GracefulExit($errorURL, "Bestätigung fehlgeschlagen: {$result}"); GracefulExit($errorURL, "Bestätigung fehlgeschlagen: {$result}");

View File

@ -11,16 +11,28 @@ require $dname . '/SMTP.php';
// general constants // general constants
$general = [ $general = [
// 'domain' => 'tobias-radloff.de', // site domain (used for building confirmation links)
/* 'domain' => 'tobias-radloff.de', */
'domain' => 'localhost', 'domain' => 'localhost',
// string concatenated with email address to create a non-recreatable md5 hash
'uniqueKey' => '***REMOVED***', // works like password salt 'uniqueKey' => '***REMOVED***', // works like password salt
// file name of confirm script
'confirmScript' => '/confirm.php', 'confirmScript' => '/confirm.php',
'statusCode' => 'HTTP/1.1 303 See Other' // status code to be used when redirection to success or error page
'statusCode' => 'HTTP/1.1 303 See Other',
// array of SQL statements used
'sql' => [
'create_table' => 'CREATE TABLE IF NOT EXISTS subscribers (id INTEGER PRIMARY KEY, email TEXT NOT NULL UNIQUE, name TEXT);',
'create_record' => 'INSERT INTO subscribers(email, name) VALUES(:e, :n);',
'read_record' => 'SELECT 1 FROM subscribers WHERE email = :e;',
'update_record' => '',
'delete_record' => 'DELETE FROM subscribers WHERE email = :e;'
]
]; ];
// complete site URL
$general['siteURL'] = 'https://' . $general['domain']; $general['siteURL'] = 'https://' . $general['domain'];
// smtp info // SMTP server information
$smtp = [ $smtp = [
'host' => '***REMOVED*** 'host' => '***REMOVED***
'port' => 587, 'port' => 587,
@ -31,28 +43,47 @@ $smtp = [
'fromName' => 'Tobias Radloffs Newsletter', 'fromName' => 'Tobias Radloffs Newsletter',
]; ];
// body of confirmation email
$bodyConfirmation = [ $bodyConfirmation = [
'Hallo!', 'Hallo!',
'Bitte bestätige die Anmeldung für meinen Newsletter, indem du auf den folgenden Link klickst:', 'Bitte bestätige die Anmeldung für meinen Newsletter, indem du auf den folgenden Link klickst:',
'%Placeholder%', // placeholder '%Placeholder%',
'Bis bald und viele Grüße, Tobias' 'Bis bald und viele Grüße, Tobias'
]; ];
// mail contents // contents of confirmation email
$mailConfirmation = [ $mailConfirmation = [
'subject' => 'Newsletter-Anmeldung bestaetigen', 'subject' => 'Newsletter-Anmeldung bestaetigen',
'bodyHTML' => '<p>' . implode('</p><p>', $bodyConfirmation) . '</p>', 'bodyHTML' => '<p>' . implode('</p><p>', $bodyConfirmation) . '</p>',
'bodyText' => implode("\n\n", $bodyConfirmation) 'bodyText' => implode("\n\n", $bodyConfirmation)
]; ];
// DB constants // database information
$db = [ $db = [
'host' => '', 'sqlite' => [
'port' => '', 'dsn' => 'sqlite:../newsletter.sqlite',
'username' => '', ],
'password' => '' 'mysql' => [
'dsn' => '',
'host' => '',
'port' => '',
'username' => '',
'password' => ''
]
]; ];
function GetConfirmationHash($confEmail) {
global $general;
return md5($confEmail . $general['uniqueKey'] );
}
// connects to database and returns PDO object
function getPDO($dbType = 'sqlite') {
global $db;
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.
function SendEmail($recipientAddress, $mailContents, $link = NULL) { function SendEmail($recipientAddress, $mailContents, $link = NULL) {
global $general, $smtp; global $general, $smtp;
@ -92,6 +123,7 @@ function SendEmail($recipientAddress, $mailContents, $link = NULL) {
} }
} }
// redirects to specified URL via GET request and conveys an optional message
function GracefulExit($location, $message = NULL) { function GracefulExit($location, $message = NULL) {
global $general; global $general;
header($general['statusCode']); header($general['statusCode']);

View File

@ -6,20 +6,15 @@ $errorURL = '/newsletter/subscribe-error.html';
require(dirname(__FILE__) . '/settings.php'); require(dirname(__FILE__) . '/settings.php');
function MakeConfirmationHash($confEmail, $confCode) {
return md5($confEmail . $confCode);
}
if (isset($_POST['email'])) { if (isset($_POST['email'])) {
$email = filter_var(trim($_POST['email'], FILTER_SANITIZE_STRING)); $email = filter_var(trim($_POST['email'], FILTER_SANITIZE_STRING));
error_log("Email ist: {$email}");
if (filter_var($email, FILTER_VALIDATE_EMAIL)) { if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$hashedUnique = MakeConfirmationHash($email, $general['uniqueKey']); $confirmQuery = http_build_query(['c' => GetConfirmationHash($email), 'e' => $email]);
$confirmQuery = http_build_query(['c' => $hashedUnique, 'e' => $email]);
$confirmLink = $general['siteURL'] . $general['confirmScript'] . "?" . $confirmQuery; $confirmLink = $general['siteURL'] . $general['confirmScript'] . "?" . $confirmQuery;
$result = SendEmail($email, $mailConfirmation, $confirmLink); $result = SendEmail($email, $mailConfirmation, $confirmLink);
if ( $result == TRUE ) { if ( $result === TRUE ) {
GracefulExit($successURL, 'Anmeldung wird fortgesetzt: Email mit Bestätigungslink wurde versandt.'); GracefulExit($successURL, 'Anmeldung wird fortgesetzt: Email mit Bestätigungslink wurde versandt.');
} else { } else {
GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Fehler beim Versenden der Bestätigungs-Email.'); GracefulExit($errorURL, 'Anmeldung fehlgeschlagen: Fehler beim Versenden der Bestätigungs-Email.');

View File

@ -7,14 +7,39 @@ $errorURL = '/newsletter/unsubscribe-error.html';
function RemoveSubscriberFromDB($subscriberAddress) { function RemoveSubscriberFromDB($subscriberAddress) {
error_log("removing subscriber {$subscriberAddress} from DB ..."); 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();
}
return TRUE; return TRUE;
} }
if (isset($_GET['e'])) { if (isset($_GET['e'])) {
$e = filter_var($_GET["e"], FILTER_SANITIZE_STRING); $e = filter_var($_GET["e"], FILTER_SANITIZE_STRING);
$result = RemoveSubscriberFromDB($e); $result = RemoveSubscriberFromDB($e);
if ($result == TRUE) { if ($result === TRUE) {
GracefulExit($successURL, "Abmeldung für {$e} erfolgreich."); GracefulExit($successURL, "Abmeldung für {$e} erfolgreich.");
} elseif (gettype($result == 'string')) { } elseif (gettype($result == 'string')) {
GracefulExit($errorURL, "Abmeldung fehlgeschlagen: {$result}"); GracefulExit($errorURL, "Abmeldung fehlgeschlagen: {$result}");