Reduce spam sin CAPTCHA con tres controles: campo trampa para ciertos bots, validación del servidor y límites de frecuencia. Cada uno aborda un problema. Ninguno demuestra con certeza si un mensaje bien escrito es de un cliente o spammer.
Esta guía explica cómo añadir la trampa HTML, qué comprueba mailcontact y cómo probarla. Si aún eliges cómo recibir envíos, empieza por nuestra guía de formularios para sitios estáticos.
Qué hace un campo trampa
Un campo trampa es un campo de texto que los visitantes deben dejar vacío. Queda fuera del formulario visible y del orden de tabulación. Un bot que rellena todos los campos puede rellenarlo también; el servidor utiliza ese valor para descartar el envío.
El campo oculto no basta. El servidor debe reconocerlo y comprobarlo antes de guardar o avisar. En mailcontact se llama company_website. Un valor no vacío tras eliminar los espacios hace que el endpoint devuelva su respuesta de éxito habitual sin guardar ningún mensaje. Ese envío descartado no consume tu cuota mensual.
Añade un campo trampa a tu formulario HTML
Para la integración recomendada, carga el script alojado de MailContact: inserta la comprobación al inicializarse y gestiona el envío y la verificación automática. El ejemplo manual siguiente sirve para formularios nativos e integraciones directas con la API.
Pégalo dentro del formulario que ya tenga email y mensaje. Utiliza una clase específica para que otros estilos no revelen accidentalmente la trampa.
<!-- Add inside your existing contact form. -->
<div class="contact-meta" aria-hidden="true">
<label for="contact-website">Website</label>
<input id="contact-website" type="text" name="company_website"
tabindex="-1" autocomplete="off" />
</div>
<style>
.contact-meta {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
}
</style>El CSS aparta el campo de la página visible. tabindex="-1" lo excluye de la navegación habitual por teclado y aria-hidden oculta el contenedor a las tecnologías de asistencia. autocomplete="off" pide al navegador que no lo rellene. No lo marques como obligatorio: un envío legítimo debe dejarlo vacío.
Estos atributos forman parte de la implementación: pruébalos. El autocompletado, gestores de contraseñas y CSS pueden interactuar de forma inesperada. Si la trampa se rellena en una visita normal, puede mostrarse éxito aunque se descarte. Es un falso positivo que corregir, no buena protección.
Incluye el campo trampa al enviar con JavaScript
new FormData(form) incluye el campo automáticamente. Si creas el cuerpo JSON manualmente, incluye company_website con los demás campos. Omitirlo devuelve un FORM_CHECK_MISSING . El script alojado añade el campo automáticamente; los formularios SDK personalizados pueden llamar a MailContact.prepare(form) una vez antes de interactuar. Nuestro formulario de contacto completo con fetch utiliza FormData e incluye este campo.
Una comprobación solo en el JavaScript del navegador se evita enviando una petición directamente al endpoint. La validación debe realizarse tanto en el servidor como en la interfaz; Guía de validación de formularios de MDN explica por qué la validación del navegador ayuda, pero no garantiza la seguridad.
Combina la trampa con validación y límites de frecuencia
Un campo trampa detecta un patrón automatizado. No limita la frecuencia de las peticiones ni su tamaño. mailcontact aplica comprobaciones adicionales a cada solicitud:
- Campos obligatorios: un email de formato válido y un mensaje no vacío. Un formato válido no demuestra que el remitente sea propietario de la dirección.
- Límites de campos: hasta 200 caracteres para name, 300 para subject, 320 para email y 5000 para message.
- Tamaño de solicitudes: se rechazan cuerpos de más de 64 KB.
- Frecuencia de solicitudes: 20 solicitudes de formulario por minuto e IP, más un límite de 60 mensajes aceptados por minuto y bandeja.
La frecuencia y las cuotas son independientes. Free permite 50 formularios aceptados por periodo mensual y Pro, 1000 mensajes en toda la cuenta. Los rechazos por validación y las trampas descartadas no consumen cuota. El spam que supera los controles y se acepta sí cuenta. Consulta la referencia antispam para las reglas actuales.
Prueba el recorrido del visitante y la trampa
- Envía normalmente: deja la trampa vacía y envía un mensaje desde el formulario real. Comprueba que llega a la bandeja.
- Usa el teclado: navega con Tab y comprueba que el campo oculto no recibe el foco normalmente.
- Prueba el autocompletado: deja que el navegador complete los campos visibles y comprueba que la trampa sigue vacía.
- Rellena la trampa a propósito: en una prueba controlada, envía un valor no vacío en
company_website. El endpoint debe devolver éxito sin nuevo mensaje ni notificación. - Elimina la comprobación: el envío debe fallar con
FORM_CHECK_MISSINGconservando el borrador. - Prueba una petición rechazada: un mensaje vacío debe devolver un error de validación y la página debe conservar lo que escribió el visitante.
Prueba también tras cambiar generadores, CSS o scripts. Un rediseño puede excluir la trampa de los datos aunque siga en la página. Mirar solo el diseño no detecta ese error.
Cuando aún llega spam
Un bot puede dejar vacío el campo trampa, utilizar datos aparentemente válidos y enviar lentamente para no superar los límites. Una persona que envía spam también puede hacerlo. MailContact combina puntuaciones del escáner, comprobaciones locales de contenido y detección de campañas por proyecto. Los mensajes sospechosos pueden exigir una prueba de trabajo automática; el spam claro se retiene en Spam durante 30 días sin notificaciones ni consumo de cuota. El script alojado gestiona la verificación y conserva los borradores fallidos. La prueba de trabajo encarece la automatización, pero no demuestra que el visitante sea humano. Revisa Spam y restaura los mensajes legítimos.
Guarda ejemplos de mensajes no deseados e indica qué proyecto los recibe. Contáctanos con ese contexto si los controles no se ajustan al tráfico. Si rastrean un email público, es un problema diferente: la guía sobre evitar publicar tu email personal explica las opciones de contacto disponibles.