# Webhook de email entrante sin tocar tus MX: ¿cómo?

> Tu propio buzón a un webhook: asunto, HTML, hasta 20 adjuntos e hilos como JSON firmado. Sin cambiar tus MX, a diferencia de SendGrid Inbound Parse.

Source: https://unlimitedmessaging.app/es/articles/email-inbound-webhook

Webhook de email entrante

# Convierte los emails de tu propio buzón  
_en JSON analizado en tu servidor._

Los servicios de parsing quieren tus registros MX o una dirección de reenvío. Conecta en cambio el buzón que ya usas: cada email nuevo llega a tu URL con su asunto, su HTML, sus adjuntos y su hilo, y respondes desde la misma dirección.

[Crear una cuenta gratis](https://app.unlimitedmessaging.app)[Ver planes de pago](https://unlimitedmessaging.app/es/pricing)

La respuesta corta

## ¿Cómo enviar los emails entrantes a un webhook?

Conecta el propio buzón. Unlimited Messaging inicia sesión en tu buzón actual por IMAP (Gmail con una contraseña de aplicación, tu propio dominio, cualquier proveedor IMAP), vigila su bandeja de entrada y envía cada email nuevo a tu URL como un evento JSON firmado, message.received, con asunto, texto, HTML, adjuntos e identificadores de hilo. Tus MX se quedan donde están, a diferencia de [SendGrid Inbound Parse](https://www.twilio.com/docs/sendgrid/for-developers/parsing-email/setting-up-the-inbound-parse-webhook). Los webhooks están en los planes de pago Medium y Max.

Los servicios de parsing se colocan delante del correo. SendGrid te pide apuntar el MX de un nombre de host dedicado a mx.sendgrid.net, y luego envía multipart/form-data (o el MIME original) a tu URL. Postmark da a cada servidor una dirección como yourhash@inbound.postmarkapp.com, a la que reenvías desde Gmail o enrutas con inbound domain forwarding, y su procesamiento de entrada viene con el plan Pro, desde 16,50 $ al mes. En ambos casos cambia la dirección a la que escriben tus clientes, o su correo pasa por un reenvío.

Unlimited Messaging lee el buzón al que tus clientes ya escriben. Una pasarela mantiene una conexión IMAP IDLE en su bandeja de entrada, en solo lectura, así que un email nuevo se recoge en cuanto el servidor lo anuncia. El email se guarda, sus adjuntos también (hasta 20 por email), y tu webhook recibe un único cuerpo JSON: externalId es el Message-ID, conversation.id la raíz de su hilo y replyTo el mensaje al que responde.

La respuesta cierra el círculo: POST /message con replyToMessageId envía desde el mismo buzón, por su propio servidor SMTP, con Re: y las cabeceras In-Reply-To y References, y guarda una copia en Enviados. El hilo sigue siendo un solo hilo en el correo de tu cliente.

Antes de conectar: [configura Gmail por IMAP con una contraseña de aplicación](https://unlimitedmessaging.app/es/articles/gmail-imap-smtp-app-password) y [por qué importa enviar desde tu propio buzón](https://unlimitedmessaging.app/es/articles/send-from-your-own-mailbox-and-number).

![Ilustración: una cuadrícula de iconos pequeños con uno resaltado, con el titular «Tu buzón, en JSON».](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Femail-inbound-webhook-es.png&w=3840&q=75)

Definición
Webhook de email entrante

Un POST HTTP que entrega cada email recibido a tu servidor como datos estructurados (remitente, asunto, texto, HTML, adjuntos, cabeceras de hilo), para que tu código nunca tenga que hablar IMAP ni decodificar MIME.

También buscado como email a webhook, API para recibir emails, webhook de parsing de email o inbound parse.

[Fuente: SendGrid, configuración del Inbound Parse↗](https://www.twilio.com/docs/sendgrid/for-developers/parsing-email/setting-up-the-inbound-parse-webhook)

Los eventos

## ¿Qué contiene el webhook de email entrante?

El email comparte el sobre de todos los canales y añade tres campos: subject, html y attachments.

1. 01  
### message.received  
Llegó un email nuevo a la bandeja de entrada. content es el cuerpo de texto, o el HTML convertido a texto cuando el email no tiene parte de texto; html es el cuerpo tal como llegó, no fiable, que hay que sanear antes de mostrarlo.
2. 02  
### attachments  
Cada archivo en orden, hasta 20 por email: url (la copia guardada), filename, mimeType, size y contentId para una imagen incrustada que el HTML referencia como cid:. El primero también se copia en mediaUrl.
3. 03  
### Hilos  
externalId es el Message-ID RFC 5322 sin corchetes angulares. conversation.id es la raíz del hilo (primer elemento de References, si no In-Reply-To, si no el propio email), así que todos los emails de un hilo lo comparten.
4. 04  
### message.sent y message.status  
Tus respuestas se anuncian como message.sent, y un rebote definitivo pasa el mensaje a UNDELIVERABLE (message.status). La dirección rebotada queda en pausa 30 días en ese buzón para proteger su reputación.
5. 05  
### account.status\_changed  
El buzón se desconectó, por ejemplo porque el servidor rechazó las credenciales tras un cambio de contraseña. Suscríbete para que un buzón mudo no pase desapercibido.

POST https://example.com/webhooks/umJSON

```
{
  "type": "message.received",
  "eventId": "whd_9a4f2e61-7c3b-4d85-b0e9-5f1a8c2d7e34",
  "occurredAt": "2026-11-09T14:05:12.000Z",
  "data": {
    "message": {
      "id": "msg_3f8a1c2e-9d4b-4e7a-8b6c-2d1e0f9a8b7c",
      "externalId": "CAF8k2Lp9xQ3@mail.example.com",
      "direction": "IN",
      "fromMe": false,
      "content": "Hi, please find the signed quote attached. Claire",
      "sentAt": "2026-11-09T14:05:12.000Z",
      "receivedAt": "2026-11-09T14:05:12.000Z",
      "sender": "claire@example.com",
      "senderId": "claire@example.com",
      "senderName": null,
      "participant": null,
      "replyTo": { "externalId": "quote-1042.20261108@yourcompany.example", "participant": null },
      "mediaUrl": "https://api.unlimitedmessaging.app/message/media/stored/4c1d...",
      "mediaType": "document",
      "mimeType": "application/pdf",
      "mediaFilename": "quote-1042-signed.pdf",
      "transcript": null,
      "subject": "Re: Quote #1042",
      "html": "<p>Hi, please find the signed quote attached.</p><p>Claire</p>",
      "attachments": [
        {
          "url": "https://api.unlimitedmessaging.app/message/media/stored/4c1d...",
          "filename": "quote-1042-signed.pdf",
          "mimeType": "application/pdf",
          "size": 184320,
          "contentId": null
        }
      ]
    },
    "channel": {
      "type": "EMAIL",
      "account": { "id": "acc_8b2e4f6a-1c3d-4e5f-a7b9-0c1d2e3f4a5b", "name": "sales@yourcompany.example" },
      "conversation": {
        "id": "quote-1042.20261108@yourcompany.example",
        "isGroup": false,
        "address": "claire@example.com"
      }
    }
  }
}
```

Un cuerpo message.received real para un email, construido a partir del esquema publicado (URLs de archivos acortadas). sender es la dirección From; senderName no se rellena en email.

Puesta en marcha

## ¿Cómo analizar emails entrantes en Next.js?

Conecta el buzón, registra un endpoint, verifica cada POST. Ni parser MIME ni librería IMAP en tu código.

1. 01  
### Conecta tu buzón  
En la aplicación web, añade una cuenta de email con la dirección y su contraseña (una contraseña de aplicación para Gmail). Los ajustes IMAP y SMTP se detectan a partir de la dirección.
2. 02  
### Registra el endpoint  
POST /webhooks con tu URL y tus eventTypes, o añádelo en la página Webhooks del panel. El secreto (whsec\_...) se muestra una sola vez.
3. 03  
### Verifica, guarda, responde  
Comprueba la cabecera webhook-signature, haz un upsert por eventId, descarga los adjuntos desde su url cuando los necesites y responde con replyToMessageId.

POST /webhookscurl

```
curl https://api.unlimitedmessaging.app/webhooks \
  -H "Authorization: Bearer $UM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/um",
    "eventTypes": ["message.received", "account.status_changed"],
    "description": "Inbound email"
  }'

# The response carries "secret": "whsec_..." once. Store it as UM_WEBHOOK_SECRET.
```

Añade accountIds para limitar el endpoint a un buzón, por ejemplo soporte@ pero no facturacion@. Sin él, cubre todas las cuentas.

app/api/webhooks/um/route.tsNext.js route handler

```
// app/api/webhooks/um/route.ts (Next.js App Router)
import crypto from 'node:crypto';
import { UnlimitedMessagingApiClient } from '@unlimited-messaging/sdk';

const um = new UnlimitedMessagingApiClient({ token: process.env.UM_API_KEY! });
const key = Buffer.from(process.env.UM_WEBHOOK_SECRET!.replace(/^whsec_/, ''), 'base64');

// Standard Webhooks: HMAC-SHA256 of "id.timestamp.rawBody", base64.
function verify(raw: string, id: string, ts: string, header: string) {
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = crypto.createHmac('sha256', key).update(`${id}.${ts}.${raw}`).digest('base64');
  return header.split(' ').some((entry) => {
    const sig = entry.startsWith('v1,') ? entry.slice(3) : '';
    return sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
  });
}

export async function POST(req: Request) {
  const raw = await req.text(); // the raw body, before any JSON parsing
  const h = req.headers;
  if (!verify(raw, h.get('webhook-id') ?? '', h.get('webhook-timestamp') ?? '',
    h.get('webhook-signature') ?? '')) {
    return new Response('bad signature', { status: 401 });
  }

  const event = JSON.parse(raw);
  if (event.type === 'message.received' && event.data.channel.type === 'EMAIL') {
    const m = event.data.message;
    const thread = event.data.channel.conversation.id; // same id for the whole thread
    const files = m.attachments ?? []; // [{ url, filename, mimeType, size, contentId }]
    await saveTicket({ eventId: event.eventId, thread, from: m.sender, subject: m.subject,
      text: m.content, files }); // upsert on eventId: delivery is at least once

    // Answer in the same thread, from the same mailbox.
    await um.messages.messageSend({ replyToMessageId: m.id, text: 'Thanks, received. We reply within a day.' });
  }
  return new Response(null, { status: 200 }); // within 10 s; queue slow work
}
```

req.text() conserva el cuerpo original sobre el que se calcula la firma (Standard Webhooks, HMAC-SHA256 sobre id.timestamp.rawBody). saveTicket es tuyo. La respuesta sale con Re: y las cabeceras de hilo, desde el mismo buzón.

Vibe coding

## ¿Programas con Cursor, Claude Code, Lovable o Bolt? Pega esto

Tu editor con IA recibe la ruta, la verificación de firma y los campos de email que necesita, sin inventar un parser MIME.

Prompt para copiar

Add an Unlimited Messaging webhook to this app so incoming emails from my own mailbox become support tickets.

1. Create a POST route (Next.js: app/api/webhooks/um/route.ts) that reads the RAW body with req.text().
2. Verify the Standard Webhooks signature: key = base64-decode(UM_WEBHOOK_SECRET without "whsec_"); expected = base64(HMAC-SHA256(key, `${webhook-id}.${webhook-timestamp}.${rawBody}`)); accept if any space-separated entry of the webhook-signature header equals `v1,${expected}` (constant-time compare); reject timestamps more than 5 minutes off; return 401 otherwise.
3. On type "message.received" with data.channel.type "EMAIL": upsert a ticket keyed on body.eventId with data.channel.conversation.id (thread id), data.message.sender, data.message.subject, data.message.content (text) and data.message.attachments ([{ url, filename, mimeType, size, contentId }]). Treat data.message.html as untrusted: sanitise before rendering.
4. To answer, install @unlimited-messaging/sdk, read UM_API_KEY from env, and call `client.messages.messageSend({ replyToMessageId: data.message.id, text })`: it replies in the same thread from the same mailbox.
5. Return 200 within 10 seconds; queue slow work.
6. Put UM_API_KEY and UM_WEBHOOK_SECRET in .env and .env.example.

Docs: https://docs.unlimitedmessaging.app (Webhooks). Register with POST https://api.unlimitedmessaging.app/webhooks and eventTypes ["message.received"].

Lo que se construye

## ¿Qué puedes construir con el email entrante?

Todo lo que hoy consiste en que alguien copie un email en otra herramienta.

### Un helpdesk en soporte@

Un ticket por conversation.id, cada respuesta añadida, contestaciones enviadas desde soporte@ en el mismo hilo. Ninguna dirección de ticketing que publicar.

### Clasificación y respuesta automática con IA

Pasa subject y content a un LLM, etiqueta y enruta el email, o envía una primera respuesta con replyToMessageId y deja que una persona tome el relevo.

1. 01  
### Facturas y documentos entrantes  
Descarga el PDF desde attachments\[\].url y envíalo a tu contabilidad o a tu OCR.
2. 02  
### Captación de leads  
Convierte las notificaciones de formularios o los emails directos en leads del CRM, por dirección del remitente.
3. 03  
### Una sola bandeja con WhatsApp y SMS  
El mismo handler recibe los eventos de WhatsApp y SMS: solo cambia data.channel.type.
4. 04  
### Flujos sin código  
Apunta el webhook a n8n, Make o Zapier y ramifica según el asunto o el remitente, sin servidor.

La tabla

## Email entrante a webhook: SendGrid, Postmark y Unlimited Messaging

Los servicios de parsing reciben el correo de una dirección o un nombre de host nuevos. Unlimited Messaging lee el buzón que ya tienes.

__Email entrante a webhook: SendGrid, Postmark y Unlimited Messaging__
| [SendGrid Inbound Parse](https://www.twilio.com/docs/sendgrid/for-developers/parsing-email/setting-up-the-inbound-parse-webhook)MX en un nombre de host dedicado | [Postmark Inbound](https://postmarkapp.com/developer/user-guide/inbound/configure-an-inbound-server)Dirección o dominio de entrada | Unlimited MessagingTu buzón por IMAP, planes de pago      |                                                              |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------ |
| Dirección que recibe                                                                                                                                             | Cualquier dirección de un nombre de host dedicado al parsing                                                                       | yourhash@inbound.postmarkapp.com, o un reenvío hacia ella | Tu dirección de siempre                                      |
| Cambio de DNS                                                                                                                                                    | MX hacia mx.sendgrid.net                                                                                                           | Ninguno con reenvío; DNS para inbound domain forwarding   | Ninguno                                                      |
| Formato del cuerpo                                                                                                                                               | multipart/form-data, o el mensaje MIME original                                                                                    | JSON; autenticación HTTP basic en la URL como protección  | JSON, firmado según Standard Webhooks                        |
| Identificadores de hilo                                                                                                                                          | En las cabeceras que analizas                                                                                                      | En las cabeceras analizadas                               | conversation.id (raíz del hilo) y replyTo, listos para usar  |
| Responder desde la misma dirección                                                                                                                               | Con el envío de SendGrid, configurado aparte                                                                                       | Con el envío de Postmark, configurado aparte              | replyToMessageId, por el SMTP de tu buzón, copia en Enviados |
| Precio                                                                                                                                                           | Incluido en un plan de SendGrid                                                                                                    | Entrada en el plan Pro, desde 16,50 $ al mes              | Webhooks con Medium o Max; sin coste por email               |
| WhatsApp y SMS en el mismo webhook                                                                                                                               | No                                                                                                                                 | No                                                        | Sí, el mismo sobre                                           |

Comprobado el 9 de noviembre de 2026 en la guía de configuración del Inbound Parse de SendGrid, la guía de servidores de entrada y la página de precios de Postmark (enlaces en las fuentes).

La letra pequeña

## ¿Qué límites tiene una pasarela de buzón a webhook?

Leer tu propio buzón elimina el trabajo de DNS. Trae consigo las reglas de ese buzón.

1. 01  
### Los webhooks son de pago  
En el plan Free, los emails recibidos aparecen en la bandeja de la aplicación web, agrupados por hilo. Enviarlos a tu servidor requiere Medium (19 € al mes, o 17 € al mes con pago anual) o Max.
2. 02  
### Solo la bandeja de entrada  
La pasarela vigila INBOX. Un email que tu proveedor marca como spam, o que un filtro mueve a otra carpeta, nunca se ve.
3. 03  
### Todavía sin Outlook ni Microsoft 365  
Outlook, Hotmail y Microsoft 365 exigen OAuth, previsto pero aún no disponible. Gmail funciona con una contraseña de aplicación, que requiere la verificación en dos pasos en la cuenta de Google.
4. 04  
### Hasta 20 adjuntos por email  
Los archivos a partir del 21 no se guardan. El HTML se pasa tal como llegó: sanéalo antes de mostrarlo en cualquier sitio.
5. 05  
### Al menos una vez, sin orden garantizado  
El mismo evento puede llegar dos veces, y los eventos no llegan en el orden en que ocurrieron: haz un upsert por eventId y ordena por sentAt.

Cómo elegir

### ¿Un servicio de parsing o tu propio buzón?

Recibes correo para miles de direcciones generadas (una por usuario, una por proyecto) en un dominio que controlas: un servicio de inbound parse con un MX está hecho para eso. Tus clientes escriben a una o pocas direcciones reales y quieres esos emails en tu código, con respuestas desde la misma dirección: conecta el buzón y suscríbete a message.received.

FAQ

## Preguntas sobre los webhooks de email entrante

O apuntas el MX de un dominio a un servicio de parsing (SendGrid, Postmark), o conectas el buzón por IMAP. Unlimited Messaging hace lo segundo: cada email nuevo de tu bandeja de entrada se envía a tu URL como JSON firmado, message.received, con el plan Medium o Max.

No. El buzón sigue recibiendo correo como antes; Unlimited Messaging lo lee por IMAP y envía por su SMTP. Nada cambia en tu DNS.

Sí, con una contraseña de aplicación de Google: activa la verificación en dos pasos, crea la contraseña en myaccount.google.com/apppasswords y pégala con tu dirección. También funcionan los buzones en tu propio dominio y otros proveedores IMAP/SMTP; Outlook y Microsoft 365 todavía no.

Cada email lista sus archivos en attachments, hasta 20: una url que sirve la copia guardada, filename, mimeType, size y contentId para imágenes incrustadas. Descarga la url cuando necesites el contenido.

Usa data.channel.conversation.id: es el Message-ID del primer email del hilo, tomado de References, así que cada respuesta lleva el mismo valor. replyTo.externalId indica el email exacto al que se responde.

Sí, según Standard Webhooks: cabeceras webhook-id, webhook-timestamp y webhook-signature, con un HMAC-SHA256 de id.timestamp.rawBody cuya clave es tu secreto whsec\_. Rechaza marcas de tiempo con más de 5 minutos de diferencia.

Los 429, 5xx, timeouts y errores de red se reintentan tras 30 s, 2 min, 10 min, 1 h, 6 h, 1 día y 2 días: 8 intentos en algo más de 3 días. Las demás respuestas 4xx son definitivas.

Sí. POST /message con replyToMessageId igual a data.message.id envía desde el mismo buzón, con Re: y las cabeceras In-Reply-To y References, y guarda una copia en Enviados.

Fuentes

## Fuentes y referencias

Para verificar por ti mismo la información de este artículo:

1. [01Setting up the Inbound Parse webhook (MX hacia mx.sendgrid.net, payload)↗Twilio SendGrid Docs](https://www.twilio.com/docs/sendgrid/for-developers/parsing-email/setting-up-the-inbound-parse-webhook)
2. [02Configure an inbound server (dirección de entrada, JSON, reenvío)↗Postmark](https://postmarkapp.com/developer/user-guide/inbound/configure-an-inbound-server)
3. [03Precios (procesamiento de entrada en Pro, desde 16,50 $ al mes)↗Postmark](https://postmarkapp.com/pricing)
4. [04RFC 5322, Internet Message Format (Message-ID, In-Reply-To, References)↗IETF](https://www.rfc-editor.org/rfc/rfc5322)
5. [05Iniciar sesión con contraseñas de aplicación↗Ayuda de Cuenta de Google](https://support.google.com/accounts/answer/185833)
6. [06Especificación Standard Webhooks↗standardwebhooks.com](https://www.standardwebhooks.com)
7. [07Referencia de la API de Unlimited Messaging - Webhooks↗Unlimited Messaging](https://docs.unlimitedmessaging.app)

![Ilian, ingeniero de software senior](https://ilianazz.com/images/iliazz.png)

Escrito por

[Ilian](https://unlimitedmessaging.app/es/authors/ilian) · Ingeniero de software senior

Ingeniero de software senior, funda y dirige varias empresas tecnológicas. Diseña productos en torno a las API de mensajería, la automatización y la integración de la IA, y comparte aquí lo que aprende construyendo.

[Ver el perfil de LinkedIn↗](https://www.linkedin.com/in/ilianAzz/)Actualizado el 9 de noviembre de 2026

![](https://unlimitedmessaging.app/assets/logos/whatsapp.svg)![](https://unlimitedmessaging.app/assets/logos/email.svg)![](https://unlimitedmessaging.app/assets/logos/sms.svg)

## Tu bandeja de entrada, en JSON limpio.

Crea una cuenta, conecta tu buzón y activa los webhooks con Medium o Max. Enviar emails sigue siendo gratis en todos los planes.

[Crear una cuenta gratis→](https://app.unlimitedmessaging.app)

Artículos similares
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fone-webhook-whatsapp-email-sms-es.png&w=3840&q=75)Un solo webhook para WhatsApp, email y SMS: ¿hasta dónde llega?Cada respuesta en tu número, tu buzón y tu móvil en un sobre JSON firmado: bandeja de soporte, contestador con IA o sincronización CRM.](https://unlimitedmessaging.app/es/articles/one-webhook-whatsapp-email-sms)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fgmail-imap-smtp-app-password-es.png&w=3840&q=75)Conecta Gmail por IMAP/SMTP en 3 pasos con una contraseña de appGmailConecta tu propio Gmail por IMAP/SMTP en tres pasos con una contraseña de aplicación de Google, gratis en todos los planes.](https://unlimitedmessaging.app/es/articles/gmail-imap-smtp-app-password)
* [![](https://unlimitedmessaging.app/_next/image?url=%2Fassets%2Farticles%2Fcovers%2Fsend-from-your-own-mailbox-and-number-es.png&w=3840&q=75)Por qué tu propio correo y número superan a un remitente compartidoPor qué enviar desde tu dirección y tu número de WhatsApp en lugar de un remitente compartido: tu reputación, tu identidad, tus respuestas, gratis en todos los planes.](https://unlimitedmessaging.app/es/articles/send-from-your-own-mailbox-and-number)
