Arrêter le spam des formulaires de contact

Arrêter le spam des formulaires de contact7 min de lecture

Comment ajouter un champ honeypot que les bots remplissent et pas les humains

Ajoutez à n'importe quel formulaire un honeypot qui attrape les bots sans gêner lecteurs d'écran, clavier ou remplissage automatique, avec la vérification serveur pour chaque stack.

Preet SutharFondateur, Ikiform

Ajoutez un input texte supplémentaire que vous masquez hors écran, retirez de l'ordre de tabulation et englobez dans aria-hidden, avec un nom qu'aucun navigateur ne remplit automatiquement. Les personnes ne le remplissent jamais ; les bots qui remplissent chaque input, si. Côté serveur, traitez tout envoi où il a une valeur comme du spam et répondez exactement comme pour un vrai message.

Ce qui distingue un honeypot

Un honeypot doit être deux choses à la fois. Pour un bot qui lit le HTML, il doit ressembler à un champ normal qui mérite d'être rempli. Pour chaque personne, il ne doit pas exister, y compris pour celles qui n'utilisent pas le formulaire comme vous : quelqu'un avec un lecteur d'écran, quelqu'un qui navigue au clavier, quelqu'un dont le gestionnaire de mots de passe remplit les formulaires à sa place. La plupart des bugs de honeypot viennent de l'oubli d'une de ces personnes, et le symptôme est un vrai message discrètement classé en spam.

Comment une personne et un bot rencontrent le même champ honeypotUne personne, avec n'importe quel navigateur ou technologie d'assistanceUn bot scriptéremplit leformulaireécran, clavierou lecteurd'écranpiègeignoréhors écran,tabindex -1,aria-hiddenautofilll'ignoreun nom qu'aucunnavigateur nereconnaîtreçupiège videanalyse leHTMLtrouve chaqueinputles remplittouspiège comprisenvoieaussitôtspammême réponsede succèsComment une personne et un bot rencontrent le même champ honeypotUne personne, avec n'importe quel navigateur ou technologie d'assistanceUn bot scriptéremplit le formulaireécran, clavier ou lecteur d'écranpiège ignoréhors écran, tabindex -1,aria-hiddenautofill l'ignoreun nom qu'aucun navigateur nereconnaîtreçupiège videanalyse le HTMLtrouve chaque inputles remplit touspiège comprisenvoie aussitôtspammême réponse de succès
  1. Une personne remplit le formulaire avec ce qu'elle utilise : un écran, un clavier ou un lecteur d'écran.
  2. Le piège est hors écran, hors de l'ordre de tabulation et masqué aux technologies d'assistance : elle ne l'atteint jamais.
  3. Son nom est de ceux que les navigateurs et gestionnaires de mots de passe ne remplissent pas automatiquement : il reste donc vide.
  4. L'envoi arrive avec un piège vide et est reçu.
  5. Un bot scripté analyse le HTML et trouve chaque input, piège compris.
  6. Il les remplit tous et envoie aussitôt.
  7. Le piège a une valeur : l'envoi est donc du spam. Le bot reçoit quand même une réponse de succès normale.
Chaque garde-fou de la ligne du haut ferme une voie par laquelle une vraie personne pourrait atteindre le champ. Retirez-en un et la ligne du haut peut aussi finir en spam.

Le balisage

Placez le piège dans le formulaire, à côté des vrais champs, sous forme d'input texte simple. Un input type="hidden" ne fonctionne pas : les bots savent que les personnes ne peuvent pas les modifier, et ne les touchent pas.

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
styles
<style>
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
</style>
  • aria-hidden="true" sur le conteneur retire le label et l'input de l'arbre d'accessibilité : les lecteurs d'écran ne les annoncent donc pas.
  • tabindex="-1" empêche la touche Tab de s'arrêter sur un input que personne ne voit.
  • Le label dit Leave this empty (laissez vide). Si un outil expose malgré tout le champ, la personne qui le lit sait quoi faire.
  • N'ajoutez pas required. Un champ obligatoire que personne ne voit bloque tout envoi honnête.

Comment le masquer

Les bots ont appris à ignorer les champs manifestement masqués. Les scrapers simples remplissent encore tout, mais certains vérifient l'attribut hidden ou un display: none inline avant de taper. Plus le masquage est éloigné de l'input lui-même, plus les bots s'y laissent prendre.

TechniqueMasqué aux personnesBots encore attrapés
Attribut hidden ou display: none inlineOuiSeulement les plus simples. C'est la première chose qu'un bot plus malin vérifie
Classe hors écran dans votre feuille de styleOuiLa plupart. Le bot doit charger et appliquer votre CSS pour le savoir
opacity: 0 ou taille nulleEn grande partie. Certaines loupes et contours de focus le révèlent encoreLa plupart, mais plus risqué pour les personnes
Ajouté par JavaScript après le chargementOuiLes bots qui exécutent des scripts. Les scrapers HTML simples ne le voient jamais : il les rate donc

Utilisez la classe hors écran de votre feuille de style. Elle attrape le plus de bots et c'est la plus sûre pour les personnes. Si un honeypot cesse de fonctionner, ajoutez-en un second avec un autre nom plutôt qu'une astuce de masquage plus subtile.

Choisir un nom que le remplissage automatique ignore

Les navigateurs et les gestionnaires de mots de passe remplissent les champs en devinant d'après leur name, leur id, leur label et leur valeur autocomplete. autocomplete="off" n'est qu'une indication, et certains navigateurs l'ignorent pour les champs qui ressemblent à des adresses ou des coordonnées. C'est donc le nom qui fait le vrai travail.

À éviterPourquoiÀ utiliser à la place
email2, phone, name, addressLe remplissage automatique les reconnaît et les remplit pour de vraies personnes_gotcha, company_website
honeypot, trap, botCertains bots ignorent les champs aux noms évidentsUn nom banal et plausible
url ou website seulsCertains outils de remplissage automatique remplissent un champ site web à partir d'un profil enregistréUn nom composé comme company_website

Le vérifier sur le serveur

Un honeypot ne fonctionne que si le serveur le lit. Une vérification côté navigateur ne sert à rien, puisqu'un bot n'exécute jamais votre script. Quand le champ a une valeur, répondez exactement comme pour un vrai message, et ne stockez ni ne transmettez l'envoi. Une réponse différente indique au bot quel champ l'a trahi. Les exemples ci-dessous appellent votre propre saveMessage ; remplacez-le par ce qui stocke ou envoie le message par e-mail.

Un formulaire HTML simple n'a pas de serveur à lui. Faites-le pointer vers Ikiform et nommez le piège _gotcha, ou renommez-le pour chaque formulaire sous Honeypot field. Ikiform fait la vérification serveur, et le piège n'est jamais stocké comme réponse.

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
Journalisez les envois piégés, même si vous ne les stockez pas. Un décompte par jour vous dit si le honeypot mérite encore sa place, et une chute soudaine à zéro signifie que les bots ont appris à l'ignorer.

Comment Ikiform gère le honeypot

Chaque formulaire Ikiform a par défaut un honeypot nommé _gotcha. Changez-le pour chaque formulaire sous Honeypot field dans les réglages du formulaire ; le nom choisi est réservé et n'est jamais stocké comme réponse. Un honeypot rempli ajoute 5 au score de spam, ce qui atteint à lui seul le seuil de 5.

Ikiform ne jette pas l'envoi. Il le garde comme spam : si une vraie personne déclenche un jour le piège, vous pouvez retrouver le message et le restaurer. Un envoi jugé comme spam reçoit la même réponse de succès qu'un vrai : un bot n'apprend donc rien. Il est stocké avec le statut spam, n'envoie ni e-mail de notification ni webhook, ne compte pas dans votre consommation, et est supprimé au bout de 30 jours. Chaque lundi, un espace de travail qui a bloqué du spam reçoit un e-mail récapitulatif avec le total, les formulaires les plus sollicités et les principales raisons. La documentation sur le spam et celle des formulaires HTML servent de référence.

Vérifiez que tout fonctionne

  1. Chargez le formulaire avec un lecteur d'écran activé et parcourez-le. Le piège n'est jamais annoncé.
  2. Parcourez le formulaire avec Tab. Le focus passe du dernier vrai champ directement au bouton.
  3. Laissez votre navigateur et votre gestionnaire de mots de passe remplir automatiquement le formulaire. Le piège reste vide.
  4. Envoyez avec le honeypot rempli, _gotcha=bot. L'envoi reçoit quand même une réponse de succès, mais la soumission est stockée comme spam et n'envoie ni e-mail ni webhook.
  5. Envoyez un message normal. Il arrive comme reçu, sans trace du champ piège.

Pièges

  • Envois JSON. Si vous construisez le corps à la main au lieu d'utiliser FormData, incluez le piège, sinon votre serveur le lira comme vide pour les bots aussi.
  • Créateurs de formulaires qui renomment les champs. Certains outils préfixent ou renomment les inputs. Vérifiez le vrai nom du piège dans le corps envoyé, pas dans l'éditeur.
  • Cache. Si une page en cache garde l'ancien nom du piège après que vous l'avez renommé, les envois arrivent avec l'ancien nom et passent. Renommez des deux côtés en même temps.
  • Honeypots en case à cocher. Une case à cocher masquée fonctionne aussi, mais les lecteurs d'écran gèrent moins bien les cases isolées que les inputs texte. Préférez un input texte.
  • Une seule couche. Les bots qui pilotent un vrai navigateur et ignorent les champs invisibles passent outre tout honeypot. Associez-le à une limite de débit et, si besoin, à une vérification humaine.

Questions

Une étape vous bloque, ou vous voulez un guide pour votre cas ? Écrivez à hello@ikiform.com.