diff --git a/public/assets/js/admin.js b/public/assets/js/admin.js index 84ddcd8..c7525ce 100644 --- a/public/assets/js/admin.js +++ b/public/assets/js/admin.js @@ -1,4 +1,5 @@ document.addEventListener('DOMContentLoaded', function () { + // Sélection globale articles var checkAll = document.getElementById('check-all'); if (checkAll) { checkAll.addEventListener('change', function () { @@ -7,4 +8,31 @@ document.addEventListener('DOMContentLoaded', function () { }); }); } + + // Indicateurs de traitement formulaire SMTP (config + tester connexion) + var smtpForm = document.getElementById('smtp-config-form'); + if (smtpForm) { + smtpForm.addEventListener('submit', function (e) { + var clicked = e.submitter; + if (!clicked) return; + smtpForm.querySelectorAll('button[type="submit"]').forEach(function (btn) { + btn.disabled = true; + }); + var isSave = clicked.id === 'smtp-save-btn'; + clicked.innerHTML = '' + + (isSave ? 'Enregistrement…' : 'En cours…'); + }); + } + + // Indicateur de traitement envoi email de test + var smtpTestForm = document.getElementById('smtp-test-form'); + if (smtpTestForm) { + smtpTestForm.addEventListener('submit', function () { + var btn = document.getElementById('smtp-send-btn'); + if (btn) { + btn.disabled = true; + btn.innerHTML = 'En cours…'; + } + }); + } }); diff --git a/public/index.php b/public/index.php index e40a8ff..749ec37 100644 --- a/public/index.php +++ b/public/index.php @@ -1991,9 +1991,138 @@ switch ($action) { } } + if ($tab === 'smtp') { + if (!isAdmin()) { + http_response_code(403); + exit; + } + require_once BASE_PATH . '/src/SmtpSettings.php'; + $adminData['smtp_config'] = [ + 'host' => smtpCfg('host', 'SMTP_HOST'), + 'port' => smtpCfg('port', 'SMTP_PORT'), + 'secure' => smtpCfg('secure', 'SMTP_SECURE'), + 'user' => smtpCfg('user', 'SMTP_USER'), + 'has_pass' => smtpCfg('pass', 'SMTP_PASS') !== '', + 'from' => smtpCfg('from', 'SMTP_FROM'), + 'from_name' => smtpCfg('from_name', 'SMTP_FROM_NAME'), + ]; + $adminData['smtp_test'] = $_SESSION['smtp_test_result'] ?? null; + unset($_SESSION['smtp_test_result']); + } + include BASE_PATH . '/templates/admin.php'; break; + case 'admin_smtp_save': + requireAuth(); + if (!isAdmin()) { + http_response_code(403); + exit; + } + require_once BASE_PATH . '/src/SmtpSettings.php'; + + saveSmtpSettings([ + 'host' => $_POST['smtp_host'] ?? '', + 'port' => $_POST['smtp_port'] ?? '', + 'secure' => $_POST['smtp_secure'] ?? '', + 'user' => $_POST['smtp_user'] ?? '', + 'pass' => $_POST['smtp_pass'] ?? '', + 'from' => $_POST['smtp_from'] ?? '', + 'from_name' => $_POST['smtp_from_name'] ?? '', + ]); + header('Location: /admin/smtp?saved=1'); + exit; + + case 'admin_smtp_test': + requireAuth(); + if (!isAdmin()) { + http_response_code(403); + exit; + } + require_once BASE_PATH . '/src/SmtpSettings.php'; + require_once BASE_PATH . '/src/mailer.php'; + + $mode = in_array($_POST['mode'] ?? '', ['connect', 'send'], true) ? $_POST['mode'] : 'connect'; + $testEmail = trim($_POST['test_email'] ?? ''); + if ($testEmail !== '' && !filter_var($testEmail, FILTER_VALIDATE_EMAIL)) { + $testEmail = ''; + } + + $smtpLogs = []; + $smtpOk = false; + $smtpErrMsg = ''; + + try { + $mail = new \PHPMailer\PHPMailer\PHPMailer(true); + $mail->isSMTP(); + $mail->Host = smtpCfg('host', 'SMTP_HOST', 'localhost'); + $mail->Port = (int)smtpCfg('port', 'SMTP_PORT', '587'); + $_stUser = smtpCfg('user', 'SMTP_USER'); + $_stPass = smtpCfg('pass', 'SMTP_PASS'); + $mail->SMTPAuth = ($_stUser !== '' || $_stPass !== ''); + $mail->Username = $_stUser; + $mail->Password = $_stPass; + $smtpSecure = strtolower(smtpCfg('secure', 'SMTP_SECURE', 'tls')); + if ($smtpSecure === 'ssl') { + $mail->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_SMTPS; + } elseif ($smtpSecure === 'tls') { + $mail->SMTPSecure = \PHPMailer\PHPMailer\PHPMailer::ENCRYPTION_STARTTLS; + } + $mail->Timeout = 15; + $mail->SMTPOptions = ['ssl' => ['verify_peer' => true, 'verify_peer_name' => true, 'allow_self_signed' => false]]; + $mail->SMTPDebug = \PHPMailer\PHPMailer\SMTP::DEBUG_SERVER; + $mail->Debugoutput = static function (string $str) use (&$smtpLogs): void { + $smtpLogs[] = rtrim($str); + }; + + if ($mode === 'send' && $testEmail !== '') { + $mail->CharSet = 'UTF-8'; + $mail->isHTML(true); + $_smtpFrom = smtpCfg('from', 'SMTP_FROM', 'no-reply@varlog.a5l.fr'); + $_smtpFromName = smtpCfg('from_name', 'SMTP_FROM_NAME', 'varlog'); + $mail->setFrom($_smtpFrom, $_smtpFromName); + $mail->addAddress($testEmail); + $_siteName = siteTitle(); + $_siteUrl = rtrim(APP_URL, '/'); + $_sentAt = date('d/m/Y à H\hi', time()); + $mail->Subject = 'Vérification de la configuration email — ' . $_siteName; + $mail->Body = '' + . '' + . '' + . '

Bonjour,

' + . '

Cet email confirme que la configuration SMTP de ' . htmlspecialchars($_siteName) . ' fonctionne correctement.

' + . '

Envoyé le ' . $_sentAt . ' depuis ' . htmlspecialchars($_siteUrl) . '.

' + . '
' + . '

Vous recevez cet email car un administrateur a effectué un test de configuration depuis l\'interface d\'administration de ' . htmlspecialchars($_siteName) . '.' + . ' Si vous n\'attendiez pas cet email, vous pouvez l\'ignorer.

' + . ''; + $mail->AltBody = "Bonjour,\r\n\r\n" + . "Cet email confirme que la configuration SMTP de {$_siteName} fonctionne correctement.\r\n\r\n" + . "Envoyé le {$_sentAt} depuis {$_siteUrl}.\r\n\r\n" + . "--\r\n" + . "Vous recevez cet email car un administrateur a effectué un test de configuration depuis l'interface d'administration de {$_siteName}." + . " Si vous n'attendiez pas cet email, vous pouvez l'ignorer."; + $mail->send(); + } else { + $mail->smtpConnect(); + $mail->smtpClose(); + } + $smtpOk = true; + } catch (\Exception $e) { + $smtpErrMsg = $e->getMessage(); + } + + $_SESSION['smtp_test_result'] = [ + 'success' => $smtpOk, + 'error' => $smtpErrMsg, + 'logs' => $smtpLogs, + 'mode' => $mode, + 'email' => $testEmail, + 'ts' => date('d/m/Y H:i:s'), + ]; + header('Location: /admin/smtp'); + exit; + case 'admin_bulk_delete': requireAuth(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { diff --git a/src/SmtpSettings.php b/src/SmtpSettings.php new file mode 100644 index 0000000..a054959 --- /dev/null +++ b/src/SmtpSettings.php @@ -0,0 +1,53 @@ +isSMTP(); - $mail->Host = (string)env('SMTP_HOST', 'localhost'); - $mail->Port = (int)env('SMTP_PORT', '587'); - $mail->SMTPAuth = (env('SMTP_USER') || env('SMTP_PASS')) ? true : false; - $mail->Username = (string)env('SMTP_USER', ''); - $mail->Password = (string)env('SMTP_PASS', ''); - $secure = strtolower((string)env('SMTP_SECURE', 'tls')); + $_smtpRead = function_exists('smtpCfg'); + $mail->Host = $_smtpRead ? smtpCfg('host', 'SMTP_HOST', 'localhost') : (string)env('SMTP_HOST', 'localhost'); + $mail->Port = (int)($_smtpRead ? smtpCfg('port', 'SMTP_PORT', '587') : env('SMTP_PORT', '587')); + $_smtpUser = $_smtpRead ? smtpCfg('user', 'SMTP_USER') : (string)env('SMTP_USER', ''); + $_smtpPass = $_smtpRead ? smtpCfg('pass', 'SMTP_PASS') : (string)env('SMTP_PASS', ''); + $mail->SMTPAuth = ($_smtpUser !== '' || $_smtpPass !== ''); + $mail->Username = $_smtpUser; + $mail->Password = $_smtpPass; + $secure = strtolower($_smtpRead ? smtpCfg('secure', 'SMTP_SECURE', 'tls') : (string)env('SMTP_SECURE', 'tls')); if ($secure === 'ssl') { $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; } elseif ($secure === 'tls') { @@ -135,8 +142,8 @@ function envoyer_mail_smtp(string $to, string $subject, string $html, ?string $t $mail->isHTML(true); // Expéditeur - $from = (string)env('SMTP_FROM', 'no-reply@mug.a5l.fr'); - $fromName = (string)env('SMTP_FROM_NAME', 'MUG'); + $from = $_smtpRead ? smtpCfg('from', 'SMTP_FROM', 'no-reply@varlog.a5l.fr') : (string)env('SMTP_FROM', 'no-reply@varlog.a5l.fr'); + $fromName = $_smtpRead ? smtpCfg('from_name', 'SMTP_FROM_NAME', 'varlog') : (string)env('SMTP_FROM_NAME', 'varlog'); $mail->setFrom($from, $fromName); // Reply-To diff --git a/templates/admin.php b/templates/admin.php index aadf105..bac876d 100644 --- a/templates/admin.php +++ b/templates/admin.php @@ -52,6 +52,10 @@ function adminStatusBadge(array $a, int $now): string Commentaires + @@ -461,6 +465,154 @@ function adminStatusBadge(array $a, int $now): string + + + + + + +
Paramètres SMTP enregistrés.
+ + +
+ + +
+
+
Configuration SMTP
+
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + + +
Laisser vide pour conserver le mot de passe actuel.
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+
+
+ + +
+ + +
+
+
+
+ + + +
+
+ + + ✓ Succès + + ✗ Échec + + — + + + +
+ +
+ +
+ + +
+ +
+ +
+ +
+ + + +