website/assets/php/send_mail.php
2026-03-16 10:30:48 +01:00

229 lines
11 KiB
PHP

<?php
/**
* OmégaKube — Formulaire de contact
* Endpoint PHP pour l'envoi d'emails via le formulaire de contact.
*
* Placer ce fichier à la racine du site (même dossier que index.html).
* Requiert : PHP 7.4+, fonction mail() activée sur le serveur.
*/
/* ── Configuration ─────────────────────────────────────────── */
const RECIPIENT_EMAIL = 'aboubacarm279@gmail.com'; // ← adresse de réception
const RECIPIENT_NAME = 'OmégaKube';
const SUBJECT_PREFIX = '[OmégaKube] ';
const ALLOWED_ORIGIN = '*'; // ou 'https://omegakube.com'
/* ── Anti-spam : limite par IP (optionnel, nécessite accès fichier) ── */
const RATE_LIMIT_ENABLED = true;
const RATE_LIMIT_MAX = 30; // max envois
const RATE_LIMIT_WINDOW = 3600; // par heure (secondes)
const RATE_LIMIT_DIR = __DIR__ . '/.rate_limits/';
/* ══════════════════════════════════════════════════════════════ */
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: ' . ALLOWED_ORIGIN);
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
/* Bloquer toute méthode autre que POST */
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['success' => false, 'message' => 'Méthode non autorisée.']);
exit;
}
/* ── Lecture du body (JSON ou form-data) ───────────────────── */
$contentType = $_SERVER['CONTENT_TYPE'] ?? '';
if (str_contains($contentType, 'application/json')) {
$raw = file_get_contents('php://input');
$data = json_decode($raw, true) ?? [];
} else {
$data = $_POST;
}
/* ── Récupération & nettoyage des champs ───────────────────── */
$name = trim(strip_tags($data['name'] ?? ''));
$email = trim(strip_tags($data['email'] ?? ''));
$subject = trim(strip_tags($data['subject'] ?? 'Contact depuis le site'));
$message = trim(strip_tags($data['message'] ?? ''));
/* ── Validation ────────────────────────────────────────────── */
$errors = [];
if (empty($name) || mb_strlen($name) < 2) {
$errors[] = 'Le nom doit contenir au moins 2 caractères.';
}
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Adresse email invalide.';
}
if (empty($message) || mb_strlen($message) < 10) {
$errors[] = 'Le message doit contenir au moins 10 caractères.';
}
if (mb_strlen($name) > 100 || mb_strlen($email) > 254 || mb_strlen($message) > 5000) {
$errors[] = 'Un des champs dépasse la longueur maximale autorisée.';
}
if (!empty($errors)) {
http_response_code(422);
echo json_encode(['success' => false, 'message' => implode(' ', $errors)]);
exit;
}
/* ── Honeypot anti-bot (champ caché "website" dans le HTML) ── */
if (!empty($data['website'])) {
// Simuler un succès pour ne pas signaler le bot
echo json_encode(['success' => true, 'message' => 'Message envoyé avec succès !']);
exit;
}
/* ── Rate limiting par IP ───────────────────────────────────── */
if (RATE_LIMIT_ENABLED) {
$ip = preg_replace('/[^a-f0-9:.]/', '', $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0');
$file = RATE_LIMIT_DIR . md5($ip) . '.json';
$now = time();
$records = [];
if (!is_dir(RATE_LIMIT_DIR)) {
@mkdir(RATE_LIMIT_DIR, 0700, true);
}
if (file_exists($file)) {
$records = json_decode(file_get_contents($file), true) ?? [];
// Ne garder que les entrées dans la fenêtre de temps
$records = array_filter($records, fn($t) => ($now - $t) < RATE_LIMIT_WINDOW);
$records = array_values($records);
}
if (count($records) >= RATE_LIMIT_MAX) {
http_response_code(429);
echo json_encode(['success' => false, 'message' => 'Trop de messages envoyés. Veuillez patienter avant de réessayer.']);
exit;
}
$records[] = $now;
file_put_contents($file, json_encode($records), LOCK_EX);
}
/* ── Construction de l'email ───────────────────────────────── */
$emailSubject = SUBJECT_PREFIX . $subject;
$emailBody = "Nouveau message depuis le formulaire de contact OmégaKube\n";
$emailBody .= str_repeat('─', 55) . "\n\n";
$emailBody .= "Nom : {$name}\n";
$emailBody .= "Email : {$email}\n";
$emailBody .= "Objet : {$subject}\n\n";
$emailBody .= "Message :\n{$message}\n\n";
$emailBody .= str_repeat('─', 55) . "\n";
$emailBody .= "Envoyé le : " . date('d/m/Y à H:i:s') . "\n";
$emailBody .= "IP : " . ($_SERVER['REMOTE_ADDR'] ?? 'inconnue') . "\n";
/* Version HTML de l'email */
$emailBodyHtml = '<!DOCTYPE html>
<html lang="fr">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"></head>
<body style="margin:0;padding:0;background:#1a0f1f;font-family:\'Segoe UI\',sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#1a0f1f;padding:40px 20px;">
<tr><td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="max-width:600px;background:#251528;border-radius:8px;overflow:hidden;border:1px solid rgba(167,77,121,0.3);">
<!-- Header -->
<tr>
<td style="background:linear-gradient(135deg,#8b3a62,#a64d79);padding:32px;text-align:center;">
<h1 style="margin:0;color:#fff;font-size:24px;font-weight:normal;letter-spacing:2px;">⬡ OmégaKube</h1>
<p style="margin:8px 0 0;color:rgba(255,255,255,0.8);font-size:14px;">Nouveau message de contact</p>
</td>
</tr>
<!-- Content -->
<tr>
<td style="padding:32px;">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td style="padding:12px 0;border-bottom:1px solid rgba(167,77,121,0.2);">
<span style="color:#8a7a91;font-size:12px;text-transform:uppercase;letter-spacing:1px;">Nom</span><br>
<span style="color:#fff;font-size:16px;margin-top:4px;display:block;">' . htmlspecialchars($name) . '</span>
</td>
</tr>
<tr>
<td style="padding:12px 0;border-bottom:1px solid rgba(167,77,121,0.2);">
<span style="color:#8a7a91;font-size:12px;text-transform:uppercase;letter-spacing:1px;">Email</span><br>
<a href="mailto:' . htmlspecialchars($email) . '" style="color:#c77daa;font-size:16px;margin-top:4px;display:block;text-decoration:none;">' . htmlspecialchars($email) . '</a>
</td>
</tr>
<tr>
<td style="padding:12px 0;border-bottom:1px solid rgba(167,77,121,0.2);">
<span style="color:#8a7a91;font-size:12px;text-transform:uppercase;letter-spacing:1px;">Objet</span><br>
<span style="color:#fff;font-size:16px;margin-top:4px;display:block;">' . htmlspecialchars($subject) . '</span>
</td>
</tr>
<tr>
<td style="padding:12px 0;">
<span style="color:#8a7a91;font-size:12px;text-transform:uppercase;letter-spacing:1px;">Message</span><br>
<p style="color:#c9b8d0;font-size:15px;line-height:1.7;margin:8px 0 0;white-space:pre-wrap;">' . htmlspecialchars($message) . '</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:20px 32px;background:rgba(0,0,0,0.2);text-align:center;">
<p style="margin:0;color:#8a7a91;font-size:12px;">Envoyé le ' . date('d/m/Y à H:i') . ' • IP : ' . htmlspecialchars($_SERVER['REMOTE_ADDR'] ?? '') . '</p>
</td>
</tr>
</table>
</td></tr>
</table>
</body>
</html>';
/* Boundary pour email multipart */
$boundary = '----=_Part_' . md5(uniqid('', true));
$headers = "From: =?UTF-8?B?" . base64_encode($name) . "?= <{$email}>\r\n";
$headers .= "Reply-To: {$email}\r\n";
$headers .= "To: " . RECIPIENT_NAME . " <" . RECIPIENT_EMAIL . ">\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n";
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
$headers .= "X-Originating-IP: " . ($_SERVER['REMOTE_ADDR'] ?? '') . "\r\n";
$fullBody = "--{$boundary}\r\n";
$fullBody .= "Content-Type: text/plain; charset=UTF-8\r\n";
$fullBody .= "Content-Transfer-Encoding: base64\r\n\r\n";
$fullBody .= chunk_split(base64_encode($emailBody)) . "\r\n";
$fullBody .= "--{$boundary}\r\n";
$fullBody .= "Content-Type: text/html; charset=UTF-8\r\n";
$fullBody .= "Content-Transfer-Encoding: base64\r\n\r\n";
$fullBody .= chunk_split(base64_encode($emailBodyHtml)) . "\r\n";
$fullBody .= "--{$boundary}--";
/* ── Envoi ──────────────────────────────────────────────────── */
$sent = mail(RECIPIENT_EMAIL, '=?UTF-8?B?' . base64_encode($emailSubject) . '?=', $fullBody, $headers);
if ($sent) {
/* Email de confirmation à l'expéditeur */
$confirmSubject = '=?UTF-8?B?' . base64_encode('Votre message a bien été reçu — OmégaKube') . '?=';
$confirmHeaders = "From: " . RECIPIENT_NAME . " <" . RECIPIENT_EMAIL . ">\r\n";
$confirmHeaders .= "Reply-To: " . RECIPIENT_EMAIL . "\r\n";
$confirmHeaders .= "MIME-Version: 1.0\r\n";
$confirmHeaders .= "Content-Type: text/plain; charset=UTF-8\r\n";
$confirmHeaders .= "Content-Transfer-Encoding: base64\r\n";
$confirmBody = "Bonjour {$name},\n\n";
$confirmBody .= "Merci pour votre message ! Nous l'avons bien reçu et nous vous répondrons dans les plus brefs délais.\n\n";
$confirmBody .= "Récapitulatif de votre message :\n";
$confirmBody .= str_repeat('─', 40) . "\n";
$confirmBody .= $message . "\n";
$confirmBody .= str_repeat('─', 40) . "\n\n";
$confirmBody .= "L'équipe OmégaKube\n";
$confirmBody .= "https://omegakube.com\n";
@mail($email, $confirmSubject, chunk_split(base64_encode($confirmBody)), $confirmHeaders);
http_response_code(200);
echo json_encode(['success' => true, 'message' => 'Votre message a bien été envoyé ! Nous vous répondrons rapidement.']);
} else {
http_response_code(500);
echo json_encode(['success' => false, 'message' => 'Une erreur est survenue lors de l\'envoi. Veuillez réessayer ou nous contacter directement par Discord.']);
}