Todos os artigos
Como testar webhooks do Mailgun no localhost
Mailgunemail webhooksHMAC verificationlocalhost

Como testar webhooks do Mailgun no localhost

Para testar o Mailgun webhooks no localhost, expor o seu manipulador local com npx portpreview PORT, configure o endpoint HTTPS resultante para os tipos de eventos necessários Mailgun, e verifique o timestamp, token e HMAC-SHA256 da carga útil antes de aceitar o evento.

O que Mailgun webhooks relatório

Mailgun envia um HTTP ou HTTPS POST com uma carga útil JSON quando um evento configurado ocorre. Os tipos de eventos atuais incluem accepted, delivered, temporary_fail, permanent_fail, opened, clicked, reclamações de spam e cancelamentos. Os eventos dependentes do rastreamento só aparecem quando o rastreamento correspondente está ativado.

Um corpo atual Mailgun Send webhook tem um signature objeto ao lado event-data. Os dados do evento contêm campos como event, id, timestamp, cabeçalhos de mensagens, informações do destinatário, etiquetas e detalhes de entrega, dependendo do tipo de evento. Código contra campos documentados e tolerar propriedades opcionais ausentes. Mailgun é oficial exemplos de carga útil são os melhores equipamentos para testes contratuais.

Não confunda um webhook Mailgun Send com Mailgun Alertas. Alertas usar uma chave de assinatura diferente e assinar todo o corpo POST em um X-Sign Cabeçalho. Este guia cobre Enviar webhooks: os campos de assinatura na carga útil e a conta Webhook Signing Key.

1. Construa um endpoint local Mailgun

Ao contrário de esquemas que assinam o corpo bruto do JSON, o cálculo documentado de Mailgun Send usa o timestamp e token do objeto de assinatura. A análise padrão da JSON é, portanto, apropriada. O seguinte Express manipulador verifica HMAC, executa uma verificação de replay-age, e duravelmente aceita o evento.

import crypto from 'node:crypto';
import express from 'express';

const app = express();
app.use(express.json({ limit: '1mb' }));

function verifyMailgunSignature({ timestamp, token, signature }) {
  if (!timestamp || !token || !signature) return false;

  const expected = crypto
    .createHmac('sha256', process.env.MAILGUN_WEBHOOK_SIGNING_KEY)
    .update(String(timestamp) + String(token))
    .digest('hex');

  const expectedBytes = Buffer.from(expected, 'hex');
  const actualBytes = Buffer.from(String(signature), 'hex');
  return expectedBytes.length === actualBytes.length &&
    crypto.timingSafeEqual(expectedBytes, actualBytes);
}

app.post('/webhooks/mailgun', async (req, res) => {
  const signing = req.body?.signature;
  const event = req.body?.['event-data'];

  if (!signing || !event || !verifyMailgunSignature(signing)) {
    return res.status(406).send('invalid webhook');
  }

  const ageSeconds = Math.abs(Date.now() / 1000 - Number(signing.timestamp));
  if (!Number.isFinite(ageSeconds) || ageSeconds > 15 * 60) {
    return res.status(406).send('stale webhook');
  }

  await acceptOnce({
    eventId: event.id,
    replayToken: signing.token,
    payload: event,
  });
  return res.sendStatus(200);
});

app.listen(3000);

A janela de 15 minutos é uma política de aplicação, não um valor Mailgun-mandado. Mailgun recomenda a verificação de que o timestamp não está muito longe do tempo atual, mas avisa para não ser excessivamente agressivo porque a entrega pode ser adiada. Escolha uma janela que se ajuste aos seus requisitos de espera e recuperação de incidentes, monitore rejeições legítimas e ajuste-a deliberadamente.

Armazenar o Webhook Signing Key em um gerenciador secreto ou variável de ambiente, nunca no controle de fonte. Mailgun's guia de fixação de ganchos web define o cálculo exato: concatenar timestamp e token sem separador, calcular HMAC-SHA256 usando o Webhook Signing Key, e comparar a digest signature.

2. Expor o host local sobre HTTPS

Com o aplicativo ouvindo na porta 3000, execute:

npx portpreview 3000

Anexar a rota local à origem pública do HTTPS. Por exemplo:

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

Deixe a aplicação e o túnel em execução durante o teste. Mailgun precisa de uma URL acessível publicamente; localhost, um endereço LAN privado, e um certificado de desenvolvimento autoassinado não são destinos remotos adequados. PortPreview termina HTTPS público e encaminha o pedido para sua porta local.

3. Configurar URLs de eventos Mailgun

Mailgun suporta a configuração webhook de nível de conta e de domínio. Os endpoints de nível de conta podem receber eventos entre domínios e subcontas herdadas; os endpoints de nível de domínio aplicam-se apenas a esse domínio. Cada tipo de evento é configurado individualmente e pode ter até três URLs. Selecione o escopo mais estreito que corresponde à sua aplicação.

  1. Abra a área Webhooks para a conta pretendida ou o domínio de envio.
  2. Escolha um tipo de evento, como delivered ou permanent_fail.
  3. Adicione o endpoint HTTPS completo PortPreview.
  4. Repita para cada evento tipo seu manipulador suporta.
  5. Envie um teste ou uma mensagem real e inspecione os registros de pedidos e aplicativos locais.

Mailgun deduplica o mesmo URL para o mesmo evento quando ele é configurado em ambos os níveis de conta e domínio, mas URLs diferentes podem receber uma cópia. A herança da conta-pai também pode causar entregas para múltiplos objetivos distintos. Revisão do funcionário regras de configuração antes de atribuir cada entrega extra para as repetições.

Como funciona a verificação da assinatura Mailgun

A signature objeto contém:

  • timestamp: Tempo Unix em segundos.
  • token: uma string de 50 caracteres gerada aleatoriamente.
  • signature: um HMAC hexadecimal digerir.
  • parent-signature: opcionalmente presente para um evento de uma subconta, permitindo validação contra a relação de conta primária descrita por Mailgun.

Para a assinatura normal da conta, calcular HMAC-SHA256(signingKey, timestamp + token)Não há separador e odados de eventosJSON não faz parte do documentadoEnviar uma Arma de CorreioCálculo. Compare bytes decodificados com uma função de temporização segura após verificar comprimentos iguais. Uma planície === a comparação é mais simples, mas uma comparação de tempo seguro é o padrão de produção mais seguro.

Um HMAC autêntico prova que uma parte com a chave de assinatura produziu a assinatura. Ele não prova que esta entrega não foi reproduzida. Mailgun recomenda especificamente caching o token e rejeitar uma solicitação posterior com o mesmo token. Uma verificação de tempo-idade limita quanto tempo uma solicitação válida capturada permanece útil. Use ambos os controles: uma restrição única para replay e uma janela de tempo razoável para frescura.

Desduplicar as entregas e os efeitos

Mantenha duas restrições de singularidade duráveis: uma para o símbolo de assinatura e outra para o Mailgun event-data.id. O token pega um replay de entrega assinado idêntico. O ID do evento protege a lógica de negócios se o mesmo evento aparecer em outro contexto de entrega válido. Espaço de nomes tanto por provedor e conta ou ambiente.

async function acceptOnce({ eventId, replayToken, payload }) {
  await db.transaction(async (tx) => {
    const tokenWasNew = await tx.webhookTokens.insertIfAbsent({
      provider: 'mailgun',
      token: replayToken,
    });
    if (!tokenWasNew) return;

    const eventWasNew = await tx.webhookEvents.insertIfAbsent({
      provider: 'mailgun',
      eventId,
      receivedAt: new Date(),
    });
    if (!eventWasNew) return;

    await tx.jobs.enqueue({
      type: 'process-mailgun-event',
      payload,
    });
  });
}

Voltar as operações inserir-se-se-ausent com índices originais do banco de dados; uma leitura seguida por um insert é race-prone sob entregas concorrentes. Submete os registos de dedup e a tarefa de fila atómica. Em seguida, reconheça rapidamente e deixe um trabalhador atualizar o estado da mensagem, ativar alertas ou sincronizar um CRM. Ver o guia de repetição e de indemnidade para alternativas quando a fila e o banco de dados de negócios não puderem compartilhar uma transação.

Mailgun códigos de resposta e comportamento de repetição

Mailgun atual Enviar documentação webhook dá três resultados importantes:

  • 200 Sucesso: Mailgun trata o webhook POST como bem sucedido e não tenta novamente.
  • 406 Não aceitável: Mailgun trata o POST como rejeitado e não tenta novamente.
  • Qualquer outro código: para outros webhooks que não as notificações de entrega, Mailgun volta mais de oito horas em 5 minutos, 10 minutos, 15 minutos, 1 hora, 2 horas e 4 horas.

A exceção de notificação de entrega é importante: não prometa que cada tipo de evento segue o cronograma geral de repetição. Verificar o mais recente Documentação automática de repetições quando as garantias de entrega afetam seu design.

Use 406 apenas para uma solicitação que você rejeita intencionalmente permanentemente, como uma assinatura inválida ou uma política externa de repetição. Use 500 ou 503 para falhas de banco de dados e filas transientes para que tipos de webhook elegíveis possam tentar novamente. Devolva 200 apenas após aceitação durável. Devolver 200 enquanto inicia o trabalho de fundo não rastreado pode perder o evento se o processo terminar.

Resolução de problemas Mailgun Webhooks localmente

O HMAC calculado nunca corresponde

Confirme que você está usando o Webhook Signing Key, não uma chave API, senha SMTP, ou Alertas de assinatura de chave. Concatene a hora da assinatura do objeto e o token sem delimitador. Produzir um hexadecimal minúsculoSHA-256digerir. Também verifique se o seu framework não renomeou o hífen event-data propriedade; notação do bracket evita esse erro.

O manipulador recebe campos de formulário em vez de JSON atual

Verifique qual Mailgun característica e versão de endpoint gerou o pedido. Não aplique um tutorial de carga útil legado cegamente a um webhook Send atual. Tipo de conteúdo de log, nomes de campo de topo e comprimento do corpo em desenvolvimento sem registrar conteúdo de mensagem ou segredos, em seguida, implementar o contrato documentado para sua conta e integração.

Mailgun continua tentando novamente

Inspecione o estado real enviado pelo fio. Uma exceção após o commit do banco de dados pode transformar a resposta em 500, causando outra tentativa. É por isso que o evento ID e inserções token deve ser único e durável. Se uma solicitação for permanentemente inválida, retorne 406; se a falha for transitória, conserte o serviço e permita que o comportamento de repetição funcione.

Nenhum evento atinge a máquina local

Confirme que a URL está anexada à conta ou domínio corretos e ao tipo de evento exato que está sendo produzido. A delivered URL não receberá opened eventos. Verifique se o processo local e o túnel ainda estão ativos e que o caminho configurado está /webhooks/mailgun. Seguir o guia de depuração do webhook local separar a configuração do provedor dos erros de roteamento e aplicação.

Verificação de segurança

  • Verificar o HMAC antes de confiar ou registrar event-data.
  • Mantenha a chave de assinatura em uma loja secreta e gire-a através de uma implantação controlada; nunca exponha-a em código do lado do cliente.
  • Use a comparação de digest timing-safe, uma política de timestamp e uma restrição única durável no token.
  • Validar o tipo de evento e os campos obrigatórios antes de entrar. Trate endereços de destinatários, assuntos, URLs de armazenamento e variáveis de usuário como dados sensíveis.
  • Aceite apenas POST, tamanho do corpo da cabeça, use HTTPS, e falhas de limite de taxa sem bloquear legítimas repetições Mailgun.
  • Não expor os endpoints não relacionados de administração local ou de depuração através da origem pública temporária.
  • Quando o teste terminar, remova o URL temporário e configure o endpoint de produção estável.

Mailgun também documenta um certificado opcional do cliente TLS em solicitações webhook quando seu servidor receptor tem TLS válido. Isso pode fornecer validação de nível de transporte, mas não substitui verificação de carga útil HMAC, controles de repetição e autorização de aplicação. A camada controla de acordo com o seu modelo de ameaça.

Ensaios de aceitação da produção

  1. Forneça uma luminária assinada válida e confirme um evento durável mais uma resposta de 200.
  2. Altere o token sem alterar a assinatura e confirme um 406 sem gravação de eventos.
  3. Repetir o corpo válido exato e confirmar nenhum segundo trabalho ou efeito colateral.
  4. Envie uma assinatura válida com uma hora marcada fora da janela configurada e verifique a rejeição pretendida.
  5. Forçar um erro de banco de dados temporário, confirmar uma resposta não-200/non-406, em seguida, restaurar o banco de dados e verificar uma aceitação bem sucedida.
  6. Exercite cada tipo de evento configurado Mailgun porque os campos de carga útil e as expectativas de repetição diferem.

Quando esses testes passarem, use o mesmo caminho de verificação e deduplicação na produção. Para uma explicação independente do fornecedor de comparação HMAC e manipulação secreta, leia o guia de verificação da assinatura webhook.

Perguntas frequentes

Pode Mailgun enviar webhooks para localhost?
O Mailgun não consegue chegar directamente à máquina local. Execute `npx portpreview PORT`, adicione sua rota webhook à origem HTTPS gerada e configure essa URL pública para cada tipo de evento Mailgun necessário.
Como posso verificar uma assinatura Mailgun Send webhook?
Concatene o timestamp do objeto de assinatura de carga útil e o token sem separador, calcule um digest hexadecimal HMAC-SHA256 usando o Webhook Signing Key, e compare-o com a assinatura fornecida usando uma comparação de tempo seguro.
Como faço para prevenir ataques de repetição de webhook Mailgun?
Guarde cada token de assinatura sob uma restrição única durável e rejeite um token já visto. Também aplicar uma política de timestamp-age razoável, permitindo tempo suficiente para atrasos de entrega legítimos e seus requisitos operacionais.
Quando é que o Mailgun tenta novamente um webhook falhado?
Mailgun trata 200 como sucesso e 406 como rejeição permanente. Para outras respostas, os webhooks que não as notificações de entrega usam os intervalos de repetição documentados durante cerca de oito horas, então os manipuladores devem ser idempotentes.