v1.5
This commit is contained in:
parent
42db666026
commit
c14f0531ff
8 changed files with 555 additions and 188 deletions
|
|
@ -935,7 +935,7 @@ section {
|
|||
margin: 0 auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding: 0.5rem 0;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.team-carousel {
|
||||
|
|
@ -944,7 +944,7 @@ section {
|
|||
}
|
||||
|
||||
.team-card {
|
||||
flex: 0 0 calc(33.333% - 1.33rem);
|
||||
flex: 0 0 calc(33.333% - 2rem);
|
||||
margin: 0 1rem;
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
|
|
@ -1445,7 +1445,7 @@ footer {
|
|||
}
|
||||
|
||||
.team-card {
|
||||
flex: 0 0 calc(50% - 1rem);
|
||||
flex: 0 0 calc(50% - 2rem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1605,7 +1605,8 @@ footer {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2rem;
|
||||
padding: 1rem;
|
||||
overflow-y: auto;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: all 0.3s ease;
|
||||
|
|
@ -1622,10 +1623,12 @@ footer {
|
|||
border-radius: 8px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
max-height: calc(100dvh - 2rem);
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
transform: scale(0.9) translateY(20px);
|
||||
transition: transform 0.3s ease;
|
||||
overflow: hidden;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.team-modal-overlay.active .team-modal {
|
||||
|
|
@ -1800,19 +1803,35 @@ footer {
|
|||
|
||||
@media (max-width: 480px) {
|
||||
.team-modal-stats {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
|
||||
.team-modal {
|
||||
margin: 1rem;
|
||||
max-height: calc(100dvh - 1rem);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.team-modal-header {
|
||||
padding: 1.5rem;
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.team-modal-content {
|
||||
padding: 1.5rem;
|
||||
padding: 1.25rem 1rem;
|
||||
}
|
||||
|
||||
.team-modal-avatar {
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.team-modal-name {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.team-modal-stats {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
229
assets/php/send_mail.php
Normal file
229
assets/php/send_mail.php
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
<?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.']);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue