Guides

Guides16 min de lecture

Recevoir les soumissions d'un formulaire HTML par e-mail

Recevez chaque soumission dans votre boîte sans serveur mail : pourquoi mailto : et mail() de PHP échouent, et une solution qui filtre le spam et permet de répondre.

Preet SutharFondateur, Ikiform

Un formulaire HTML ne peut pas envoyer d'e-mail tout seul, car un navigateur n'a aucun moyen de parler à un serveur mail. Faites pointer l'action du formulaire vers un backend de formulaires, qui reçoit l'envoi, filtre le spam, le stocke et vous l'envoie par e-mail, à vous et à votre équipe. Nommez le champ e-mail email, et le bouton Reply de votre boîte répond directement à la personne qui a rempli le formulaire.

La plupart des sites n'attendent qu'une chose d'un formulaire de contact : que le message arrive dans une boîte que quelqu'un lit. C'est plus difficile qu'il n'y paraît. HTML a un élément <form> mais aucun moyen d'envoyer du courrier, et les vieux raccourcis renvoient le travail au visiteur ou finissent en spam. Ce guide explique pourquoi, compare honnêtement les options et met en place un formulaire qui vous envoie un e-mail, sur n'importe quel site et n'importe quelle stack.

Pourquoi un formulaire ne peut pas envoyer d'e-mail tout seul

Quand un visiteur clique sur Send, le navigateur fait une requête HTTP vers l'URL de l'action du formulaire. C'est tout ce qu'un formulaire sait faire. Envoyer un e-mail demande une conversation SMTP avec un serveur mail, depuis une machine en laquelle le serveur destinataire a confiance. Un navigateur ne peut pas ouvrir cette connexion, et même s'il le pouvait, un e-mail parti de l'ordinateur d'un visiteur quelconque serait rejeté. Il y a donc toujours quelque chose sur un serveur entre le formulaire et votre boîte : votre propre code, un script chez votre hébergeur ou un service.

Avec un backend de formulaires, ce quelque chose est une URL. Le formulaire envoie vers https://ikiform.com/f/<id>, et Ikiform fait le reste :

Comment un envoi de formulaire devient un e-mail dans votre boîtevotreformulairetout site,toute stackIkiformvalide,évalue lespam, stockeun e-mailpardestinataireréponse àl'expéditeurvotreboîteRépondreécrit auvisiteurstockécomme spamni e-mail niwebhookenvoipas du spamsecondesscore de spam atteintComment un envoi de formulaire devient un e-mail dans votre boîtevotre formulairetout site, toute stackIkiformvalide, évalue le spam,stockeun e-mail pardestinataireréponse à l'expéditeurvotre boîteRépondre écrit auvisiteurstockécomme spamni e-mail niwebhookenvoipas du spamsecondesscore de spam atteint
  1. Le visiteur envoie votre formulaire, et le navigateur ou votre serveur le transmet à votre endpoint Ikiform.
  2. Ikiform vérifie les champs selon la définition du formulaire, évalue le spam et stocke l'envoi.
  3. Un envoi qui atteint le score de spam est stocké comme spam. Il reçoit la même réponse de succès, mais n'envoie ni e-mail ni webhook.
  4. Tout autre envoi déclenche un e-mail par destinataire, avec l'adresse du visiteur comme adresse de réponse.
  5. L'e-mail arrive dans votre boîte quelques secondes plus tard. Répondre écrit au visiteur.
Le visiteur ne voit jamais d'adresse e-mail et n'ouvre jamais d'appli de messagerie. Votre page ne contient qu'un formulaire.

Six façons de recevoir un formulaire dans votre boîte

Chacune convient à quelqu'un. Le tableau montre ce que chacune vous coûte une fois que de vrais visiteurs, et de vrais bots, utilisent le formulaire.

ApprochePoints fortsCompromis
action="mailto:you@example.com"Ni serveur, ni compte, un seul attribut.Rien n'est envoyé. Le navigateur ouvre l'appli de messagerie du visiteur avec un brouillon, ou ne fait rien si aucune n'est configurée. Votre adresse est dans la page, à la portée des scrapers. Voir le guide Gmail.
Un script PHP avec mail()Fonctionne sur presque tous les hébergements PHP mutualisés, sans tiers.Dépend de la configuration mail de l'hébergeur, et un e-mail qui prétend venir de votre domaine échoue souvent à SPF ou DMARC et finit en spam. Ni filtrage du spam, ni stockage, et pas de PHP du tout sur les hébergeurs statiques. Voir sans PHP.
Un SDK d'e-mail côté navigateur, comme EmailJSPas de serveur. Des modèles d'e-mail conçus dans leur tableau de bord.Les clés et les id de modèles sont dans le JavaScript de votre page : n'importe qui peut donc envoyer vos modèles avec son propre texte. Voir l'alternative à EmailJS.
Votre propre route plus une API d'e-mail, comme Resend, Postmark, Amazon SES ou Nodemailer en SMTPContrôle total : votre objet, votre HTML, une confirmation au visiteur.Vous construisez la validation, le filtrage du spam, les limites de débit, le stockage et les nouvelles tentatives, vous vérifiez un domaine d'envoi, et il vous faut un serveur même pour un site statique. Voir le guide Next.js.
Google Apps Script en application webTourne sur un compte Google que vous avez déjà.Les quotas de scripts limitent le nombre de destinataires par jour, l'URL n'a aucune protection anti-spam, et c'est vous qui maintenez le script.
Un backend de formulaires, comme Ikiform, Formspree ou Web3FormsUne URL dans action. Filtrage du spam, stockage et e-mail sans serveur.La mise en page et l'objet de l'e-mail sont ceux du service. Avec Ikiform, rien n'est jamais envoyé par e-mail au visiteur.

Si vous avez besoin d'un e-mail entièrement à votre marque, ou d'une confirmation au visiteur, écrivez votre propre route avec une API d'e-mail. Si vous voulez le message dans votre boîte et un moyen d'y répondre, sans spam, un backend de formulaires demande le moins de code. La suite de ce guide utilise Ikiform.

Le formulaire

Trois champs couvrent la plupart des formulaires de contact : qui c'est, où répondre et ce que la personne veut. Choisissez votre stack ci-dessous ; ce choix s'applique à tous les exemples de code de ces guides.

Ce formulaire fonctionne sans aucun JavaScript : le navigateur l'envoie, Ikiform vous écrit et le visiteur arrive sur la page indiquée dans _redirect. Chaque champ a sous lui un emplacement d'erreur vide pour le script ci-dessous.

contact.html
<form id="contact" action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="name">Name</label>
  <input id="name" name="name" autocomplete="name" required maxlength="120" />
  <p data-error="name"></p>

  <label for="email">Your email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <p data-error="email"></p>

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="6" required minlength="10"></textarea>
  <p data-error="message"></p>

  <input type="hidden" name="page" value="/contact" />
  <input type="hidden" name="_redirect" value="https://example.com/contact/sent" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send message</button>
  <p id="contact-status" role="status"></p>
</form>

Le script garde le visiteur sur la page. Il envoie avec fetch, écrit chaque erreur du serveur sous son champ, et remplace le formulaire par une phrase qui rappelle l'adresse à laquelle vous répondrez, pour qu'une faute de frappe saute aux yeux.

contact.js
const form = document.getElementById("contact");
const status = document.getElementById("contact-status");
const button = form.querySelector("button");

form.addEventListener("submit", async (event) => {
  event.preventDefault();
  for (const slot of form.querySelectorAll("[data-error]")) slot.textContent = "";
  button.disabled = true;
  status.textContent = "Sending";

  try {
    const response = await fetch(form.action, {
      method: "POST",
      headers: { Accept: "application/json" },
      body: new FormData(form),
    });
    const result = await response.json();
    if (result.ok) {
      const email = form.elements.namedItem("email").value;
      const done = document.createElement("p");
      done.setAttribute("role", "status");
      done.textContent = `Sent. We'll reply to ${email}.`;
      form.replaceWith(done);
      return;
    }
    for (const [field, messages] of Object.entries(result.error.fields ?? {})) {
      const slot = form.querySelector(`[data-error="${field}"]`);
      if (slot) slot.textContent = messages[0];
    }
    status.textContent = result.error.fields ? "Check the fields above." : result.error.message;
  } catch {
    status.textContent = "Couldn't send. Check your connection and try again.";
  }
  button.disabled = false;
});
  • Remplacez frm_xxxxxxxxxxxxxxxx par l'id de votre formulaire, visible dans le tableau de bord.
  • name="email" fait de ce champ l'adresse de réponse de l'e-mail de notification. Gardez ce nom, même si le libellé dit « Votre e-mail ».
  • page est un champ masqué ordinaire. Il apparaît dans l'e-mail, pour que vous sachiez de quelle page vient le message.
  • _gotcha est le honeypot. Les humains ne le voient jamais ; un bot qui le remplit est stocké comme spam et n'envoie d'e-mail à personne.
  • _redirect ne fonctionne que pour une URL https: sur l'un des Allowed domains du formulaire. Omettez-le et définissez plutôt Redirect after submit dans les réglages du formulaire, sinon Ikiform affiche sa propre page de remerciement.

Les guides par framework vont plus loin : Next.js, Astro, SvelteKit, Nuxt, React, Vue et HTML simple. Les créateurs de sites comme Webflow et Carrd ont leurs propres pages, et le modèle de formulaire de contact ajoute un champ de sujet.

Définissez aussi les champs dans le tableau de bord : Ikiform refuse alors un envoi non conforme avec 422 validation_failed et un message par champ, que le code ci-dessus affiche à côté de chaque input. Essayez ici ; cela exécute le même validateur dans votre navigateur :

Aperçu

Exécute le validateur d'Ikiform dans votre navigateur. Rien n'est envoyé.

Collez cette définition dans l'onglet Fields du formulaire. Sans définition, Ikiform accepte n'importe quel nom de champ et envoie par e-mail tout ce qui arrive.

À quoi ressemble l'e-mail

Chaque soumission acceptée envoie un e-mail simple et lisible. Voici la version texte de l'un d'eux :

E-mail de notification
From: Ikiform <notifications@ikiform.com>
To: you@yourcompany.com
Reply-To: ada@example.com
Subject: New submission: Contact

Contact got a new submission on Oct 25, 2026, 9:14 AM UTC.

name: Ada Lovelace
email: ada@example.com
message: Do you ship to Canada? I'd like to order 40 units before December.
page: /contact

View it in Ikiform:
https://ikiform.com/dashboard/submissions?form=frm_xxxxxxxxxxxxxxxx&submission=sub_...
  • Il vient de notifications@ikiform.com. Vous n'avez ni enregistrements DNS ni domaine d'envoi à configurer, car le courrier part du domaine d'Ikiform.
  • L'objet est toujours New submission: <form name>. _subject ne change pas l'objet des e-mails de notification. Il est transmis aux webhooks et à l'API sous meta.subject. Pour distinguer vos formulaires, donnez à chacun un nom clair dans le tableau de bord, comme « Contact, page tarifs ».
  • Les champs apparaissent dans l'ordre de l'envoi, libellés par leur name. Les champs qui commencent par _ sont omis.
  • Un formulaire ou une réponse très longs sont raccourcis, et l'e-mail indique combien de champs supplémentaires se trouvent dans le tableau de bord. La page des limites donne les chiffres.
  • Les champs qui ressemblent à des mots de passe ou à des numéros de carte sont omis, et l'e-mail d'un envoi qui en contient est retenu pour vérification. Ne collectez pas d'identifiants avec un backend de formulaires.
  • Les membres de l'espace de travail ont un bouton View submission. Les personnes extérieures à l'espace de travail reçoivent les champs et un lien de désinscription.

Qui reçoit l'e-mail

Les destinataires se règlent par formulaire dans le tableau de bord, jamais par le formulaire lui-même. Un champ qui désignerait un destinataire permettrait à n'importe qui d'utiliser votre formulaire pour écrire à n'importe qui : Ikiform n'en a donc pas.

QuiComment les ajouterRemarques
Par défautRien à faireLe membre choisi comme Notification email de l'espace de travail, ou tous les propriétaires de l'espace de travail si personne n'est choisi
Membres choisisCochez-les dans les réglages Notifications du formulaireUniquement les membres dont l'adresse e-mail est vérifiée
Personnes extérieures à l'espace de travailAdd someone outside the workspace, puis Send linkElles ne reçoivent d'e-mails qu'après confirmation. Jusqu'à 5 par formulaire, et chacune peut se désinscrire

Chaque formulaire envoie des e-mails à 10 adresses au plus. Chaque destinataire reçoit sa propre copie plutôt qu'une copie partagée, personne ne voit donc les adresses des autres. Si la boîte d'un destinataire renvoie une erreur, Ikiform suspend un moment les e-mails vers cette adresse et le tableau de bord affiche Emails bounced à côté. Plusieurs destinataires couvre l'aiguillage par sujet, que les destinataires seuls ne permettent pas.

Répondre à la personne, pas à Ikiform

Ikiform définit l'adresse de réponse d'abord à partir d'un champ _replyto, puis d'un champ nommé email, email_address, your_email, reply_to, contact_email. La valeur doit être une seule adresse e-mail valide, sinon elle est ignorée. Avec une adresse de réponse, cliquer sur Reply dans Gmail, Outlook ou Apple Mail ouvre une réponse au visiteur, et votre réponse part de votre propre adresse.

Sans elle, une réponse part vers notifications@ikiform.com, que personne ne lit. C'est la surprise la plus fréquente, et c'est généralement un champ appelé user_email ou Email Address avec une espace. Renommez-le, ou ajoutez _replyto. Le guide sur l'adresse de réponse couvre les formulaires à deux champs e-mail et les créateurs de sites qui renomment les champs à votre place.

Quand beaucoup d'envois arrivent d'un coup

Chaque formulaire envoie jusqu'à 50 e-mails de notification par heure, ou 10 tant que l'espace de travail a moins de 7 jours. Au-delà, les autres soumissions de l'heure sont stockées normalement et arrivent dans un seul e-mail récapitulatif à la fin de l'heure. Ce plafond protège votre boîte, et la réputation des e-mails d'Ikiform auprès de votre fournisseur, quand un formulaire est partagé à grande échelle ou qu'un bot passe à travers les filtres.

Ce qui arrive aux e-mails de notification pendant une heure chargéeun formulaire, une heure pleine en UTCsoumissions 1 à50un e-mail chacune,en secondesà partir de la51estockée, gardéepour le récapfin de l'heureun récap parformulaireplafond atteintheure suivanteCe qui arrive aux e-mails de notification pendant une heure chargéeun formulaire, une heure pleine en UTCsoumissions 1 à 50un e-mail chacune, en secondesà partir de la 51estockée, gardée pour le récapfin de l'heureun récap par formulaireplafond atteintheure suivante
  1. Les 50 premières soumissions d'un formulaire dans une heure pleine envoient chacune un e-mail comme d'habitude.
  2. Les soumissions suivantes de la même heure sont stockées et affichées tout de suite dans le tableau de bord, sans e-mail individuel.
  3. À la fin de l'heure, chaque destinataire reçoit un récapitulatif qui les compte et renvoie vers le tableau de bord.
Le plafond s'applique par formulaire : un pic sur un formulaire n'en ralentit pas un autre. Les webhooks ne sont pas plafonnés et partent toujours pour chaque soumission.

L'objet du récapitulatif indique le nombre et le nom du formulaire ; il ne liste pas les champs et ne définit pas d'adresse de réponse, répondez donc à ces messages depuis le tableau de bord. Si vous dépassez régulièrement le plafond, l'e-mail n'est pas le bon canal pour ce formulaire : envoyez-le plutôt vers Slack ou une boîte partagée via un webhook.

Tenir le spam hors de votre boîte

L'e-mail rend le spam coûteux : chaque envoi de bot est une notification que quelqu'un ouvre. Ikiform stocke le spam avec une réponse de succès normale, pour que le bot n'apprenne rien, et n'envoie aucun e-mail pour lui. Quatre éléments décident de ce qui compte comme spam :

DéfenseCe qu'elle arrêteConfiguration
HoneypotLes bots qui remplissent tous les inputsL'input masqué _gotcha
Score de spamDes liens dans le champ nom, trois liens ou plus, des formules de spam connues, des adresses jetables et des répétitions identiques. À 5, l'envoi est du spamAucune
Domaines autorisésLes envois depuis d'autres sitesAjoutez votre domaine dans les réglages du formulaire
Vérification humaineLes bots qui pilotent un vrai navigateurRéglez Spam check sur Ikiform

Jetez de temps en temps un œil au filtre Spam du tableau de bord. Si un vrai message s'y retrouve, marquez-le comme non-spam et son e-mail part à ce moment-là. La documentation anti-spam explique chaque signal, y compris quand activer la vérification humaine.

Ce que l'e-mail ne sait pas faire

Ikiform n'envoie pas d'e-mail à la personne qui remplit le formulaire. Les e-mails de notification vont uniquement à vous et à votre équipe : il n'y a donc ni réponse automatique, ni e-mail de confirmation, ni double opt-in. Envoyez-les depuis votre outil d'e-mailing, déclenché par un webhook. Si votre site promet « nous avons bien reçu votre message », affichez-le sur la page après l'envoi, là où le code ci-dessus le fait déjà.

  • Une boîte d'équipe partagée. Ajoutez l'adresse de l'équipe comme destinataire, ou faites un transfert depuis votre fournisseur de messagerie.
  • Un canal de discussion. Envoyez chaque soumission vers Slack, Discord ou Microsoft Teams par webhook. Le chat convient aux formulaires qui reçoivent plus de quelques messages par jour.
  • Un tableur ou un CRM. Google Sheets, ou n'importe quel outil via Zapier ou n8n.
  • Les pièces jointes. L'envoi de fichiers n'est pas encore pris en charge. Un envoi avec un fichier reçoit 422 files_not_supported. Demandez plutôt un lien vers un fichier partagé.

Désactiver l'e-mail

Certains formulaires se passent mieux d'e-mail, comme une inscription à une newsletter très active. Désactivez Email new submissions dans les réglages Notifications du formulaire. Les soumissions sont toujours stockées, et les webhooks partent toujours.

Le plafond est plus bas sur les nouveaux espaces de travail : 10 e-mails par formulaire et par heure pendant les 7 premiers jours. Si vous testez avec un script, attendez-vous à recevoir un récapitulatif plus tôt que plus tard.

Choisissez votre cas

La configuration ci-dessus est la même partout. Ces pages couvrent une boîte précise, une stack précise ou l'outil que vous quittez.

Vérifiez que tout fonctionne

Faites ces vérifications avant de mettre le formulaire en ligne. Ikiform n'a pas d'offre gratuite. Les tests sont gratuits : un espace de travail sans offre accepte 50 soumissions de test par mois depuis localhost. Pour passer en production, choisissez Pro à partir de 6 $/mois pour 500 soumissions, ou payez une seule fois : 10 000 soumissions pour 49 $ ou 50 000 soumissions pour 149 $, avec des crédits qui n'expirent jamais. Voir les tarifs.

  1. Dans Allowed domains du formulaire, ajoutez le domaine de votre site, plus localhost pendant le développement. Laissez vide pour accepter les envois de partout.
  2. Dans les réglages Notifications du formulaire, vérifiez que Email new submissions est activé et que les bonnes personnes sont cochées.
  3. Remplissez le formulaire sur votre page et envoyez-le. Vous arrivez sur votre page de remerciement, ou sur celle hébergée par Ikiform.
  4. Ouvrez Submissions dans le tableau de bord. La nouvelle soumission y est, avec tous les champs envoyés.
  5. Ouvrez l'e-mail de notification. L'objet est New submission: suivi du nom du formulaire, et tous les champs envoyés sont listés.
  6. Cliquez sur Reply. La ligne To affiche l'adresse saisie dans le formulaire, pas celle d'Ikiform.
  7. 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.
  8. Rien n'est arrivé ? Passez le filtre de statut du tableau de bord sur Spam. Le spam reçoit la même réponse de succès qu'une vraie soumission.

Dépannage

ProblèmeQue faire
La soumission est dans le tableau de bord mais aucun e-mail n'est arrivéRegardez d'abord dans votre dossier spam ou promotions, et ajoutez notifications@ikiform.com à vos contacts. Vérifiez ensuite les réglages Notifications du formulaire : l'e-mail est peut-être désactivé, une adresse extérieure affiche peut-être encore Waiting for confirmation, ou Emails bounced.
La soumission est dans le tableau de bord mais aucun e-mail ni webhook n'est arrivéElle a été stockée comme spam. Le spam n'envoie rien. Ouvrez-la sous le filtre Spam pour voir les raisons, et marquez-la comme non-spam pour envoyer son e-mail et ses webhooks.
Reply répond à notifications@ikiform.comAucune adresse de réponse n'a été trouvée. Nommez le champ e-mail email, email_address, your_email, reply_to ou contact_email, ou ajoutez un champ _replyto avec l'adresse du visiteur.
Les e-mails se sont arrêtés et un récapitulatif est arrivé à la placeLe formulaire a dépassé 50 e-mails dans l'heure (10 sur un nouvel espace de travail). Tout est dans le tableau de bord. Cherchez un pic de bots sous Spam, ou utilisez un webhook pour les formulaires très actifs.
_subject ne change pas l'objet_subject ne change pas l'objet des e-mails de notification. Il est transmis aux webhooks et à l'API sous meta.subject.
403 origin_not_allowed, ou tous les envois finissent en spamLe domaine de la page n'est pas dans les Allowed domains du formulaire. Ajoutez-le, plus localhost pour les tests en local. Les sous-domaines d'un domaine listé sont autorisés.
422 validation_failedL'envoi ne correspond pas à la définition des champs du formulaire. error.fields nomme chaque champ et la raison. Faites correspondre le name de l'input à l'id du champ.
402 test_limit_reachedL'espace de travail n'a pas d'offre et a utilisé ses 50 tests gratuits depuis localhost ce mois-ci. Choisissez une offre, ou utilisez Send test dans le tableau de bord.

Questions

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