Alle Artikel
SendGrid Event Webhooks auf localhost testen
SendGridemail webhookssignature verificationlocalhost

SendGrid Event Webhooks auf localhost testen

Um ein SendGrid Event Webhook auf localhost zu testen, führen Sie Ihren Handler lokal aus, setzen Sie seinen Port mit npx portpreview PORTGeben Sie den resultierenden HTTPS-Endpunkt als SendGrid Post-URL ein und überprüfen Sie jede Anfrage mit dem Signed Event Webhook Public Key, bevor Sie ihre Ereignisse verarbeiten.

Was die SendGrid Event Webhook sendet

Die Event Webhook berichtet, was passiert, nachdem SendGrid eine Nachricht akzeptiert hat. Zu liefernde Ereignisse umfassen processed, delivered, deferred, bounce, und droppedEngagement-Events umfassen open, clickSpam-Berichte und Abonnementänderungen. Die genauen Felder variieren je nach Ereignistyp, so dass die Route hauptsächlich auf event und optionale Felder als optional behandeln.

Eine Request Body ist ein JSON ArraySendGrid kann mehrere Ereignisse in einem einzigen POST platzieren. Ein Handler, der annimmt, req.body.event Sie werden den Batch stillschweigend vermissen. Der Beamte Event Webhook Referenz dokumentiert die Ereignisnamen und -felder, einschließlich sg_event_id und sg_message_id.

Benutze Ereignisse als Fakten, nicht als Befehle. Beispielsweise kann ein delivered-Ereignis den Nachrichtenstatus aktualisieren, während ein Klick einen Engagement-Record anhängen kann. Vermeiden Sie es, dass ein Click-Handler einen späteren Abmeldezustand überschreibt, nur weil Anfragen nicht in Ordnung sind.

1. Erstellen Sie einen lokalen Endpunkt

Dieses Express Beispiel wendet absichtlich einen Rohkörper-Parser nur auf die SendGrid Route an. Die Signaturverifizierung hängt von den genauen signierten Bytes SendGrid ab; das Parsen und Re-Serialisieren von JSON kann diese Bytes ändern.

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);

Installieren Sie den offiziellen Helfer mit npm install @sendgrid/eventwebhookMount global express.json() nach dieser Route, oder diesen Pfad explizit ausschließen. Die gleiche Regel gilt für Next.js, Fastify, NestJS, serverlose Funktionen und API-Gateways: Behalten Sie den ursprünglichen Körper als String- oder Bytepuffer, bis die Überprüfung erfolgreich ist. Der offizielle SendGrid Node Repository hat ein Matching signiertes Event Webhook Beispiel.

2. Geben Sie SendGrid eine HTTPS URL

Halten Sie die Anwendung am Laufen und öffnen Sie dann ein zweites Terminal:

npx portpreview 3000

PortPreview druckt einen öffentlichen HTTPS-Ursprung. Wenn es https://example.portpreview.devDie vollständige Post-URL lautet:

https://example.portpreview.dev/webhooks/sendgrid

Der Pfad muss genau mit der Route übereinstimmen. Halten Sie den Tunnelprozess beim Testen am Leben. Ein tunnel leitet den datenverkehr weiter; es ersetzt nicht ihren lokalen server, so dass verbindungsfehler normalerweise bedeuten, dass die app gestoppt wird, an einem anderen port hört oder auf eine weise gebunden wird, die der tunnel nicht erreichen kann.

3. Konfigurieren Sie die Event Webhook in SendGrid

  1. In der SendGrid UI, offen Einstellungen > Mail Einstellungen.
  2. Unter Webhook Einstellungen, offen Event Webhooks und wählen Erstellen Sie einen neuen Webhook.
  3. Aktivieren Sie es, fügen Sie die PortPreview URL als Post-URL hinzu und wählen Sie nur die Aktionen aus, die Ihre Anwendung benötigt.
  4. Unter Sicherheitsfunktionen aktivieren Signed Event Webhook.
  5. Speichern Sie den Webhook, öffnen Sie seine Einstellungen erneut, kopieren Sie den generierten öffentlichen Verifizierungsschlüssel und speichern Sie ihn als SENDGRID_WEBHOOK_PUBLIC_KEY.
  6. Verwendung Testen Sie Ihre IntegrationSenden Sie dann eine echte Nachricht, um die Ereignistypen auszuüben, die wichtig sind.

SendGrid Strom Aufstellführung stellt fest, dass der Test Beispielereignisse anstelle von Daten aus einem echten E-Mail-Versand sendet. Speichern Sie vor dem Testen der Signaturverifizierung: Das Schlüsselpaar wird generiert, wenn die Signed Event Webhook-Konfiguration gespeichert wird.

Wie die signierte Webhook-Verifizierung von SendGrid funktioniert

Signed Event Webhook verwendet ECDSA. SendGrid behält den privaten Schlüssel und zeigt Ihnen den entsprechenden öffentlichen Verifizierungsschlüssel an. Jede Lieferung beinhaltet X-Twilio-Email-Event-Webhook-Signature und X-Twilio-Email-Event-Webhook-TimestampDie Verifizierung umfasst den Zeitstempel, der mit den Rohnutzlastbytes und einemSHA-256Hash; die Signatur istBase64-kodiert. Der offizielle Helfer übernimmt Public-Key-Konvertierung, Signatur-Dekodierung, Hashing undECDSAÜberprüfung.

Dies ist eine asymmetrische Überprüfung: Der angezeigte Wert ist ein öffentlicher Schlüssel, kein HMAC-Geheimnis. Führen Sie die Nutzlast nicht durch JSON.stringify()Trimmen Sie Whitespace, fügen Sie eine Newline an oder verifizieren Sie jeweils ein Array-Element. Überprüfen Sie zuerst die vollständigen Anforderungsbytes und analysieren Sie dann das Array. Siehe SendGrid Dokumentation der Sicherheitsmerkmale für den Algorithmus und Header.

Eine gültige Signatur stellt fest, dass die signierten Bytes vom Inhaber des privaten Schlüssels von SendGrid stammen und nicht verändert wurden. Es macht die Ereignisverarbeitung nicht idempotent, autorisiert willkürliche Aktionen oder beweist, dass ein Ereignis neu ist. Das sind getrennte Kontrollen.

Machen Batch-Verarbeitung idempotent

SendGrid wiederholt fehlgeschlagene POSTs, und Netzwerke können eine erfolgreiche Antwort verlieren. Daher ist eine doppelte Lieferung normal. Verwenden Sie jedes Ereignis sg_event_id als primärer Deduplizierungsschlüssel mit einer eindeutigen Datenbankeinschränkung. Wenn Ihr Produkt mehrere SendGrid-Konten oder -Umgebungen kombiniert, benennen Sie den Schlüssel nach Anbieter und Konto oder Umgebung.

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,
      });
    });
  }
}

Die Quittungsbeilage und die dauerhafte Warteschlange sollten sich verbinden. Nur 2xx zurückgeben, nachdem der Batch dauerhaft ist accepted. Wenn ein Ereignis fehlschlägt, nachdem andere sich verpflichtet haben, kann eine Nicht-2xx-Antwort dazu führen, dass die gesamte Anforderung zurückkehrt; Deduplizierung lässt den nächsten Versuch bereits Ereignisse überspringen accepted und sicher fortfahren. Verwenden Sie kein In-Memory Set in der Produktion, weil Neustarts es löschen und mehrere Instanzen es nicht teilen. Der breitere Webhook Retry und Idempotency Guide deckt dauerhafte Muster ab.

Retries verstehen, bevor Sie Statuscodes auswählen

Laut SendGrids Event Webhook Dokumentation markiert eine 2xx Antwort den POST erfolgreich. Eine Nicht-2xx-Antwort verursacht Wiederholungen in zunehmenden Abständen für bis zu 24 Stunden nach dem Ereignis; Dies ist ein rollendes Fenster für jedes neue fehlgeschlagene Ereignis. Dieses Verhalten bedeutet, dass ein permanenter Signaturfehler auch wiederholte Versuche erzeugen kann, während die Rückgabe von 2xx für ein Ereignis, das Sie nie gespeichert haben, es verliert.

  • 2xx: die gesamte Charge wurde authentifiziert und dauerhaft accepted, oder jedes Ereignis ist bereits bekannt.
  • 4xx: fehlerhafte oder nicht authentifizierte Inputs. Logge nur sichere Diagnosen; erwarte das allgemeine Nicht-2xx-Wiederholungsverhalten von SendGrid.
  • 5xx: Eine transiente Datenbank, Warteschlange oder ein Anwendungsfehler, der wiederholt werden sollte.

Halten Sie den Anforderungspfad kurz: Überprüfen, validieren Sie die äußere Form, deduplizieren und enqueue atomar und antworten Sie dann. Führen Sie E-Mail-Analyse-Updates, CRM-Synchronisierung und Benachrichtigungen in Mitarbeitern durch.

Fehlersuche bei lokalen SendGrid Webhooks

Die Unterschrift ist immer ungültig

Die häufigste Ursache ist JSON Middleware, die den Körper vor der Verifizierung verbraucht. Bestätigen Sie, dass die Prüfstelle das Original erhält Buffer, einschließlich aller führenden oder nachlaufenden Whitespace. Überprüfen Sie dann, ob der öffentliche Schlüssel zu dieser genauen Event Webhook-Konfiguration gehört und dass beide Twilio-Header unverändert die App erreichen. Starten Sie den lokalen Prozess neu, nachdem Sie seine Umgebung geändert haben.

Testintegration gelingt, aber reale Ereignisse erscheinen nicht

Stellen Sie sicher, dass der Webhook aktiviert ist und dass die gewünschten Aktionen ausgewählt sind. Opens erfordern offenes Tracking und Klicks erfordern Klick-Tracking. Denken Sie auch daran, dass die Testanforderung Beispiele enthält; Verwenden Sie einen tatsächlichen Send, um produktionsähnliche Felder und Sequenzierung zu validieren.

Der Endpunkt gibt 404 oder 502 zurück

Für 404 vergleichen Sie den konfigurierten Pfad mit /webhooks/sendgridStellen Sie bei Gateway-Fehlern sicher, dass die lokale App auf demselben Port läuft, der an PortPreview übergeben wurde. Wenn anfragen ankommen, aber 500 zurückgeben, überprüfen sie lokale protokolle und reduzieren sie den handler vorübergehend auf die Überprüfung plus dauerhafte erfassung.

Veranstaltungen sind dupliziert oder nicht in Ordnung

Das ist eine Realität des Liefersystems, kein Beweis dafür, dass der Tunnel den Verkehr dupliziert hat. Dedupliziert von sg_event_idZustandsübergänge nach Möglichkeit monoton machen und Ereigniszeit getrennt von der Empfangszeit speichern. Verwenden Sie die Webhook Debugging Workflow um Transport-, Authentifizierungs- und Business-Logikfehler zu isolieren.

Sicherheits-Checkliste für den lokalen und produktionstechnischen Einsatz

  • Verwenden Sie HTTPS und überprüfen Sie jede Signatur, bevor Sie Ereignisdetails analysieren oder protokollieren.
  • Behalten Sie den öffentlichen Verifizierungsschlüssel in der Konfiguration, damit er sauber aktualisiert werden kann, wenn sich der Webhook-Schlüssel ändert.
  • Akzeptieren Sie nur POST, begrenzen Sie die Anforderungsgröße, validieren Sie, dass der analysierte Wert ein Array ist, und erlauben Sie nur Ereignisnamen, die Sie bearbeiten.
  • Platzieren Sie PII nicht in SendGrid Kategorien oder eindeutige Argumente; SendGrid's Referenz warnt ausdrücklich, dass diese Felder gespeichert und nicht als PII behandelt werden.
  • Stellen Sie keine Admin-Sitzung, Debug-Konsole oder nicht verwandte lokale Routen über denselben temporären Ursprung frei.
  • Protokollieren Sie keine Empfängeradressen, Nutzlasten, Signaturen oder Umgebungswerte, es sei denn, dies ist notwendig und angemessen geändert.
  • Ersetzen Sie die temporäre Tunnel-URL nach dem Testen durch einen stabilen HTTPS-Endpunkt in der Produktion und deaktivieren Sie veraltete Webhook-Konfigurationen.

SendGrid kann OAuth 2.0 auch für Event Webhook Sicherheit verwenden, entweder allein oder neben Signaturen. Wenn Ihre Bereitstellung eine Bearer-Token-Lebenszyklussteuerung erfordert, folgen Sie dem offiziellen Sicherheitsleitfaden, anstatt einen Token-Austausch zu erfinden. Die Signaturverifizierung bleibt wertvoll, da sie die genauen Zeitstempel- und Nutzdatenbytes bindet.

Ein produktionsfertiger Abnahmetest

  1. Senden Sie eine signierte Testanfrage und bestätigen Sie eine 2xx Antwort.
  2. Ändern Sie ein Payload-Byte und bestätigen Sie eine 403 ohne Datenbankschreiben.
  3. Wiederholen Sie die identische gültige Anforderung und bestätigen Sie keine doppelte Aufgabe oder Geschäftsaktion.
  4. Senden Sie ein JSON-Objekt anstelle eines Arrays und bestätigen Sie eine kontrollierte 400.
  5. Stoppen Sie die Datenbank kurz, bestätigen Sie eine 5xx, stellen Sie sie wieder her und überprüfen Sie, ob ein Wiederholungsversuch einmal accepted ist.
  6. Senden Sie eine echte E-Mail und bestätigen Sie, dass die ausgewählten Liefer- und Engagement-Events dem gleichen Weg folgen.

Sobald diese Prüfungen bestanden haben, verschieben Sie den Endpunkt in die Produktion, ohne die Verifizierungs- und Idempotenzlogik zu ändern. Für tiefere kryptographische Fehlermodi lesen Sie die Webhook-Signaturprüfungsleitfaden.

Häufig gestellte Fragen

Kann SendGrid Event Webhooks an localhost senden?
Nicht direkt. Führen Sie den Handler lokal aus, starten Sie `npx portpreview PORT` und konfigurieren Sie die generierte öffentliche HTTPS-URL plus Ihren Webhook-Pfad als SendGrid Post-URL.
Wie prüfe ich ein SendGrid signiertes Event Webhook?
Lesen Sie die X-Twilio-Email-Event-Webhook-Signature- und X-Twilio-Email-Event-Webhook-Timestamp-Header, bewahren Sie den vollständigen rohen Request-Body und überprüfen Sie sie mit dem öffentlichen Schlüssel mit dem offiziellen Event Webhook-Helfer von SendGrid.
Warum schlägt die SendGrid Webhook-Verifizierung nach dem JSON-Parsing fehl?
Die ECDSA-Signatur deckt den Zeitstempel plus die genauen rohen Nutzlastbytes ab. Das Parsen und Re-Serialisieren von JSON kann Whitespace oder Formatierung ändern, so dass die Überprüfung mit dem ursprünglichen Buffer oder String erfolgen muss, bevor JSON Parsen.
Ist SendGrid fehlgeschlagen Event Webhooks?
SendGrid dokumentiert die Erhöhung der Wiederholungsintervalle für Nicht-2xx-Antworten für bis zu 24 Stunden nach jedem Ereignis. Geben Sie 2xx erst zurück, nachdem der Batch authentifiziert und dauerhaft accepted ist, und deduplizieren Sie mit sg_event_id.