✨ Story 5.5: endpoint contact PHP
This commit is contained in:
@@ -202,4 +202,158 @@ function verifyCsrfToken(?string $token): bool
|
||||
session_start();
|
||||
}
|
||||
return !empty($token) && !empty($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie le token reCAPTCHA v3 auprès de Google
|
||||
*/
|
||||
function verifyRecaptcha(string $token): float
|
||||
{
|
||||
if (empty($token) || empty(RECAPTCHA_SECRET_KEY)) {
|
||||
error_log('reCAPTCHA: token ou secret manquant');
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
$response = file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => 'Content-Type: application/x-www-form-urlencoded',
|
||||
'content' => http_build_query([
|
||||
'secret' => RECAPTCHA_SECRET_KEY,
|
||||
'response' => $token,
|
||||
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? ''
|
||||
])
|
||||
]
|
||||
]));
|
||||
|
||||
if ($response === false) {
|
||||
error_log('reCAPTCHA: impossible de contacter Google');
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
$result = json_decode($response, true);
|
||||
|
||||
if (!($result['success'] ?? false)) {
|
||||
error_log('reCAPTCHA: échec - ' . json_encode($result['error-codes'] ?? []));
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return (float) ($result['score'] ?? 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide et nettoie les données du formulaire de contact
|
||||
* @throws Exception si validation échoue
|
||||
*/
|
||||
function validateContactData(array $input): array
|
||||
{
|
||||
$errors = [];
|
||||
$required = ['nom', 'prenom', 'email', 'categorie', 'objet', 'message'];
|
||||
|
||||
foreach ($required as $field) {
|
||||
if (empty(trim($input[$field] ?? ''))) {
|
||||
$errors[] = "Le champ {$field} est requis";
|
||||
}
|
||||
}
|
||||
|
||||
$emailRaw = trim($input['email'] ?? '');
|
||||
$email = str_replace(["\r", "\n"], '', $emailRaw);
|
||||
if ($email && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = "L'adresse email n'est pas valide";
|
||||
}
|
||||
|
||||
$validCategories = ['projet', 'poste', 'autre'];
|
||||
$categorie = $input['categorie'] ?? '';
|
||||
if ($categorie && !in_array($categorie, $validCategories, true)) {
|
||||
$errors[] = 'Catégorie invalide';
|
||||
}
|
||||
|
||||
if (strlen($input['nom'] ?? '') > 100) {
|
||||
$errors[] = 'Le nom est trop long (max 100 caractères)';
|
||||
}
|
||||
if (strlen($input['prenom'] ?? '') > 100) {
|
||||
$errors[] = 'Le prénom est trop long (max 100 caractères)';
|
||||
}
|
||||
if (strlen($input['objet'] ?? '') > 200) {
|
||||
$errors[] = "L'objet est trop long (max 200 caractères)";
|
||||
}
|
||||
if (strlen($input['message'] ?? '') > 5000) {
|
||||
$errors[] = 'Le message est trop long (max 5000 caractères)';
|
||||
}
|
||||
if (strlen($input['objet'] ?? '') > 0 && strlen($input['objet']) < 5) {
|
||||
$errors[] = "L'objet est trop court (min 5 caractères)";
|
||||
}
|
||||
if (strlen($input['message'] ?? '') > 0 && strlen($input['message']) < 20) {
|
||||
$errors[] = 'Le message est trop court (min 20 caractères)';
|
||||
}
|
||||
|
||||
if (!empty($errors)) {
|
||||
throw new Exception(implode('. ', $errors));
|
||||
}
|
||||
|
||||
return [
|
||||
'nom' => htmlspecialchars(trim($input['nom'] ?? ''), ENT_QUOTES, 'UTF-8'),
|
||||
'prenom' => htmlspecialchars(trim($input['prenom'] ?? ''), ENT_QUOTES, 'UTF-8'),
|
||||
'email' => filter_var($email, FILTER_SANITIZE_EMAIL),
|
||||
'entreprise' => htmlspecialchars(trim($input['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'),
|
||||
'ip' => $_SERVER['REMOTE_ADDR'] ?? 'inconnue',
|
||||
'date' => date('d/m/Y à H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie l'email de contact
|
||||
*/
|
||||
function sendContactEmail(array $data): bool
|
||||
{
|
||||
$categorieLabels = [
|
||||
'projet' => 'Projet freelance',
|
||||
'poste' => 'Proposition de poste',
|
||||
'autre' => 'Autre demande'
|
||||
];
|
||||
|
||||
$subject = "[Portfolio] {$categorieLabels[$data['categorie']]} - {$data['objet']}";
|
||||
|
||||
$body = <<<EMAIL
|
||||
============================================
|
||||
NOUVEAU MESSAGE - PORTFOLIO
|
||||
============================================
|
||||
|
||||
DE: {$data['prenom']} {$data['nom']}
|
||||
ADRESSE EMAIL: {$data['email']}
|
||||
ENTREPRISE: {$data['entreprise']}
|
||||
CATEGORIE: {$categorieLabels[$data['categorie']]}
|
||||
|
||||
--------------------------------------------
|
||||
OBJET: {$data['objet']}
|
||||
--------------------------------------------
|
||||
|
||||
MESSAGE:
|
||||
|
||||
{$data['message']}
|
||||
|
||||
============================================
|
||||
Envoye le {$data['date']}
|
||||
IP: {$data['ip']}
|
||||
============================================
|
||||
EMAIL;
|
||||
|
||||
$headers = implode("\r\n", [
|
||||
'From: ' . CONTACT_EMAIL,
|
||||
'Reply-To: ' . $data['email'],
|
||||
'Content-Type: text/plain; charset=UTF-8',
|
||||
'X-Mailer: PHP/' . phpversion(),
|
||||
'X-Priority: 1'
|
||||
]);
|
||||
|
||||
$result = mail(CONTACT_EMAIL, $subject, $body, $headers);
|
||||
|
||||
if (!$result) {
|
||||
error_log('Échec envoi email contact: ' . print_r($data, true));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user