Formulario de contacto JavaScript que envía el correo

Formgong team ·

Un formulario de contacto en JavaScript igual necesita un sitio para el POST. Llama a fetch, envía los campos y lee la respuesta JSON. Formgong acepta esa llamada sin un servidor tuyo. No hace falta una librería ni una ruta API. En el plan gratis, Telegram es inmediato y el correo es un resumen diario.

Copia este formulario JavaScript

JavaScript
<form id="fg-contact" action="https://formgong.com/submit" method="POST">
  <input type="hidden" name="access_key" value="fk_your_access_key">
  <input type="hidden" name="_lang" value="es">
  <label>Nombre <input type="text" name="name" autocomplete="name" placeholder="Tu nombre" required></label>
  <label>Correo electrónico <input type="email" name="email" autocomplete="email" placeholder="tu@ejemplo.com" required></label>
  <label>Mensaje <textarea name="message" placeholder="¿En qué podemos ayudarte?" required></textarea></label>
  <div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
  <label>Deja este campo vacío<input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
  <button type="submit">Enviar</button>
  <p role="status"></p>
</form>
<script>
  const form = document.querySelector("#fg-contact");
  const status = form.querySelector("[role=status]");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const button = form.querySelector("button");
    button.disabled = true;
    const fields = Object.fromEntries(new FormData(form));
    try {
      const response = await fetch(form.action, {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify(fields),
      });
      const result = await response.json();
      status.textContent = result.message || (result.success ? "Enviado. ¡Gracias!" : "No se pudo enviar. Inténtalo de nuevo.");
      if (result.success) form.reset();
    } catch {
      status.textContent = "Error de conexión. Inténtalo de nuevo.";
    } finally {
      button.disabled = false;
    }
  });
</script>
Envía FormData en lugar de JSON
Envía FormData en lugar de JSON
<script>
  const form = document.querySelector("#fg-contact");
  form.addEventListener("submit", async (event) => {
    event.preventDefault();
    const status = form.querySelector("[role=status]");
    try {
      const response = await fetch("https://formgong.com/submit", {
        method: "POST",
        headers: { Accept: "application/json" },
        body: new FormData(form),
      });
      const result = await response.json();
      status.textContent = result.message || (result.success ? "Enviado. ¡Gracias!" : "No se pudo enviar. Inténtalo de nuevo.");
      if (!result.success) return;
      form.reset();
    } catch {
      status.textContent = "Error de conexión. Inténtalo de nuevo.";
    }
  });
</script>
Solo la llamada fetch, si el formulario ya está en la página
Solo la llamada fetch, si el formulario ya está en la página
async function onSubmit(event) {
  event.preventDefault();
  const fields = Object.fromEntries(new FormData(event.currentTarget));
  const response = await fetch("https://formgong.com/submit", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Accept: "application/json",
    },
    // _lang: language of Formgong messages and the autoreply (multilingual site: document.documentElement.lang).
    body: JSON.stringify({ _lang: "es", ...fields, access_key: "fk_your_access_key" }),
  });
  const result = await response.json();
  if (!result.success) throw new Error(result.message || "No se pudo enviar. Inténtalo de nuevo.");
  return result.message; // localized "Sent. Thank you!"
}

Cómo funcionan los formularios en JavaScript

La gente busca un formulario JavaScript que envíe correo, no un formulario fetch. fetch es solo la llamada del navegador que hace el POST. No hacen falta EmailJS, Axios ni una ruta de servidor.

Envía una cabecera Accept con application/json, o el extremo responde con una redirección, como un formulario simple. Un fetch fallido lanza un error. Un aviso rechazado vuelve con success en false y un texto que puedes mostrar.

Configuración en JavaScript

  1. Crea un formulario en Formgong y copia la clave.
  2. Pega el código de arriba. Es un formulario y un script corto: async y await, JSON y try catch para errores de red.
  3. Deja el campo señuelo vacío y fuera de la pantalla. Si un bot lo llena, el aviso se guarda como spam y no se entrega.
  4. El script apaga el botón mientras corre la petición y luego muestra el texto de la respuesta. El éxito limpia el formulario.
  5. Abre la página real y envía una prueba. Revisa la bandeja y conecta Telegram si quieres un aviso en el teléfono.

Formas de enviar un formulario JavaScript

OpciónQué operas túQué recibes
mailto:Nada en un servidor. Se abre el correo.Un mensaje solo si el visitante envía. En el teléfono se rompe fácil.
Tu ruta APIUn servidor, SMTP y un secreto.Correo que tú controlas. También te quedas el spam, las caídas y el código.
EmailJSSu script en la página.Correo por su servicio. Esta fila no da un precio. No se volvió a mirar ese día.
FormspreeNinguno. El navegador envía a Formspree.Correo y un panel. Gratis: 50 envíos al mes. Personal cuesta 15 dólares al mes.
FormgongNinguno. fetch envía a Formgong.Telegram al momento. En Free el correo es un resumen diario. 300 envíos al mes, datos en la UE.

Los precios de Formspree salen de formspree.io/plans el 2026-10-06. Los límites de Formgong salen del código. EmailJS sale en esta búsqueda. Su precio no se volvió a mirar ese día. Web3Forms.com respondió HTTP 403, así que no está en la tabla.

Paquete de componentes: npm install @formgong/core (npm: @formgong/core)

Añadir a un proyecto existente: npx formgong init (npm: formgong)

¿fetch, una librería o tu servidor?

Usa esta página si el formulario es JavaScript simple, un widget pequeño o un diálogo. El visitante se queda en la página.

Usa HTML simple si JavaScript puede estar apagado. El formulario de arriba igual tiene action, así que funciona si el script no corre.

Escribe tu servidor solo si el aviso debe cambiar datos en tu app. EmailJS envía con su script. Formgong es un POST.

Preguntas y respuestas

¿JavaScript puede enviar un formulario al correo sin servidor?

El navegador no habla SMTP. Puede hacer POST de los campos a un backend. Ese backend envía el correo. Tú no operas un servidor para este formulario.

¿Debo enviar FormData o JSON?

JSON vale para campos de texto. FormData vale si ya tienes el formulario y si envías archivos. Los dos llegan a la misma bandeja. No pongas Content-Type tú mismo en FormData.

¿Por qué recibo una redirección en vez de JSON?

Un POST de formulario simple devuelve una redirección. Para JSON, envía una cabecera Accept con application/json. Luego lee success y el texto.

¿Cómo debo tratar los errores?

Un fetch fallido lanza un error. Eso es un fallo de red. Un aviso rechazado devuelve JSON con success en false. Muestra ese texto y conserva lo que la persona escribió.

¿Necesito EmailJS u otra librería?

No. fetch ya está en el navegador. Una librería está bien si ya la usas. Envía los mismos campos y las mismas cabeceras.

Empezar gratis