# Envoyer un formulaire HTML par e-mail sans PHP

> Remplacez un script contact.php qui appelle mail() par un formulaire qui envoie vers un endpoint hébergé, en gardant vos noms de champs, votre page de remerciement et les réponses.

Publié le 2026-10-25 · https://ikiform.com/fr/guides/send-form-to-email/without-php

Remplacez l'`action` du formulaire, qui pointe vers votre script PHP, par l'URL d'un backend de formulaires, gardez les noms de champs et supprimez le script. Le backend fait ce que faisait `mail()`, plus ce qu'il n'a jamais bien fait : filtrer le spam, stocker et envoyer des e-mails qui n'atterrissent pas dans les spams. Cela fonctionne sur les hébergeurs statiques où PHP ne peut pas tourner du tout.

## Ce qui change ici

La plupart des formulaires de contact PHP sont les mêmes vingt lignes, copiées d'un tutoriel il y a des années. Ils lisent `$_POST`, construisent une chaîne, appellent `mail()` et redirigent. En voici un typique :

`contact.php`:

```php
<?php
$name = $_POST["name"];
$email = $_POST["email"];
$phone = $_POST["phone"];
$message = $_POST["message"];

$to = "hello@example.com";
$subject = "Website enquiry from $name";
$body = "Name: $name\nEmail: $email\nPhone: $phone\n\n$message";
$headers = "From: $email\r\nReply-To: $email";

if (mail($to, $subject, $body, $headers)) {
  header("Location: /thanks.html");
} else {
  echo "Sorry, something went wrong.";
}
```

Il a l'air inoffensif, et il fonctionnait quand il a été écrit. Aujourd'hui, il casse de quatre façons, et seule la première est visible :

| Problème | Pourquoi cela arrive |
| --- | --- |
| Pas de PHP chez l'hébergeur | GitHub Pages, Netlify, Vercel, Cloudflare Pages et S3 servent des fichiers ; ils n'exécutent pas PHP. Le formulaire envoie vers un fichier qui n'est jamais exécuté, et vous obtenez un `404` ou un `405`. |
| Les e-mails finissent en spam, ou disparaissent | `mail()` confie le message au programme de messagerie local du serveur. L'en-tête `From:` prétend venir de l'adresse du visiteur, mais l'e-mail part du serveur de votre hébergeur : il échoue donc aux vérifications SPF et DMARC du domaine du visiteur. Gmail et Outlook le filtrent ou le rejettent, souvent sans rien dire. |
| Injection d'en-têtes | `$email` va dans les en-têtes sans vérification. Un bot qui envoie une valeur contenant un saut de ligne peut ajouter sa propre ligne `Bcc:` et utiliser votre formulaire pour envoyer du spam, ce qui fait mettre l'IP de votre hébergeur sur liste noire. |
| Rien n'est conservé | Si l'e-mail se perd, le message aussi. Il n'y a ni trace, ni filtre anti-spam, ni moyen de retrouver les demandes du mois dernier. |

Vous pourriez corriger chaque point : valider chaque valeur, envoyer via un fournisseur SMTP avec une bibliothèque comme PHPMailer, configurer SPF et DKIM pour votre domaine, ajouter un honeypot et une limite de débit, et tout journaliser dans une base de données. C'est un projet raisonnable si vous faites déjà tourner du PHP. Sinon, confiez ce travail à un backend de formulaires.

Schéma : Le même formulaire avec mail() de PHP et avec un backend de formulaires

1. Avec contact.php, le formulaire envoie vers votre hébergeur, et mail() envoie un message qui prétend venir du visiteur. Les serveurs destinataires voient un expéditeur qui ne correspond pas au domaine et le classent en spam ou le suppriment.
2. Avec un backend de formulaires, le formulaire envoie les mêmes champs à Ikiform. Ikiform envoie l'e-mail depuis son propre domaine et met l'adresse du visiteur dans Reply-To, ce qui est précisément le rôle de Reply-To.

La solution à la délivrabilité n'est pas un meilleur script. C'est d'envoyer depuis un domaine autorisé à envoyer.

## Sortir le formulaire de PHP

Gardez les noms de champs exactement tels quels. Seule l'`action` change, plus deux inputs masqués :

`Avant`:

```html
<form action="/contact.php" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <button>Send</button>
</form>
```

`Après`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="name" required />
  <input name="email" type="email" required />
  <input name="phone" type="tel" />
  <textarea name="message" required></textarea>
  <input type="hidden" name="_redirect" value="https://example.com/thanks.html" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>
```

Puis faites correspondre chaque chose que faisait le script à l'endroit où elle se trouve désormais :

| Dans contact.php | Désormais |
| --- | --- |
| `$to = "hello@example.com"` | Les destinataires, dans les réglages **Notifications** du formulaire |
| `header("Location: /thanks.html")` | L'input masqué `_redirect`, ou **Redirect after submit** dans les réglages du formulaire |
| `Reply-To: $email` | Automatique, car le champ s'appelle `email` |
| `$subject = "Website enquiry from $name"` | Fixé à `New submission: <form name>`. Nommez le formulaire « Demande depuis le site » pour garder la formulation |
| `echo "Sorry, something went wrong."` | La page d'erreur d'Ikiform pour un envoi classique, ou votre propre message avec `fetch` |
| Les vérifications que vous n'avez jamais écrites | Le honeypot `_gotcha`, le score de spam, les limites de débit et la validation des champs |

- Ajoutez votre domaine dans **Allowed domains**. `_redirect` ne fonctionne que pour une URL `https:` sur l'un de ces domaines.
- Supprimez `contact.php` du serveur une fois le nouveau formulaire en place. Un script oublié reste un relais mail ouvert pour les bots qui se souviennent de l'URL.
- Si vous êtes passé à un hébergeur statique, l'ancienne URL `/contact.php` n'existe plus. Les bots qui envoient directement dessus reçoivent un `404`, et c'est très bien.

> Si votre formulaire était une extension WordPress plutôt qu'un script, le principe est le même. Le [guide WordPress](https://ikiform.com/fr/docs/guides/wordpress.md) montre où placer le formulaire dans un thème à blocs.

## Vérifiez que tout fonctionne

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. Envoyez le formulaire sur votre page en ligne. Vous arrivez sur votre ancienne `thanks.html`.
3. Ouvrez **Submissions** dans le tableau de bord. La nouvelle soumission y est, avec tous les champs envoyés.
4. Ouvrez l'e-mail. Il vient d'Ikiform, pas de l'adresse du visiteur, et n'est pas dans les spams. Ajoutez l'expéditeur à vos contacts pour que les suivants n'y soient pas non plus.
5. Cliquez sur **Reply**. L'adresse du visiteur est sur la ligne **To**.
6. 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.

## Pièges

- **Anciens noms de formulaire avec crochets.** Les formulaires PHP utilisent souvent des noms comme `contact[email]`. Ikiform les stocke tels quels, mais l'adresse de réponse ne vient que d'un champ nommé `email` ou de quelques variantes proches. Renommez le champ, ou ajoutez `_replyto`.
- **L'objet ne peut pas inclure le nom.** L'objet du script contenait le nom du visiteur. L'objet de la notification est fixe, et `_subject` est transmis aux webhooks et à l'API sans changer l'e-mail.
- **Encodage des caractères.** Les scripts `mail()` abîmaient souvent les accents parce qu'ils ne définissaient jamais de charset. L'e-mail d'Ikiform est en UTF-8, les noms dans n'importe quelle écriture arrivent donc intacts.
- **Plusieurs adresses dans `$to`.** Une liste séparée par des virgules dans le script devient des destinataires distincts dans le tableau de bord. Les adresses extérieures confirment par lien avant de recevoir quoi que ce soit. Voir [plusieurs destinataires](https://ikiform.com/fr/guides/send-form-to-email/multiple-recipients.md).

## Si quelque chose ne va pas

| Problème | Que faire |
| --- | --- |
| Le navigateur arrive sur la page de remerciement d'Ikiform au lieu de la vôtre | `_redirect` est ignoré sauf si son domaine figure dans **Allowed domains** et qu'il s'agit d'une URL `https:`. Ajoutez le domaine, ou définissez plutôt **Redirect after submit** dans les réglages du formulaire. |
| `403 origin_not_allowed`, ou tous les envois finissent en spam | Le 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. |
| Le formulaire envoie toujours vers le fichier PHP | Une page en cache ou une seconde copie du formulaire, comme un include de pied de page, a encore l'ancienne `action`. Cherchez `contact.php` dans tout le site. |
| 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. |

## Questions

### Mon ancien formulaire continuera-t-il de fonctionner pendant la transition ?

Oui. L'ancien script fonctionne jusqu'à ce que vous changiez l'action du formulaire : vous pouvez donc d'abord tester le nouvel endpoint sur une copie de la page, puis basculer et supprimer le script.

### Puis-je envoyer un formulaire HTML par e-mail sans PHP ?

Oui. Faites pointer l'action du formulaire vers un backend de formulaires au lieu d'un script PHP. Le backend reçoit l'envoi et vous envoie un e-mail, votre site peut donc être du HTML simple sur n'importe quel hébergeur statique.

### Pourquoi les e-mails envoyés avec mail() de PHP vont-ils en spam ?

Les scripts définissent généralement l'en-tête From avec l'adresse du visiteur, mais l'e-mail part du serveur de votre hébergeur. Il échoue donc aux vérifications SPF et DMARC du domaine du visiteur, et Gmail et Outlook le traitent comme falsifié. Un backend de formulaires envoie depuis son propre domaine et met le visiteur dans Reply-To.

### Dois-je changer mes noms de champs ?

Non. Ikiform stocke tous les noms que vous envoyez. Gardez le champ e-mail nommé email, email_address, your_email, reply_to ou contact_email, ou ajoutez un champ _replyto, pour que les réponses aillent au visiteur.

### PHPMailer avec SMTP est-il une meilleure option ?

Il règle la délivrabilité si vous envoyez via un fournisseur avec votre domaine configuré pour SPF et DKIM. Il vous faut quand même un hébergeur PHP, de la validation, un filtrage du spam et un endroit où garder les messages. C'est un bon choix si vous maintenez déjà du code PHP.

## Autres guides

- [Recevoir un formulaire par e-mail](https://ikiform.com/fr/guides/send-form-to-email.md): 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.
- [Vers Gmail](https://ikiform.com/fr/guides/send-form-to-email/gmail.md): Recevez les soumissions dans Gmail sans liens mailto:, mots de passe d'application ni Apps Script, puis libellez-les, évitez les spams et répondez depuis Gmail.
- [Répondre depuis votre boîte](https://ikiform.com/fr/guides/send-form-to-email/reply-to.md): Faites que Répondre sur une notification écrive à la personne qui a rempli le formulaire : noms de champs valides, quand utiliser _replyto, et pourquoi les réponses s'égarent.
- [Plusieurs destinataires](https://ikiform.com/fr/guides/send-form-to-email/multiple-recipients.md): Envoyez un formulaire à toute votre équipe, ou aiguillez chaque message vers la bonne personne selon le sujet, sans laisser le formulaire choisir qui reçoit l'e-mail.
- [Alternative à EmailJS](https://ikiform.com/fr/guides/send-form-to-email/emailjs-alternative.md): Quittez EmailJS pour un formulaire de contact : pourquoi les clés côté navigateur sont un risque, ce qui change dans le code, et ce que vous perdez, comme la réponse automatique.
- [Next.js](https://ikiform.com/fr/guides/send-form-to-email/nextjs.md): Deux façons d'envoyer un formulaire Next.js par e-mail avec une Server Action : l'envoyer vous-même avec Resend ou Nodemailer, ou le transmettre à un backend.
