diff --git a/impfwarteliste.php b/impfwarteliste.php
index a80bf42..7ecb77f 100644
--- a/impfwarteliste.php
+++ b/impfwarteliste.php
@@ -8,8 +8,11 @@
'
- . 'Fehler in impfwarteliste.php
'
- . 'Die Seite ist wegen eines PHP-Fehlers abgebrochen.
'
- . 'Meldung: ' . htmlspecialchars((string)$error['message'], ENT_QUOTES, 'UTF-8') . '
'
- . 'Datei: ' . htmlspecialchars((string)$error['file'], ENT_QUOTES, 'UTF-8') . '
'
- . 'Zeile: ' . (int)$error['line'] . '
'
+ . 'Es ist ein Fehler aufgetreten
'
+ . 'Die Seite konnte leider nicht vollständig geladen werden. '
+ . 'Bitte versuchen Sie es später noch einmal oder rufen Sie uns an.
'
. '';
});
diff --git a/inc/functions.inc.php b/inc/functions.inc.php
index 7a3038e..52dd015 100644
--- a/inc/functions.inc.php
+++ b/inc/functions.inc.php
@@ -2916,17 +2916,75 @@ function loadAktuelleUrlaubsInfo(PDO $pdo): ?array
}
+/**
+ * Erzeugt einen Authentifizierungscode fuer ein intern_users-Konto und schickt
+ * dem Benutzer den Bestaetigungslink.
+ *
+ * Wird von register.php (direkt nach der Anmeldung) und von authmeldung.php
+ * (manuelle Anforderung) benutzt, damit beide denselben Text und dieselbe
+ * Code-Erzeugung verwenden.
+ *
+ * passwortcode_time wird mit NOW() gesetzt, also mit der Uhr des DB-Servers -
+ * authentifizierung.php prueft die Gueltigkeit ebenfalls dort.
+ *
+ * @return bool true, wenn die Mail uebergeben werden konnte
+ */
+function sendeAuthentifizierungsMail(PDO $pdo, array $user, string $organisationsname): bool
+{
+ $passwortcode = random_string();
+
+ $stmt = $pdo->prepare("
+ UPDATE intern_users
+ SET passwortcode = :passwortcode, passwortcode_time = NOW()
+ WHERE id = :userid
+ ");
+ $stmt->execute([
+ 'passwortcode' => sha1($passwortcode),
+ 'userid' => $user['id']
+ ]);
+
+ $url = getSiteURL() . 'authentifizierung.php?userid=' . urlencode((string)$user['id'])
+ . '&code=' . urlencode($passwortcode);
+
+ $betreff = 'Authentifizierung für Ihren Account bei ' . $organisationsname;
+
+ $text = 'Hallo ' . htmlentities((string)$user['vorname']) . ',
+für die Nutzung des Kontos müssen Sie das Konto per E-Mail authentifizieren. Dazu klicken Sie auf den folgenden Link:
+' . $url . '
+
+Nach der Authentifizierung können Sie das Konto vollumfänglich nutzen.
+Haben Sie kein Konto bei uns angelegt, ignorieren Sie diese E-Mail.
+
+Viele Grüße,
+Ihr ' . $organisationsname . ' Team';
+
+ return SendMailMessage($pdo, (string)$user['email'], $betreff, $text);
+}
+
+/**
+ * Verschickt eine Mail, ohne die aufrufende Seite abzubrechen.
+ * "Silent" heisst: keine Ausgabe und keine Exception nach aussen - der Fehler
+ * landet aber im Server-Log, und der Rueckgabewert sagt, ob es geklappt hat.
+ * Frueher wurde jeder Fehler ersatzlos verschluckt; ein stiller SMTP-Ausfall
+ * war dadurch von aussen nicht von einem falschen Code zu unterscheiden.
+ *
+ * @return bool true, wenn die Mail uebergeben werden konnte
+ */
function SendMailMessageSilent($con, $empfaenger, $betreff, $body){
// LOGIN CONFIG AUSLESEN
$queryconfig = mysqli_query($con, "Select * FROM config");
- $rowconfig = mysqli_fetch_assoc($queryconfig);
-
- if($queryconfig->num_rows == 1){
- $row = mysqli_fetch_assoc($queryconfig);
- $userid = $row["mailserver"];
- echo $userid;
+ if($queryconfig === false){
+ error_log("SendMailMessageSilent: config-Tabelle nicht lesbar: " . mysqli_error($con));
+ return false;
}
+
+ $rowconfig = mysqli_fetch_assoc($queryconfig);
+ if($rowconfig === null){
+ error_log("SendMailMessageSilent: kein Datensatz in der Tabelle config");
+ return false;
+ }
+
$mailserver = $rowconfig["mailserver"];
$mailUsername = $rowconfig["mailUsername"];
$mailPassword = $rowconfig["mailPassword"];
@@ -2968,11 +3026,16 @@ function SendMailMessageSilent($con, $empfaenger, $betreff, $body){
//$mail->Encoding = 'base64';
$mail->send();
-
+ return true;
+
} catch (Exception $e) {
-
+ // Nicht nach aussen werfen, aber auch nicht verschweigen.
+ error_log(sprintf(
+ 'SendMailMessageSilent: Versand an %s fehlgeschlagen: %s',
+ (string)$empfaenger,
+ $mail->ErrorInfo !== '' ? $mail->ErrorInfo : $e->getMessage()
+ ));
+ return false;
}
-
-
}
diff --git a/intern/authmeldung.php b/intern/authmeldung.php
index 56e1db9..cb47e0a 100644
--- a/intern/authmeldung.php
+++ b/intern/authmeldung.php
@@ -30,31 +30,14 @@ if(isset($_GET['send']) ) {
$error = "Kein Benutzer gefunden";
} else {
- $passwortcode = random_string();
- $statement = $pdo->prepare("UPDATE intern_users SET passwortcode = :passwortcode, passwortcode_time = NOW() WHERE id = :userid");
- $result = $statement->execute(array('passwortcode' => sha1($passwortcode), 'userid' => $user['id']));
-
- $empfaenger = $user['email'];
- $betreff = "Authentifizierung für deinen Account auf ". $_SERVER['SERVER_NAME'];
-
- $url_passwortcode = getSiteURL().'authentifizierung.php?userid='.$user['id'].'&code='.$passwortcode;
- $text = 'Hallo '.$user['vorname'].',
-für die Nutzung des Kontos müssen Sie das Konto per E-Mail authentifizieren. Dazu klicken Sie auf den folgenden Link:
-'.$url_passwortcode.'
-
-Nach der Authentifizierung können Sie das Konto vollumfänglich nutzen.
-Haben Sie keine Konto bei uns angelegt, ignorieren Sie diese E-Mail.
-
-Viele Grüße,
-Ihr ' .$organisationsname . ' Team';
-
- //echo $text;
-
- $mailOk = SendMailMessage($pdo, $empfaenger, $betreff ,$text);
-
-
- echo "Ein Link, um Ihr Konto per E-Mail zu authentifizieren, wurde an deine E-Mail-Adresse gesendet.";
- $showForm = false;
+ // Codeerzeugung und Mailtext liegen in sendeAuthentifizierungsMail(),
+ // damit register.php exakt dieselbe Mail verschickt.
+ if(sendeAuthentifizierungsMail($pdo, $user, $organisationsname)) {
+ echo "Ein Link, um Ihr Konto per E-Mail zu authentifizieren, wurde an Ihre E-Mail-Adresse gesendet.";
+ $showForm = false;
+ } else {
+ $error = "Die E-Mail konnte gerade nicht versendet werden. Bitte versuchen Sie es später noch einmal.";
+ }
}
}
}
diff --git a/intern/impfwarteliste.php b/intern/impfwarteliste.php
index bb0c762..2f1a039 100644
--- a/intern/impfwarteliste.php
+++ b/intern/impfwarteliste.php
@@ -5,7 +5,9 @@ require_once(__DIR__ . "/../inc/functions.inc.php");
require_once(__DIR__ . "/../inc/functions.impfen.inc.php");
require_once(__DIR__ . "/../inc/impfworkflow_notifications.inc.php");
-ini_set('display_errors', '1');
+// Fehler protokollieren, aber nicht an Besucher ausgeben.
+ini_set('display_errors', '0');
+ini_set('log_errors', '1');
error_reporting(E_ALL);
$user = check_intern_user();
diff --git a/intern/login.php b/intern/login.php
index 64b3ba1..47dfb93 100644
--- a/intern/login.php
+++ b/intern/login.php
@@ -47,7 +47,7 @@ if (!empty($_POST['email']) && !empty($_POST['passwort'])) {
'code' => $codeHash
]);
- SendMailMessageSilent(
+ $mailOk = SendMailMessageSilent(
$con,
$user['email'],
'Ihr Login-Code für Praxis-Creutzburg.de',
@@ -55,11 +55,27 @@ if (!empty($_POST['email']) && !empty($_POST['passwort'])) {
Geben Sie diesen Code niemals weiter."
);
- header('Location: verify_2fa.php');
- exit;
+ if ($mailOk) {
+ header('Location: verify_2fa.php');
+ exit;
+ }
+
+ // Ohne zugestellten Code kommt der Benutzer auf verify_2fa.php nicht
+ // weiter. Statt ihn dort warten zu lassen, den Versuch zuruecknehmen
+ // und es hier sagen. Die Ursache steht im Server-Log.
+ $pdo->prepare("DELETE FROM intern_2fa_codes WHERE user_id = :uid")
+ ->execute(['uid' => $user['id']]);
+ unset($_SESSION['2fa_userid']);
+
+ $error_msg = "Der Login-Code konnte gerade nicht per E-Mail versendet werden. "
+ . "Bitte versuchen Sie es in ein paar Minuten erneut oder rufen Sie uns an.";
}
- $error_msg = "E-Mail oder Passwort war ungültig";
+ // Nur setzen, wenn oben nicht schon eine genauere Meldung entstanden ist
+ // (z. B. weil der Code nicht versendet werden konnte).
+ if ($error_msg === "") {
+ $error_msg = "E-Mail oder Passwort war ungültig";
+ }
}
diff --git a/intern/neueanfrage-old1.php b/intern/neueanfrage-old1.php
index 9e5d9ad..35a01f6 100644
--- a/intern/neueanfrage-old1.php
+++ b/intern/neueanfrage-old1.php
@@ -3,7 +3,9 @@ session_start();
require_once(__DIR__ . "/../inc/config.inc.php");
require_once(__DIR__ . "/../inc/functions.inc.php");
-ini_set('display_errors', 1);
+// Fehler protokollieren, aber nicht an Besucher ausgeben.
+ini_set('display_errors', '0');
+ini_set('log_errors', '1');
error_reporting(E_ALL);
include("templates/header.inc.php");
diff --git a/intern/neueanfrage-old2.php b/intern/neueanfrage-old2.php
index 9e5d9ad..35a01f6 100644
--- a/intern/neueanfrage-old2.php
+++ b/intern/neueanfrage-old2.php
@@ -3,7 +3,9 @@ session_start();
require_once(__DIR__ . "/../inc/config.inc.php");
require_once(__DIR__ . "/../inc/functions.inc.php");
-ini_set('display_errors', 1);
+// Fehler protokollieren, aber nicht an Besucher ausgeben.
+ini_set('display_errors', '0');
+ini_set('log_errors', '1');
error_reporting(E_ALL);
include("templates/header.inc.php");
diff --git a/intern/neueanfrage.php b/intern/neueanfrage.php
index 35e8c34..d9276b6 100644
--- a/intern/neueanfrage.php
+++ b/intern/neueanfrage.php
@@ -6,7 +6,9 @@ ob_start();
require_once(__DIR__ . "/../inc/config.inc.php");
require_once(__DIR__ . "/../inc/functions.inc.php");
-ini_set('display_errors', '1');
+// Fehler protokollieren, aber nicht an Besucher ausgeben.
+ini_set('display_errors', '0');
+ini_set('log_errors', '1');
error_reporting(E_ALL);
diff --git a/intern/register.php b/intern/register.php
index fad40c5..0ad6911 100644
--- a/intern/register.php
+++ b/intern/register.php
@@ -119,14 +119,35 @@ if(isset($_GET['register'])) {
$pdo->commit();
- echo 'Du wurdest erfolgreich registriert. Zum Login';
+ echo 'Du wurdest erfolgreich registriert. Zum Login
';
$showFormular = false;
+ // Bisher wurde hier keine Mail verschickt: mailreg blieb 0 und jeder
+ // neue Benutzer landete nach dem Login auf der Aufforderung, die
+ // Authentifizierung selbst anzustossen. Den Link gibt es jetzt sofort.
+ $stmt = $pdo->prepare("SELECT id, vorname, email FROM intern_users WHERE email = :email LIMIT 1");
+ $stmt->execute([':email' => $email]);
+ $neuerUser = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ if ($neuerUser && sendeAuthentifizierungsMail($pdo, $neuerUser, $organisationsname)) {
+ echo 'Wir haben Ihnen eine E-Mail geschickt. Bitte bestätigen Sie darin '
+ . 'Ihre Adresse, damit Sie das Konto vollständig nutzen können.
';
+ } else {
+ echo 'Die Bestätigungs-E-Mail konnte gerade nicht versendet werden. '
+ . 'Sie können sie nach dem Login jederzeit erneut anfordern.
';
+ }
+
} catch (Exception $e) {
- $pdo->rollBack();
- echo 'Fehler beim Registrieren.
';
- echo ($e->getMessage());
- echo "
";
+ // Der Mailversand laeuft nach dem commit(). Ohne diese Pruefung
+ // wuerde ein Fehler dort in rollBack() ohne offene Transaktion
+ // laufen und die Seite mit einem Fatal Error abbrechen.
+ if ($pdo->inTransaction()) {
+ $pdo->rollBack();
+ }
+ // Interne Fehlermeldungen gehoeren ins Log, nicht auf die Seite.
+ error_log('register.php: Registrierung fehlgeschlagen: ' . $e->getMessage());
+ echo 'Bei der Registrierung ist ein Fehler aufgetreten. '
+ . 'Bitte versuchen Sie es später noch einmal oder rufen Sie uns an.
';
}
}
diff --git a/zeiterfassung/api/vacations.php b/zeiterfassung/api/vacations.php
index cf256a4..4aefb18 100644
--- a/zeiterfassung/api/vacations.php
+++ b/zeiterfassung/api/vacations.php
@@ -4,8 +4,10 @@ require_once(__DIR__ . '/../inc/config.inc.php');
require_once(__DIR__ . '/../inc/functions.inc.php');
require_once(__DIR__ . '/../inc/vacation_absence.inc.php');
-ini_set('display_errors', '1');
-ini_set('display_startup_errors', '1');
+// Fehler protokollieren, aber nicht an Besucher ausgeben.
+ini_set('display_errors', '0');
+ini_set('log_errors', '1');
+ini_set('display_startup_errors', '0');
error_reporting(E_ALL);
if (!function_exists('vacationApiTableHasColumn')) {