146 lines
5.6 KiB
PHP
146 lines
5.6 KiB
PHP
<?php
|
|
// Session pour CSRF et rate-limit
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
$contactEmail = $_ENV['CONTACT_EMAIL'] ?? '';
|
|
$error = null;
|
|
$success = false;
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
// CSRF
|
|
$token = $_POST['_token'] ?? '';
|
|
if (!hash_equals($_SESSION['contact_csrf'] ?? '', $token)) {
|
|
$error = 'Requête invalide. Veuillez réessayer.';
|
|
}
|
|
|
|
// Honeypot (champ caché que les bots remplissent)
|
|
if (!$error && ($_POST['_hp'] ?? '') !== '') {
|
|
$error = 'Requête invalide.';
|
|
}
|
|
|
|
// Rate-limit : 1 message par 5 minutes par session
|
|
if (!$error) {
|
|
$lastSent = $_SESSION['contact_last_sent'] ?? 0;
|
|
if (time() - $lastSent < 300) {
|
|
$error = 'Merci d\'attendre quelques minutes avant d\'envoyer un nouveau message.';
|
|
}
|
|
}
|
|
|
|
// Validation des champs
|
|
$name = trim($_POST['name'] ?? '');
|
|
$from = trim($_POST['email'] ?? '');
|
|
$subject = trim($_POST['subject'] ?? 'Contact depuis varlog');
|
|
$body = trim($_POST['message'] ?? '');
|
|
|
|
if (!$error) {
|
|
if ($name === '' || mb_strlen($name) > 100) {
|
|
$error = 'Nom invalide.';
|
|
} elseif (!filter_var($from, FILTER_VALIDATE_EMAIL)) {
|
|
$error = 'Adresse e-mail invalide.';
|
|
} elseif ($body === '' || mb_strlen($body) > 5000) {
|
|
$error = 'Message vide ou trop long (max 5000 caractères).';
|
|
}
|
|
}
|
|
|
|
if (!$error && $contactEmail !== '') {
|
|
$subjectClean = mb_encode_mimeheader(
|
|
'[' . siteTitle() . ' contact] ' . mb_strimwidth($subject, 0, 100, '…'),
|
|
'UTF-8',
|
|
'B'
|
|
);
|
|
$nameClean = mb_encode_mimeheader($name, 'UTF-8', 'B');
|
|
|
|
$fromEmail = $_ENV['CONTACT_FROM_EMAIL'] ?? ('noreply@' . (parse_url(APP_URL, PHP_URL_HOST) ?? 'localhost'));
|
|
$headers = 'From: =?UTF-8?B?' . base64_encode(siteTitle() . ' contact') . "?= <{$fromEmail}>\r\n";
|
|
$headers .= "Reply-To: {$nameClean} <{$from}>\r\n";
|
|
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
|
|
$headers .= "Content-Transfer-Encoding: 8bit\r\n";
|
|
|
|
$fullBody = "De : {$name} <{$from}>\n\n{$body}\n\n---\nEnvoyé depuis varlog";
|
|
|
|
if (@mail($contactEmail, $subjectClean, $fullBody, $headers)) {
|
|
$_SESSION['contact_last_sent'] = time();
|
|
$success = true;
|
|
} else {
|
|
$error = 'Erreur lors de l\'envoi. Veuillez réessayer plus tard.';
|
|
}
|
|
} elseif (!$error) {
|
|
$error = 'Formulaire de contact non configuré.';
|
|
}
|
|
}
|
|
|
|
// Génère un nouveau token CSRF à chaque affichage du formulaire
|
|
if (!$success) {
|
|
$_SESSION['contact_csrf'] = bin2hex(random_bytes(16));
|
|
}
|
|
|
|
ob_start();
|
|
?>
|
|
|
|
<div class="posts-list">
|
|
<h1 class="mb-1">Contact</h1>
|
|
<p class="text-muted mb-4">Envoyez-moi un message. Votre adresse e-mail ne sera pas publiée.</p>
|
|
|
|
<?php if ($success): ?>
|
|
|
|
<div class="alert alert-success" role="alert">
|
|
Message envoyé. Je vous répondrai dès que possible.
|
|
</div>
|
|
|
|
<?php else: ?>
|
|
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-danger" role="alert"><?= htmlspecialchars($error) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<form method="POST" action="/?action=contact" novalidate>
|
|
<input type="hidden" name="_token" value="<?= htmlspecialchars($_SESSION['contact_csrf']) ?>">
|
|
<!-- Honeypot -->
|
|
<div style="display:none" aria-hidden="true">
|
|
<input type="text" name="_hp" tabindex="-1" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="contact-name" class="form-label">Nom <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="contact-name" name="name"
|
|
value="<?= htmlspecialchars($_POST['name'] ?? '') ?>"
|
|
maxlength="100" required autocomplete="name">
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="contact-email" class="form-label">Adresse e-mail <span class="text-danger">*</span></label>
|
|
<input type="email" class="form-control" id="contact-email" name="email"
|
|
value="<?= htmlspecialchars($_POST['email'] ?? '') ?>"
|
|
required autocomplete="email">
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="contact-subject" class="form-label">Sujet</label>
|
|
<input type="text" class="form-control" id="contact-subject" name="subject"
|
|
value="<?= htmlspecialchars($_POST['subject'] ?? '') ?>"
|
|
maxlength="150" autocomplete="off">
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="contact-message" class="form-label">Message <span class="text-danger">*</span></label>
|
|
<textarea class="form-control" id="contact-message" name="message"
|
|
rows="7" maxlength="5000" required><?= htmlspecialchars($_POST['message'] ?? '') ?></textarea>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-success">Envoyer</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php
|
|
$content = ob_get_clean();
|
|
$title = 'Contact — ' . siteTitle();
|
|
include __DIR__ . '/layout.php';
|