From ca008f66bb664d2c5502b751242f29463fb7a729 Mon Sep 17 00:00:00 2001 From: skycel Date: Wed, 4 Feb 2026 22:52:45 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix:=20robustesse=20contact=20pr?= =?UTF-8?q?od?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../6.1.correctif-contact-form-production.md | 3 + includes/functions.php | 58 +++++++++++-------- tests/phpmailer.test.php | 2 + 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/docs/stories/6.1.correctif-contact-form-production.md b/docs/stories/6.1.correctif-contact-form-production.md index 405f361..3509a9e 100644 --- a/docs/stories/6.1.correctif-contact-form-production.md +++ b/docs/stories/6.1.correctif-contact-form-production.md @@ -71,6 +71,9 @@ GPT-5 Codex - Constantes SMTP ajoutées via .env / config.php - Endpoint contact charge l'autoload vendor - Tests locaux OK ; test production confirmé +- SMTP requis (MAIL_HOST obligatoire) pour éviter fallback mail() +- Sanitation CRLF sur champs sensibles (nom/prenom/objet/email) +- reCAPTCHA tolérant si Google indisponible (seuil appliqué) ### Debug Log References diff --git a/includes/functions.php b/includes/functions.php index ff7670d..816c380 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -228,7 +228,7 @@ function verifyRecaptcha(string $token): float if ($response === false) { error_log('reCAPTCHA: impossible de contacter Google'); - return 0.3; + return RECAPTCHA_THRESHOLD; } $result = json_decode($response, true); @@ -256,8 +256,19 @@ function validateContactData(array $input): array } } + $nomRaw = trim($input['nom'] ?? ''); + $prenomRaw = trim($input['prenom'] ?? ''); $emailRaw = trim($input['email'] ?? ''); + $entrepriseRaw = trim($input['entreprise'] ?? ''); + $objetRaw = trim($input['objet'] ?? ''); + $messageRaw = trim($input['message'] ?? ''); + + $nom = str_replace(["\r", "\n"], '', $nomRaw); + $prenom = str_replace(["\r", "\n"], '', $prenomRaw); $email = str_replace(["\r", "\n"], '', $emailRaw); + $entreprise = str_replace(["\r", "\n"], '', $entrepriseRaw); + $objet = str_replace(["\r", "\n"], '', $objetRaw); + $message = $messageRaw; if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = "L'adresse email n'est pas valide"; } @@ -268,22 +279,22 @@ function validateContactData(array $input): array $errors[] = 'Catégorie invalide'; } - if (strlen($input['nom'] ?? '') > 100) { + if (strlen($nom) > 100) { $errors[] = 'Le nom est trop long (max 100 caractères)'; } - if (strlen($input['prenom'] ?? '') > 100) { + if (strlen($prenom) > 100) { $errors[] = 'Le prénom est trop long (max 100 caractères)'; } - if (strlen($input['objet'] ?? '') > 200) { + if (strlen($objet) > 200) { $errors[] = "L'objet est trop long (max 200 caractères)"; } - if (strlen($input['message'] ?? '') > 5000) { + if (strlen($message) > 5000) { $errors[] = 'Le message est trop long (max 5000 caractères)'; } - if (strlen($input['objet'] ?? '') > 0 && strlen($input['objet']) < 5) { + if (strlen($objet) > 0 && strlen($objet) < 5) { $errors[] = "L'objet est trop court (min 5 caractères)"; } - if (strlen($input['message'] ?? '') > 0 && strlen($input['message']) < 20) { + if (strlen($message) > 0 && strlen($message) < 20) { $errors[] = 'Le message est trop court (min 20 caractères)'; } @@ -292,13 +303,13 @@ function validateContactData(array $input): array } return [ - 'nom' => htmlspecialchars(trim($input['nom'] ?? ''), ENT_QUOTES, 'UTF-8'), - 'prenom' => htmlspecialchars(trim($input['prenom'] ?? ''), ENT_QUOTES, 'UTF-8'), + 'nom' => htmlspecialchars($nom, ENT_QUOTES, 'UTF-8'), + 'prenom' => htmlspecialchars($prenom, ENT_QUOTES, 'UTF-8'), 'email' => filter_var($email, FILTER_SANITIZE_EMAIL), - 'entreprise' => htmlspecialchars(trim($input['entreprise'] ?? ''), ENT_QUOTES, 'UTF-8'), + 'entreprise' => htmlspecialchars($entreprise, ENT_QUOTES, 'UTF-8'), 'categorie' => $categorie, - 'objet' => htmlspecialchars(trim($input['objet'] ?? ''), ENT_QUOTES, 'UTF-8'), - 'message' => htmlspecialchars(trim($input['message'] ?? ''), ENT_QUOTES, 'UTF-8'), + 'objet' => htmlspecialchars($objet, ENT_QUOTES, 'UTF-8'), + 'message' => htmlspecialchars($message, ENT_QUOTES, 'UTF-8'), 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'inconnue', 'date' => date('d/m/Y à H:i:s'), ]; @@ -341,20 +352,21 @@ IP: {$data['ip']} ============================================ EMAIL; + if (!MAIL_HOST) { + error_log('Échec envoi email contact: MAIL_HOST manquant'); + return false; + } + $mail = new \PHPMailer\PHPMailer\PHPMailer(true); try { - if (MAIL_HOST) { - $mail->isSMTP(); - $mail->Host = MAIL_HOST; - $mail->SMTPAuth = true; - $mail->Username = MAIL_USERNAME; - $mail->Password = MAIL_PASSWORD; - $mail->SMTPSecure = MAIL_ENCRYPTION; - $mail->Port = MAIL_PORT; - } else { - $mail->isMail(); - } + $mail->isSMTP(); + $mail->Host = MAIL_HOST; + $mail->SMTPAuth = true; + $mail->Username = MAIL_USERNAME; + $mail->Password = MAIL_PASSWORD; + $mail->SMTPSecure = MAIL_ENCRYPTION; + $mail->Port = MAIL_PORT; $mail->CharSet = 'UTF-8'; $mail->setFrom(MAIL_FROM, MAIL_FROM_NAME); diff --git a/tests/phpmailer.test.php b/tests/phpmailer.test.php index 64ece43..d657381 100644 --- a/tests/phpmailer.test.php +++ b/tests/phpmailer.test.php @@ -11,6 +11,8 @@ assertTrue(strpos($composer, 'phpmailer/phpmailer') !== false, 'missing phpmaile $functions = file_get_contents(__DIR__ . '/../includes/functions.php'); assertTrue(strpos($functions, 'PHPMailer') !== false, 'missing PHPMailer usage'); +assertTrue(strpos($functions, 'MAIL_HOST') !== false, 'missing MAIL_HOST usage'); +assertTrue(strpos($functions, 'isSMTP') !== false, 'missing SMTP usage'); $config = file_get_contents(__DIR__ . '/../includes/config.php'); assertTrue(strpos($config, 'MAIL_HOST') !== false, 'missing mail constants');