Todos os artigos
Como testar Event Webhooks da SendGrid no localhost
SendGridemail webhookssignature verificationlocalhost

Como testar Event Webhooks da SendGrid no localhost

Para testar um SendGrid Event Webhook no localhost, execute seu manipulador localmente, exponha sua porta com npx portpreview PORT, insira o endpoint HTTPS resultante como URL de publicação SendGrid, e verifique cada solicitação com a chave pública Signed Event Webhook antes de processar seus eventos.

O que o SendGrid Event Webhook envia

O Event Webhook relata o que acontece após SendGrid aceitar uma mensagem. Os eventos de entregabilidade incluem processed, delivered, deferred, bounce, e dropped. Os eventos de noivado incluem open, click, relatórios de spam e alterações de assinatura. Os campos exatos variam de acordo com o tipo de evento, então roteie primeiramente em event e tratar campos opcionais como opcional.

Um corpo de solicitação é um JSON array, não necessariamente um objeto. SendGrid pode colocar vários eventos em um único POST. Um manipulador que assume req.body.event vai silenciosamente perder o lote. O funcionário Event Webhook referência documenta os nomes e campos dos eventos, incluindo sg_event_id e sg_message_id.

Use eventos como fatos, não comandos. Por exemplo, um evento delivered pode atualizar o status da mensagem, enquanto um clique pode adicionar um registro de engajamento. Evite fazer um manipulador de clique sobrescrever um estado de cancelamento posterior simplesmente porque os pedidos chegaram fora de ordem.

1. Criar um endpoint local

Este exemplo Express aplica deliberadamente um analisador de corpo bruto apenas à rota SendGrid. A verificação da assinatura depende dos bytes exatos SendGrid assinados; o processamento e o re-serialização do JSON podem alterar esses 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);

Instalar o ajudante oficial com npm install @sendgrid/eventwebhook. Montar global express.json() após esta rota, ou explicitamente excluir este caminho. A mesma regra se aplica em Next.js, Fastify, NestJS, funções sem servidor e gateways API: reter o corpo original como um buffer string ou byte até que a verificação tenha sucesso. O funcionário SendGrid O repositório de nós tem uma correspondência assinado Event Webhook exemplo.

2. Dê SendGrid uma URL HTTPS

Mantenha a aplicação em execução e abra um segundo terminal:

npx portpreview 3000

PortPreview imprime uma origem HTTPS pública. Se for https://example.portpreview.dev, o URL completo do Post é:

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

O caminho deve corresponder exactamente à rota. Mantenha o processo do túnel vivo durante os testes. Um túnel avança o tráfego; ele não substitui seu servidor local, então falhas de conexão geralmente significam que o aplicativo é parado, ouvindo em outra porta, ou vinculado de uma forma que o túnel não pode alcançar.

3. Configure o Event Webhook em SendGrid

  1. Na interface SendGrid, aberta Configuração > Configuração do E- mail.
  2. Em Configuração do Webhook, abrir Event Webhooks e escolher Criar um novo webhook.
  3. Habilite-o, adicione o URL PortPreview como URL de publicação e selecione apenas as ações que sua aplicação precisa.
  4. Em recursos de segurança, habilitar Signed Event Webhook.
  5. Salve o webhook, reabra suas configurações, copie a chave de verificação pública gerada e armazene-a como SENDGRID_WEBHOOK_PUBLIC_KEY.
  6. Utilização Teste sua integração, então envie uma mensagem real para exercer os tipos de eventos que importam.

SendGrid é atual guia de configuração observa que o teste envia eventos de exemplo em vez de dados de um envio de e- mail real. Salve antes de testar a verificação da assinatura: o par de chaves é gerado quando a configuração Signed Event Webhook é salva.

Como funciona a verificação do Webhook assinado SendGrid

Signed Event Webhook usa ECDSA. SendGrid mantém a chave privada e exibe a correspondente chave de verificação pública para você. Cada entrega inclui X-Twilio-Email-Event-Webhook-Signature e X-Twilio-Email-Event-Webhook-Timestamp. Verificação cobre o timestamp concatenado com os bytes de carga útil brutos e um hash SHA-256; a assinatura é codificada por Base64. O auxiliar oficial lida com conversão de chave pública, decodificação de assinatura, hashing e verificação ECDSA.

Esta é uma verificação assimétrica: o valor exibido é uma chave pública, não um segredo HMAC. Não executar a carga útil através JSON.stringify(), aparar espaço em branco, adicionar uma nova linha, ou verificar um elemento array de cada vez. Verifique os bytes de solicitação completos primeiro, em seguida, analisar o array. Ver SendGrid Documentação das características de segurança para o algoritmo e cabeçalhos.

Uma assinatura válida estabelece que os bytes assinados vieram do titular da chave privada SendGrid e não foram alterados. Ele não faz o processamento de eventos idempotent, autorizar ações arbitrárias, ou provar que um evento é novo. São controles separados.

Tornar o processamento em lote idempotent

SendGrid repetições falharam POSTs, e as redes podem perder uma resposta bem sucedida. Portanto, o parto em duplicata é normal. Usar cada evento sg_event_id como chave primária de deduplicação, com uma restrição única de banco de dados. Se seu produto combina várias contas ou ambientes SendGrid, o namespace é a chave por provedor e conta ou ambiente.

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

O inserto de recibo e enqueue durável devem comprometer-se em conjunto. Apenas devolva 2xx após o lote ser duravelmente accepted. Se um evento falhar após o commit de outros, uma resposta non-2xx pode fazer com que toda a requisição retorne; a deduplicação permite que a próxima tentativa ignore os eventos já accepted e continue em segurança. Não utilize uma memória Set na produção porque reinicia-o e várias instâncias não o partilham. O mais amplo webhook retry e guia de idempotência abrange padrões duradouros.

Compreender as tentativas antes de escolher os códigos de estado

SegundoSendGrid'sWebhook do eventodocumentação, uma resposta 2xx marca o sucesso do POST. Uma resposta não 2xx provoca repetições em intervalos crescentes por até 24 horas após o evento; esta é uma janela de rolamento para cada novo evento falhando. Esse comportamento significa que uma falha de assinatura permanente também pode gerar tentativas repetidas, enquanto retornar 2xx para um evento que você nunca armazenou perde.

  • 2xx: o lote completo foi autenticado e duravelmente accepted, ou cada evento já é conhecido.
  • 4xx: Entrada mal formada ou não autenticada. Log somente diagnósticos seguros; esperar SendGrid não- 2xx geral retry behavior.
  • 5xx: uma base de dados transitória, fila ou falha na aplicação que deve ser tentada novamente.

Mantenha o caminho da solicitação curto: verificar, validar a forma externa, deduplicar atomicamente e enqueue, em seguida, responder. Execute atualizações de análise de email, sincronização de CRM e notificações em trabalhadores.

Resolução de problemas locais SendGrid Webhooks

A assinatura é sempre inválida

A causa mais comum é o middleware JSON consumindo o corpo antes da verificação. Confirmar que o verificador recebe o original Buffer, incluindo qualquer espaço em branco. Em seguida, verifique se a chave pública pertence a esta configuração exata Event Webhook e que ambos os cabeçalhos Twilio atingem o aplicativo inalterado. Reinicie o processo local após alterar seu ambiente.

A Integração de Testes tem sucesso, mas os eventos reais não aparecem

Verifique se o webhook está habilitado e se as ações desejadas estão selecionadas. Abre requer rastreamento aberto, e cliques requerem rastreamento clique. Lembre-se também que a solicitação de teste contém exemplos; use um envio real para validar campos tipo produção e sequenciamento.

O parâmetro final devolve 404 ou 502

Para 404, compare o caminho configurado com /webhooks/sendgrid. Para erros de gateway, certifique-se de que o aplicativo local está rodando na mesma porta passada para PortPreview. Se as solicitações chegarem mas retornarem 500, inspecione os registros locais e reduza temporariamente o manipulador para verificação e captura durável.

Os eventos são duplicados ou fora de ordem

Essa é uma realidade do sistema de entrega, não evidência de que o túnel duplicou o tráfego. Desduplicar por sg_event_id, fazer transições de estado monotônicas sempre que possível, e armazenar tempo de evento separadamente do tempo de recepção. Utilizar o fluxo de trabalho de depuração Webhook local isolar falhas de transporte, autenticação e lógica de negócios.

Verificação de segurança para uso local e de produção

  • Use HTTPS e verifique cada assinatura antes de processar ou registrar os detalhes do evento.
  • Mantenha a chave de verificação pública na configuração para que ela possa ser atualizada de forma limpa quando a chave webhook mudar.
  • Aceitar POST somente, limitar o tamanho da solicitação, validar que o valor analisado é um array, e permitir apenas nomes de eventos que você lida.
  • Não coloque PII em categorias SendGrid ou argumentos únicos; a referência de SendGrid adverte explicitamente que esses campos são armazenados e não tratados como PII.
  • Não expor uma sessão de administração, console de depuração ou rotas locais não relacionadas através da mesma origem temporária.
  • Não registrar endereços do destinatário, cargas úteis, assinaturas ou valores de ambiente, a menos que necessário e adequadamente redigido.
  • Substitua a URL temporária do túnel por um endpoint HTTPS de produção estável após testes e desativa as configurações do webhook.

SendGrid também pode usar OAuth 2.0 para segurança Event Webhook, tanto sozinho quanto ao lado de assinaturas. Se a sua implantação precisar de controles de ciclo de vida, siga o guia de segurança oficial em vez de inventar uma troca de fichas. A verificação da assinatura continua a ser valiosa, pois liga o horário exato e os bytes de carga útil.

Ensaio de aceitação pronto para a produção

  1. Envie um pedido de teste assinado e confirme uma resposta 2xx.
  2. Mude um byte de carga útil e confirme um 403 sem gravação de banco de dados.
  3. Reproduza o pedido válido idêntico e confirme sem duplicar trabalho ou ação de negócios.
  4. Envie um objeto JSON em vez de um array e confirme um 400 controlado.
  5. Parar o banco de dados brevemente, confirmar um 5xx, restaurá-lo, e verificar que uma repetição é accepted uma vez.
  6. Envie um e-mail real e confirme os eventos de entrega e engajamento selecionados seguindo o mesmo caminho.

Uma vez que essas verificações passem, mova o endpoint para a produção sem alterar a lógica de verificação e idempotência. Para modos de falha criptográfica mais profundos, leia o guia de verificação da assinatura webhook.

Perguntas frequentes

Pode SendGrid enviar Event Webhooks para localhost?
Não directamente. Execute o manipulador localmente, inicie `npx portpreview PORT` e configure o URL HTTPS público gerado e o seu caminho webhook como URL de publicação SendGrid.
Como posso verificar um SendGrid assinado Event Webhook?
Leia os cabeçalhos X-Twilio-Email-Event-Webhook-Signature e X-Twilio-Email-Event-Webhook-Timestamp, preserve o corpo de solicitação bruto completo, e verifique-os com a chave pública usando SendGrid oficial Event Webhook helper.
Por que a verificação do Webhook SendGrid falha após a análise do JSON?
A assinatura ECDSA cobre o timestamp mais os bytes de carga bruta exatos. A análise e re-serialização do JSON podem alterar o espaço em branco ou a formatação, então a verificação deve acontecer contra o Buffer ou string original antes da análise do JSON.
A repetição do SendGrid falhou Event Webhooks?
Sim. SendGrid documentos aumentando intervalos de repetição para respostas não 2xx por até 24 horas após cada evento. Devolver 2xx apenas após o lote ser autenticado e duravelmente accepted, e desduplicar com sg_event_id.