Envía un formulario a tu email6 min de lectura
Envía un formulario HTML a tu email sin PHP
Sustituye un script contact.php que llama a mail() por un formulario que envía a un endpoint alojado, conservando tus nombres de campo, tu página de agradecimiento y las respuestas.
Cambia el action del formulario de tu script PHP a la URL de un backend de formularios, conserva los nombres de campo y borra el script. El backend hace lo que hacía mail(), más lo que nunca hizo bien: filtrar spam, guardar los envíos y enviar correo que no acaba en spam. Funciona en hostings estáticos donde PHP no se puede ejecutar.
Qué cambia aquí
La mayoría de los formularios de contacto en PHP son las mismas veinte líneas, copiadas de un tutorial hace años. Leen $_POST, construyen una cadena, llaman a mail() y redirigen. Este es uno típico:
<?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.";
}Parece inofensivo, y funcionaba cuando se escribió. Hoy falla de cuatro maneras, y solo la primera es evidente:
| Problema | Por qué pasa |
|---|---|
| No hay PHP en el hosting | GitHub Pages, Netlify, Vercel, Cloudflare Pages y S3 sirven archivos; no ejecutan PHP. El formulario envía a un archivo que nunca se ejecuta, y recibes un 404 o un 405. |
| El correo acaba en spam o desaparece | mail() pasa el mensaje al programa de correo local del servidor. La cabecera From: dice ser la dirección del visitante, pero el correo sale del servidor de tu hosting, así que falla las comprobaciones SPF y DMARC del dominio del visitante. Gmail y Outlook lo filtran o lo rechazan, muchas veces sin avisar. |
| Inyección de cabeceras | $email entra en las cabeceras sin comprobar. Un bot que envía un valor con un salto de línea puede añadir su propia línea Bcc: y usar tu formulario para enviar spam, lo que mete la IP de tu hosting en listas de bloqueo. |
| No se guarda nada | Si se pierde el email, se pierde el mensaje. No hay registro, ni filtro antispam, ni forma de revisar las consultas del mes pasado. |
Podrías arreglar cada problema: validar cada valor, enviar a través de un proveedor SMTP con una librería como PHPMailer, configurar SPF y DKIM para tu dominio, añadir un honeypot y un límite de frecuencia, y registrar en una base de datos. Es un proyecto razonable si ya usas PHP. Si prefieres no hacerlo, pasa el trabajo a un backend de formularios.
- Con contact.php, el formulario envía a tu hosting y mail() manda un mensaje que dice venir del visitante. Los servidores receptores ven un remitente que no coincide con el dominio y lo clasifican como spam o lo descartan.
- Con un backend de formularios, el formulario envía los mismos campos a Ikiform. Ikiform manda el email desde su propio dominio y pone la dirección del visitante en Reply-To, que es justo para lo que sirve Reply-To.
Saca el formulario de PHP
Conserva los nombres de campo tal cual. Solo cambia el action, más dos inputs ocultos:
<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><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>Después, ubica cada cosa que hacía el script en su nuevo sitio:
| En contact.php | Ahora |
|---|---|
$to = "hello@example.com" | Destinatarios en los ajustes de Notifications del formulario |
header("Location: /thanks.html") | El input oculto _redirect, o Redirect after submit en los ajustes del formulario |
Reply-To: $email | Automático, porque el campo se llama email |
$subject = "Website enquiry from $name" | Fijo: New submission: <form name>. Llama al formulario "Consulta web" para mantener el texto |
echo "Sorry, something went wrong." | La página de error de Ikiform para un envío normal, o tu propio mensaje con fetch |
| Comprobaciones que nunca escribiste | El honeypot _gotcha, la puntuación de spam, los límites de frecuencia y la validación de campos |
- Añade tu dominio en Allowed domains.
_redirectsolo funciona con una URLhttps:en uno de esos dominios. - Borra
contact.phpdel servidor cuando el nuevo formulario funcione. Un script olvidado sigue siendo un relay de correo abierto para los bots que recuerdan la URL. - Si te pasaste a un hosting estático, la antigua URL
/contact.phpya no existe. Los bots que envían directamente a ella reciben un404, y no pasa nada.
Comprueba que funciona
- En Allowed domains del formulario, añade el dominio de tu sitio, más
localhostmientras desarrollas. Déjalo vacío para aceptar envíos desde cualquier lugar. - Envía el formulario en tu página publicada. Llegas a tu antigua
thanks.html. - Abre Submissions en el panel. El nuevo envío está ahí con todos los campos que mandaste.
- Abre el email. Viene de Ikiform, no de la dirección del visitante, y no está en spam. Añade el remitente a tus contactos para que los siguientes tampoco lo estén.
- Pulsa Reply. La dirección del visitante está en la línea To.
- Envía con el honeypot relleno,
_gotcha=bot. Sigue recibiendo una respuesta de éxito, pero el envío se guarda como spam y no manda ningún email ni webhook.
Detalles a tener en cuenta
- Nombres antiguos con corchetes. Los formularios PHP suelen usar nombres como
contact[email]. Ikiform los guarda tal cual, pero el reply-to solo sale de un campo llamadoemailo de unas pocas variantes parecidas. Renombra el campo o añade_replyto. - El asunto no puede incluir el nombre. El asunto del script llevaba el nombre del visitante. El asunto de la notificación es fijo, y
_subjectse pasa a los webhooks y a la API sin cambiar el email. - Codificación de caracteres. Los scripts con
mail()solían estropear los acentos porque nunca definían un charset. El email de Ikiform es UTF-8, así que los nombres en cualquier alfabeto llegan intactos. - Varias direcciones en
$to. Una lista separada por comas en el script pasa a ser destinatarios separados en el panel. Las direcciones externas confirman mediante un enlace antes de recibir nada. Consulta varios destinatarios.
Si algo sale mal
| Problema | Qué hacer |
|---|---|
| El navegador llega a la página de agradecimiento de Ikiform en lugar de a la tuya | _redirect se ignora salvo que su dominio esté en Allowed domains y sea una URL https:. Añade el dominio o configura Redirect after submit en los ajustes del formulario. |
403 origin_not_allowed, o todos los envíos acaban en spam | El dominio de la página no está en Allowed domains del formulario. Añádelo, más localhost para las pruebas locales. Los subdominios de un dominio de la lista están permitidos. |
| El formulario sigue enviando al archivo PHP | Una página en caché o una segunda copia del formulario, como un include del pie de página, aún tiene el action antiguo. Busca contact.php en todo el sitio. |
| El envío está en el panel, pero no llegó ningún email ni webhook | Se guardó como spam. El spam no envía nada. Ábrelo en el filtro Spam para ver los motivos y márcalo como no spam para enviar su email y sus webhooks. |
Preguntas
Sí. El script antiguo sigue funcionando hasta que cambies el action del formulario, así que puedes probar primero el nuevo endpoint en una copia de la página y después hacer el cambio y borrar el script.
Sí. Apunta el action del formulario a un backend de formularios en lugar de a un script PHP. El backend recibe el envío y te manda un email, así tu sitio puede ser HTML simple en cualquier hosting estático.
Los scripts suelen poner en la cabecera From la dirección del visitante, pero el correo sale del servidor de tu hosting. Eso falla las comprobaciones SPF y DMARC del dominio del visitante, así que Gmail y Outlook lo tratan como falsificado. Un backend de formularios envía desde su propio dominio y pone al visitante en Reply-To.
No. Ikiform guarda los nombres que envíes, sean cuales sean. Llama al campo del email email, email_address, your_email, reply_to o contact_email, o añade un campo _replyto, para que las respuestas vayan al visitante.
Resuelve la entregabilidad si envías a través de un proveedor con tu dominio configurado para SPF y DKIM. Sigues necesitando un hosting PHP, validación, filtro antispam y un sitio donde guardar los mensajes. Es una buena opción si ya mantienes código PHP.
¿Te atascaste en un paso o quieres una guía para tu caso? Escribe a hello@ikiform.com.