2026-03-16 10:30:48 +01:00
< ? 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 ;
2026-03-16 12:26:36 +01:00
const RATE_LIMIT_MAX = 3 ; // max envois
2026-03-16 10:30:48 +01:00
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 ));
2026-03-16 12:26:36 +01:00
$headers = " From: " . RECIPIENT_NAME . " < " . RECIPIENT_EMAIL . " > \r \n " ;
$headers .= " Reply-To: =?UTF-8?B? " . base64_encode ( $name ) . " ?= < { $email } > \r \n " ;
2026-03-16 10:30:48 +01:00
$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.' ]);
2026-03-16 12:26:36 +01:00
}