Un formulaire de contact qui n'envoie rien, ou dont les messages finissent dans les spams, coûte des clients sans que vous le sachiez. Dans ce tutoriel, vous créez un formulaire de contact complet en HTML et PHP : validation des champs, protection contre les robots, envoi fiable par SMTP avec la boîte e-mail de votre domaine, et messages clairs pour le visiteur.

Niveau : débutant à intermédiaire. Durée : environ 45 minutes. Prérequis : un hébergement avec PHP 8.1 ou plus récent (la plupart des hébergements mutualisés avec cPanel conviennent), Composer, et une adresse e-mail professionnelle sur votre domaine. Le code de ce tutoriel a été testé avec PHP 8.3 et PHPMailer : envoi valide, champs invalides, piège à robots, tentative d'injection et panne du serveur d'envoi.

Pourquoi ne pas utiliser la fonction mail() de PHP ?

La fonction mail() envoie les messages depuis le serveur web, sans authentification. Résultat fréquent : les messages sont classés en spam ou rejetés, car ils ne passent pas les contrôles SPF, DKIM et DMARC de votre domaine. En passant par SMTP avec une vraie boîte e-mail, vos messages partent comme si vous les envoyiez vous-même. Si vous n'avez pas encore d'adresse sur votre domaine, commencez par notre guide pour créer une adresse e-mail professionnelle.

Étape 1 : organiser les fichiers

Les identifiants de la boîte e-mail ne doivent jamais se trouver dans le dossier public du site. Voici l'organisation à respecter (sur cPanel, le dossier public s'appelle public_html) :

mon-compte/
├── config-mail.php      ← identifiants SMTP (hors du dossier public)
├── vendor/              ← bibliothèques installées par Composer
└── public_html/
    ├── contact.html     ← le formulaire
    └── contact.php      ← le traitement

Étape 2 : installer PHPMailer

PHPMailer est la bibliothèque de référence pour envoyer des e-mails en PHP. Dans le dossier mon-compte (via le terminal de cPanel ou en SSH) :

composer require phpmailer/phpmailer

Composer crée le dossier vendor/ et un fichier composer.json.

Étape 3 : écrire la configuration SMTP

Créez config-mail.php, toujours en dehors de public_html. Les valeurs exactes (serveur, port) sont indiquées par votre fournisseur e-mail :

<?php
return [
    'host'   => 'smtp.votre-domaine.ci',
    'port'   => 587,
    'secure' => 'tls',
    'user'   => 'contact@votre-domaine.ci',
    'pass'   => 'mot-de-passe-de-la-boite',
    'to'     => 'contact@votre-domaine.ci',
];

Le port 587 avec 'tls' (STARTTLS) est le réglage le plus courant. Certains fournisseurs utilisent le port 465 avec 'ssl'.

Étape 4 : créer le formulaire HTML

Créez public_html/contact.html. Trois détails font la différence : des champs obligatoires vérifiés dès le navigateur, un champ piège invisible pour les humains, et une case de consentement.

<form action="/contact.php" method="post">
  <label for="nom">Nom</label>
  <input id="nom" name="nom" required maxlength="100" autocomplete="name">

  <label for="email">E-mail</label>
  <input id="email" name="email" type="email" required autocomplete="email">

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="6" required minlength="10" maxlength="5000"></textarea>

  <!-- Piège à robots : invisible, les humains le laissent vide -->
  <div class="piege" aria-hidden="true">
    <label for="site_web">Ne pas remplir</label>
    <input id="site_web" name="site_web" tabindex="-1" autocomplete="off">
  </div>

  <label class="consent">
    <input type="checkbox" name="consentement" value="1" required>
    J'accepte que mes données soient utilisées pour répondre à ma demande.
  </label>

  <button type="submit">Envoyer</button>
</form>
<div id="alerte" class="alerte" hidden></div>

Le champ piège est simplement sorti de l'écran en CSS. Les robots qui remplissent tous les champs se dénoncent ainsi :

.piege { position: absolute; left: -9999px; }
.alerte { padding: .8rem 1rem; border-radius: 8px; margin-bottom: 1rem; }
.ok { background: #dcfce7; }
.ko { background: #fee2e2; }

Étape 5 : traiter l'envoi en PHP

Créez public_html/contact.php. Le script refuse tout ce qui n'est pas un envoi de formulaire, ignore les robots, valide chaque champ, puis envoie le message :

<?php
declare(strict_types=1);

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require __DIR__ . '/../vendor/autoload.php';
$config = require __DIR__ . '/../config-mail.php';

function retour(string $etat): never
{
    header('Location: /contact.html?etat=' . $etat, true, 303);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    exit('Méthode non autorisée');
}

// 1. Piège à robots : ce champ est caché aux humains, seuls les robots le remplissent.
if (!empty($_POST['site_web'])) {
    retour('ok');
}

// 2. Récupération et validation des champs
$nom     = trim((string) ($_POST['nom'] ?? ''));
$email   = trim((string) ($_POST['email'] ?? ''));
$message = trim((string) ($_POST['message'] ?? ''));

if ($nom === '' || mb_strlen($nom) > 100
    || !filter_var($email, FILTER_VALIDATE_EMAIL)
    || mb_strlen($message) < 10 || mb_strlen($message) > 5000
    || empty($_POST['consentement'])) {
    retour('invalide');
}
$nom = str_replace(["\r", "\n"], ' ', $nom);

// 3. Envoi par SMTP avec la boîte e-mail de votre domaine
$mail = new PHPMailer(true);
try {
    $mail->isSMTP();
    $mail->Host       = $config['host'];
    $mail->Port       = $config['port'];
    $mail->SMTPSecure = $config['secure'];
    $mail->SMTPAuth   = true;
    $mail->Username   = $config['user'];
    $mail->Password   = $config['pass'];
    $mail->CharSet    = 'UTF-8';

    $mail->setFrom($config['user'], 'Formulaire du site');
    $mail->addAddress($config['to']);
    $mail->addReplyTo($email, $nom);
    $mail->Subject = 'Nouveau message de ' . $nom;
    $mail->Body    = "Nom : $nom\nE-mail : $email\n\n$message";

    $mail->send();
    retour('ok');
} catch (Exception $e) {
    error_log('Formulaire de contact : ' . $mail->ErrorInfo);
    retour('erreur');
}

Quelques points importants :

  • L'expéditeur est toujours votre boîte (setFrom), jamais l'adresse du visiteur : sinon vos messages échouent aux contrôles anti-usurpation. L'adresse du visiteur va dans addReplyTo, pour que le bouton « Répondre » fonctionne.
  • Les retours à la ligne sont retirés du nom : un robot ne peut pas s'en servir pour glisser des destinataires cachés dans l'e-mail.
  • Le robot piégé reçoit « ok » : il ne sait pas qu'il a été repéré et ne cherche pas à contourner le piège.
  • Le code 303 renvoie le visiteur vers la page du formulaire : s'il actualise la page, le message n'est pas envoyé une deuxième fois.
  • En cas de panne, le détail technique part dans le journal d'erreurs du serveur, et le visiteur voit un message simple.

Étape 6 : afficher le résultat au visiteur

Ajoutez ce petit script en bas de contact.html. Il lit le paramètre etat renvoyé par PHP et affiche le bon message :

<script>
  const etat = new URLSearchParams(location.search).get('etat');
  const textes = {
    ok: ['ok', 'Merci, votre message est bien parti. Nous vous répondons rapidement.'],
    invalide: ['ko', 'Vérifiez les champs : e-mail valide, message de 10 caractères minimum, case cochée.'],
    erreur: ['ko', "L'envoi a échoué. Réessayez dans quelques minutes ou écrivez-nous directement."],
  };
  if (textes[etat]) {
    const bloc = document.getElementById('alerte');
    bloc.className = 'alerte ' + textes[etat][0];
    bloc.textContent = textes[etat][1];
    bloc.hidden = false;
  }
</script>

Étape 7 : tester avant de mettre en ligne

  1. Envoyez un message normal : il doit arriver dans votre boîte, et « Répondre » doit viser l'adresse du visiteur.
  2. Saisissez un e-mail invalide ou un message trop court : le message d'erreur doit s'afficher.
  3. Vérifiez que config-mail.php et vendor sont bien en dehors de public_html : par exemple, https://votre-domaine.ci/config-mail.php doit renvoyer une erreur 404.
  4. Regardez le dossier spam de la boîte de réception pendant les premiers jours.

Votre site doit aussi être servi en HTTPS, sinon les données du formulaire circulent en clair. Si vous gérez votre propre serveur, suivez notre tutoriel VPS avec Nginx et HTTPS. Pour les autres protections de base, voir sécuriser son site web.

Aller plus loin

  • Beaucoup de spam malgré le piège ? Ajoutez une vérification anti-robot comme Cloudflare Turnstile ou reCAPTCHA, ou limitez le nombre d'envois par adresse IP.
  • Accusé de réception : envoyez un second e-mail au visiteur pour confirmer la bonne réception de sa demande.
  • Données personnelles : ne gardez que les informations nécessaires et indiquez dans votre politique de confidentialité ce que vous en faites. Voir notre article sur les données personnelles en Côte d'Ivoire.
  • Être recontacté sur WhatsApp : proposez un champ téléphone facultatif, beaucoup de clients préfèrent ce canal. Voir WhatsApp Business, le guide complet.

Questions fréquentes

Mon formulaire envoie, mais les messages arrivent en spam. Pourquoi ?

Le plus souvent, l'expéditeur n'est pas une boîte de votre domaine, ou les enregistrements SPF, DKIM et DMARC du domaine sont absents ou incorrects. Vérifiez-les chez votre fournisseur e-mail.

Mon hébergeur n'a pas Composer. Que faire ?

Installez PHPMailer sur votre ordinateur avec Composer, puis envoyez le dossier vendor sur l'hébergement par FTP, au même endroit que dans l'étape 1.

Puis-je utiliser Gmail comme serveur d'envoi ?

C'est possible avec un mot de passe d'application, mais l'expéditeur sera une adresse Gmail, moins crédible qu'une adresse sur votre domaine. Pour une entreprise, préférez la boîte de votre domaine.

Le formulaire fonctionne-t-il avec WordPress ?

Sur WordPress, utilisez plutôt une extension de formulaire et une extension SMTP : le principe reste le même (envoi authentifié depuis une boîte de votre domaine).

Être accompagné

NEWTIV crée des sites professionnels dont les formulaires, devis et demandes de rappel arrivent vraiment, avec un suivi des demandes et une connexion à WhatsApp. Demandez un devis, nous vous répondons sous 48 heures ouvrées.