para probar un SendGrid Event Webhook en localhost, ejecute su controlador localmente, exponga su puerto con npx portpreview PORT, ingrese el resultado HTTPS punto final como SendGridURL de publicación y verifique cada solicitud con el Signed Event Webhook clave pública antes de procesar sus eventos.
¿Qué SendGrid Event Webhook envía
El Event Webhook informa lo que sucede después SendGrid acepta un mensaje. Los eventos de entregabilidad incluyen processed, delivered, deferred, bounce, y dropped. Los eventos de compromiso incluyen open, click, informes de spam y cambios de suscripción. Los campos exactos varían según el tipo de evento, por lo que la ruta se realiza principalmente en event y trate los campos opcionales como opcionales.
Un cuerpo de solicitud es un JSON formación, no necesariamente un objeto. SendGrid puede colocar varios eventos en un solo POST. Un manejador que asume req.body.event Se perderá silenciosamente el lote. El funcionario Event Webhook referencia documenta los nombres y campos de los eventos, incluidos sg_event_id y sg_message_id.
Utilice los eventos como hechos, no como órdenes. Por ejemplo, un delivered evento puede actualizar el estado del mensaje, mientras que un click puede agregar un registro de participación. Evite hacer un click El controlador sobrescribe un estado de cancelación de suscripción posterior simplemente porque las solicitudes llegaron desordenadas.
1. Cree un punto final local
Este Express El ejemplo aplica deliberadamente un analizador de cuerpo sin formato solo al SendGrid ruta. La verificación de la firma depende de los bytes exactos. SendGrid firmado; analizar y volver a serializar JSON puede cambiar esos bytes.
import express from 'express';
import { EventWebhook, EventWebhookHeader } from '@sendgrid/eventwebhook';
const app = express();
const verifier = new EventWebhook();
const publicKey = verifier.convertPublicKeyToECDSA(
process.env.SENDGRID_WEBHOOK_PUBLIC_KEY,
);
app.post(
'/webhooks/sendgrid',
express.raw({ type: 'application/json' }),
async (req, res) => {
const signature = req.get(EventWebhookHeader.SIGNATURE());
const timestamp = req.get(EventWebhookHeader.TIMESTAMP());
if (!signature || !timestamp || !verifier.verifySignature(
publicKey,
req.body,
signature,
timestamp,
)) {
return res.status(403).send('invalid signature');
}
let events;
try {
events = JSON.parse(req.body.toString('utf8'));
} catch {
return res.status(400).send('invalid JSON');
}
if (!Array.isArray(events)) {
return res.status(400).send('expected an event array');
}
await enqueueNewEvents(events);
return res.sendStatus(204);
},
);
app.use(express.json());
app.listen(3000);
Instale el ayudante oficial con npm install @sendgrid/eventwebhook. Monte global express.json() después de esta ruta, o excluir explícitamente esta ruta. La misma regla se aplica en Next.js, Fastify, NestJS, funciones sin servidor y API puertas de enlace: conserva el cuerpo original como una cadena o un búfer de bytes hasta que la verificación se realice correctamente. El funcionario SendGrid El repositorio de nodos tiene una coincidencia firmado Event Webhook ejemplo.
2. Dar SendGrid un HTTPS URL
Mantenga la aplicación en ejecución, luego open una segunda terminal:
npx portpreview 3000
PortPreview imprime un publico HTTPS origen. si es https://example.portpreview.dev, la URL completa de la publicación es:
https://example.portpreview.dev/webhooks/sendgrid
El camino debe coincidir exactamente con la ruta. Mantenga vivo el proceso del túnel mientras realiza la prueba. Un túnel adelanta el tráfico; no reemplaza su servidor local, por lo que las fallas de conexión generalmente significan que la aplicación se detiene, escucha en otro puerto o está vinculada de una manera que el túnel no puede alcanzar.
3. Configurar el Event Webhook en SendGrid
- En el SendGrid interfaz de usuario, open Ajustes > Configuración de correo.
- En Configuración de webhook, open Event Webhooks y elige Crear nuevo webhook.
- Habilítelo, agregue el PortPreview URL como URL de publicación y seleccione solo las acciones que su aplicación necesita.
- En Funciones de seguridad, habilite Signed Event Webhook.
- Guarde el webhook, vuelva aopen su configuración, copie la clave de verificación pública generada y guárdela como
SENDGRID_WEBHOOK_PUBLIC_KEY. - Usar Test Your Integrationy luego envía un mensaje real para ejercitar los tipos de eventos que importan.
SendGrides actual guía de configuración señala que la prueba envía eventos de ejemplo en lugar de datos de un envío de correo real. Guardar antes de probar signature verificación: el par de claves se genera cuando el Signed Event Webhook se guarda la configuración.
Cómo SendGridLa verificación del webhook firmado funciona
Signed Event Webhook usos ECDSA. SendGrid guarda la clave privada y le muestra la clave de verificación pública correspondiente. Cada entrega incluye X-Twilio-Email-Event-Webhook-Signature y X-Twilio-Email-Event-Webhook-Timestamp. La verificación cubre el timestamp concatenado con los bytes de carga útil sin procesar y un SHA-256 picadillo; el signature es Base64-codificado. El asistente oficial maneja la conversión de clave pública, signature decodificación, hash y ECDSA verificación.
Esta es una verificación asimétrica: el valor mostrado es una clave pública, no un secreto HMAC. No ejecute la carga útil JSON.stringify(), recorte espacios en blanco, agregue una nueva línea o verifique un elemento de la matriz a la vez. Primero verifique los bytes de solicitud completos y luego analice la matriz. Ver SendGrid's documentación de características de seguridad para el algoritmo y los encabezados.
Un válido signature establece que los bytes firmados provienen del titular de SendGridLa clave privada y no fueron alteradas. No hace que el procesamiento de eventos sea idempotente, no autoriza acciones arbitrarias ni prueba que un evento sea nuevo. Esos son controles separados.
Hacer que el procesamiento por lotes sea idempotente
SendGrid los reintentos fallaron POSTs, y las redes pueden perder una respuesta exitosa. Por lo tanto, la entrega duplicada es normal. Utilice cada evento sg_event_id como clave de deduplicación principal, con una restricción de base de datos única. Si su producto combina múltiples SendGrid cuentas o entornos, espacio de nombres de la clave por proveedor y cuenta o entorno.
async function enqueueNewEvents(events) {
for (const event of events) {
await db.transaction(async (tx) => {
const inserted = await tx.webhookReceipts.insertIfAbsent({
provider: 'sendgrid',
eventId: event.sg_event_id,
receivedAt: new Date(),
});
if (!inserted) return;
await tx.jobs.enqueue({
type: 'process-sendgrid-event',
payload: event,
});
});
}
}
El inserto del recibo y la cola duradera deben comprometerse juntos. Solo devuelva 2xx después de que el lote esté duradero accepted. Si un evento falla después de que otros se hayan confirmado, una respuesta que no sea 2xx puede hacer que se devuelva toda la solicitud; la deduplicación permite que el siguiente intento omita eventos ya accepted y continuar con seguridad. No utilices un en memoria Set en producción porque los reinicios lo borran y varias instancias no lo comparten. El más amplio Guía de idempotencia y reintento de webhook cubre patrones duraderos.
Comprender los reintentos antes de elegir códigos de estado
De acuerdo a SendGrid's Event Webhook documentación, una respuesta 2xx marca la POST exitoso. Una respuesta que no sea 2xx provoca reintentos a intervalos crecientes hasta 24 horas después del evento; Esta es una ventana móvil para cada nuevo evento fallido. Ese comportamiento significa una permanente signature el fallo también puede generar intentos repetidos, mientras que devolver 2xx para un evento que nunca almacenó lo pierde.
- 2xx: el lote completo ha sido autenticado y duradero accepted, o todos los eventos ya se conocen.
- 4xx: entrada mal formada o no autenticada. Registre sólo diagnósticos seguros; esperar SendGridComportamiento general de reintento no 2xx.
- 5xx: una falla transitoria de base de datos, cola o aplicación que se debe volver a intentar.
Mantenga la ruta de solicitud breve: verifique, valide la forma exterior, deduplica atómicamente y ponga en cola, luego responda. Realizar actualizaciones de análisis de correo electrónico, CRM sincronización y notificaciones en trabajadores.
Solución de problemas locales SendGrid ganchos web
El signature siempre es inválido
La causa más común es JSON middleware que consume el cuerpo antes de la verificación. Confirmar que el verificador recibe el original. Buffer, incluido cualquier espacio en blanco inicial o final. Luego verifique que la clave pública pertenezca exactamente a este Event Webhook configuración y que ambos Twilio Los encabezados llegan a la aplicación sin cambios. Reinicie el proceso local después de cambiar su entorno.
La integración de la prueba tiene éxito, pero los eventos reales no aparecen
Verifique que el webhook esté habilitado y que las acciones deseadas estén seleccionadas. Las aperturas requieren open seguimiento, y clickRequerimos click seguimiento. Recuerde también que la solicitud de prueba contiene ejemplos; Utilice un envío real para validar secuencias y campos similares a los de producción.
El punto final devuelve 404 o 502
Para 404, compare la ruta configurada con /webhooks/sendgrid. Para errores de puerta de enlace, asegúrese de que la aplicación local se esté ejecutando en el mismo puerto pasado a PortPreview. Si las solicitudes llegan pero devuelven 500, inspeccione los registros locales y reduzca temporalmente el controlador a verificación más captura duradera.
Los eventos están duplicados o desordenados.
Esa es una realidad del sistema de entrega, no evidencia de que el túnel duplique el tráfico. Deduplicar por sg_event_id, haga que las transiciones de estado sean monótonas siempre que sea posible y almacene el tiempo del evento por separado del tiempo de recepción. Utilice el flujo de trabajo de depuración de webhook local para aislar errores de transporte, autenticación y lógica empresarial.
Lista de verificación de seguridad para uso local y de producción
- Usar HTTPS y verificar cada signature antes de analizar o registrar los detalles del evento.
- Mantenga la clave de verificación pública en la configuración para que pueda actualizarse limpiamente cuando cambie la clave del webhook.
- Aceptar POST únicamente, limite el tamaño de la solicitud, valide que el valor analizado sea una matriz y permita solo los nombres de eventos que usted maneje.
- No coloque PII en SendGrid categorías o argumentos únicos; SendGridLa referencia advierte explícitamente que esos campos se almacenan y no se tratan como PII.
- No exponga una sesión de administración, una consola de depuración ni rutas locales no relacionadas a través del mismo origen temporal.
- No registre direcciones de destinatarios, cargas útiles, signatures, o valores ambientales a menos que sean necesarios y estén redactados adecuadamente.
- Reemplace la URL del túnel temporal con una producción estable HTTPS endpoint después de la prueba y deshabilite las configuraciones de webhook obsoletas.
SendGrid también puede usar OAuth 2.0 para Event Webhook seguridad, ya sea solo o junto signatures. Si su implementación necesita portador-token controles del ciclo de vida, siga la guía de seguridad oficial en lugar de inventar un token intercambio. La verificación de firma sigue siendo valiosa porque vincula la información exacta timestamp y bytes de carga útil.
Una prueba de aceptación lista para producción
- Envíe una solicitud de prueba firmada y confirme una respuesta 2xx.
- Cambie un byte de carga útil y confirme un 403 sin escritura en la base de datos.
- Vuelva a reproducir la solicitud válida idéntica y confirme que no haya trabajos duplicados ni acciones comerciales.
- Enviar un JSON objeto en lugar de una matriz y confirme un 400 controlado.
- Detenga la base de datos brevemente, confirme un 5xx, restáurelo y verifique que se pueda volver a intentar. accepted una vez.
- Envíe un correo electrónico real y confirme que los eventos de entrega y participación seleccionados sigan el mismo camino.
Una vez que se pasen estas comprobaciones, mueva el punto final a producción sin cambiar la lógica de verificación e idempotencia. Para modos de falla criptográfica más profundos, lea el gancho web signature guía de verificación.
