guia · api de e-mail
Como uma equipe de produto deve implementar uma API de e-mail com segurança?
Implemente uma API de e-mail como um fluxo assíncrono e com permissões, e não como uma chamada direta do formulário para o provedor. Autentique quem chama, confirme que o tenant é dono de um domínio From verificado, valide e dimensione a mensagem, atribua um ID de job estável na aplicação, coloque-a na fila uma única vez e faça a submissão a partir de um worker. Registre o ID de mensagem do provedor no momento da aceitação, ingira os eventos de entrega de forma idempotente e suprima bounces permanentes e reclamações. Use novas tentativas limitadas somente quando o risco de duplicação estiver controlado. Mantenha as credenciais no servidor, minimize os dados de mensagens nos logs e diferencie a aceitação pela API, a entrega ao servidor de e-mail e a chegada à caixa de entrada.
Defina o limite da API antes de escolher um provedor
Uma API de e-mail deve expor a intenção da aplicação sem vazar todos os detalhes do provedor para o código do produto. Defina recursos para mensagens, domínios de envio, chaves de API, eventos e supressões. Decida quais campos quem chama pode controlar, incluindo From, To, Reply-To, assunto, texto, HTML e uma pequena lista de permissão de cabeçalhos. Rejeite cabeçalhos de transporte fornecidos por quem chama que possam entrar em conflito com a assinatura ou o roteamento do provedor. Trate o envio como uma escrita com consequências: a resposta deve identificar um recurso de mensagem da aplicação e seu estado atual, sem sugerir um resultado na caixa postal. Mantenha a conta do provedor, a região, o configuration set e os identificadores de transporte atrás de um adapter. Esse limite torna a migração de provedor possível e dá um lugar estável para os controles de autorização, retenção e abuso.
Autentique quem chama e autorize cada domínio de remetente
Armazene as chaves de API apenas como hashes unidirecionais e exiba o segredo completo uma única vez. Dê a cada chave um workspace responsável, status, data de criação e um caminho de revogação; adicione escopos mais restritos quando uma integração só deve enviar ou só deve ler eventos. A autenticação responde quem apresentou uma credencial, enquanto a autorização decide se aquele principal pode usar o domínio From e o recurso de mensagem solicitados. Verifique a propriedade do domínio em cada envio, inclusive nos endpoints de lote, em vez de confiar em um identificador de domínio fornecido pelo cliente. Exija a verificação no provedor antes de habilitar tráfego de produção. Nunca coloque credenciais do provedor ou chaves de API do workspace em JavaScript do navegador, query strings, ferramentas de analytics ou mensagens de erro. A autorização no nível de objeto é especialmente importante para identificadores de mensagem, evento, supressão, caixa de entrada e domínio em uma API multi-tenant.
Verifique o domínio e alinhe a autenticação
Um domínio de envio precisa de mais do que uma flag no banco de dados. Conclua a verificação de propriedade do provedor e publique os registros DKIM exigidos. O SPF autoriza hosts para a identidade SMTP MAIL FROM ou HELO, enquanto o DKIM associa um domínio de assinatura a uma assinatura criptográfica da mensagem. O DMARC avalia se um identificador SPF ou DKIM bem-sucedido está alinhado com o domínio From visível da RFC 5322 e permite que o dono do domínio publique uma política de tratamento e de relatórios. Quando o domínio já tiver SPF, mescle o mecanismo exigido no registro existente; a RFC 7208 diz que um domínio não deve publicar vários registros que levem à seleção de mais de um registro SPF. Adote uma política DMARC mais rígida somente depois que mensagens controladas e relatórios agregados mostrarem que todos os remetentes legítimos estão alinhados. A autenticação reduz o uso não autorizado do domínio, mas não garante a chegada à caixa de entrada.
Valide a estrutura da mensagem e minimize a entrada aceita
A RFC 5322 define uma mensagem de Internet como campos de cabeçalho seguidos de um corpo opcional, e as especificações MIME estendem o conteúdo além do texto básico. Uma API pode esconder a maior parte dos detalhes do formato de transmissão e ainda assim aplicá-los. Normalize os arrays de destinatários, limite a quantidade de destinatários e o tamanho total codificado, exija pelo menos um corpo em texto ou HTML e valide os endereços sem fingir que a sintaxe comprova a existência da caixa postal. Remova caracteres de retorno de carro e de quebra de linha dos campos que viram cabeçalhos. Gere o Message-ID ou deixe o provedor gerá-lo; não o reutilize como ID de job da aplicação, porque uma nova versão da mensagem pode receber legitimamente um novo identificador. Permita apenas cabeçalhos personalizados documentados, rejeite duplicatas de campos protegidos e renderize os templates antes da submissão ao provedor, para que variáveis ausentes falhem em um estado controlado da aplicação.
Coloque na fila uma única vez e use identificadores estáveis na aplicação
Uma requisição do usuário deve criar um job de mensagem durável dentro de uma transação e, depois, um worker deve fazer a chamada ao provedor. Dê ao job um identificador estável e registre uma impressão digital da requisição ou uma chave de idempotência fornecida por quem chama, quando o contrato suportar isso. O HTTP define o POST como não idempotente por padrão e desaconselha novas tentativas automáticas, a menos que o cliente saiba que a operação é efetivamente idempotente ou que a requisição original não foi aplicada. Isso importa no e-mail, porque um timeout pode ocorrer depois de o provedor aceitar a mensagem, mas antes de o worker receber a resposta. Em caso de falha ambígua, reconcilie primeiro o job armazenado e o estado no provedor, em vez de criar um novo envio. Use o padrão outbox quando o estado da aplicação e a publicação na fila precisarem avançar juntos e coloque uma restrição de unicidade no limite de idempotência.
Projete as novas tentativas em torno das classes de falha
Separe validação, autorização, throttling, rejeição pelo provedor, falha transitória de transporte e falha de entrega ao destinatário. Entrada inválida e domínio From não autorizado devem falhar sem nova tentativa. Limites de taxa do provedor e erros temporários de serviço podem ser tentados novamente com backoff exponencial limitado, jitter, um teto de tentativas e um visibility timeout da fila maior que o prazo de requisição do worker. Um timeout de rede ambíguo exige reconciliação que leve em conta duplicatas, e não uma nova requisição incondicional. O próprio SMTP diferencia respostas transitórias 4xx de permanentes 5xx, mas uma aplicação que usa a API de um provedor deve seguir a semântica de erros documentada por esse provedor. Mova os jobs esgotados para um estado de dead-letter revisável e mantenha o motivo sanitizado. Não tente novamente um bounce permanente de destinatário como se fosse uma indisponibilidade da API e não transforme uma reclamação em outra tentativa de envio.
Registre a aceitação e ingira os eventos de entrega
Persista o identificador da mensagem do provedor imediatamente após a aceitação e mapeie-o para o ID da mensagem da aplicação. Assim, os eventos do provedor podem atualizar o recurso correto mesmo quando um relatório de reclamação oculta detalhes do destinatário. O Amazon SES, por exemplo, diferencia um envio bem-sucedido da entrega ao servidor de e-mail do destinatário e pode publicar eventos de entrega, bounce, reclamação, rejeição, atraso de entrega, falha de renderização, abertura e clique. Verifique a autenticidade do webhook usando o mecanismo documentado pelo provedor, valide o esquema do evento, elimine duplicatas por um identificador de evento do provedor ou impressão digital determinística e permita a entrega repetida do mesmo evento sem repetir efeitos colaterais. Armazene payloads brutos apenas quando necessário, criptografados, com acesso controlado e retenção limitada. O estado normalizado deve distinguir resultados aceitos, entregues ao servidor, com bounce, com reclamação, atrasados, rejeitados e suprimidos.
Faça da supressão um controle no momento do envio
Um registro de supressão deve ser verificado antes de cada submissão ao provedor, e não apenas exibido em um painel. Endereços com bounce permanente e reclamações normalmente exigem supressão; atrasos temporários de entrega pedem uma política diferente. Defina o escopo da supressão de forma deliberada. Uma lista para toda a conta pode proteger a reputação compartilhada, mas pode permitir que o resultado de um destinatário de um tenant bloqueie outro tenant. Uma lista com escopo por tenant reduz esse acoplamento, mas ainda precisa de uma camada de proteção contra abuso e de segurança da plataforma. Registre o motivo, o evento de origem, o tenant, a data de criação e um caminho controlado de remoção. Remover a supressão de uma reclamação ou de um bounce permanente tem consequências e deve exigir revisão deliberada e evidência de que o endereço é válido e de que o destinatário espera a mensagem. Evite copiar endereços brutos de destinatários para logs gerais ou experimentos; o armazenamento operacional pode aplicar a política de envio enquanto o analytics usa contagens agregadas.
Proteja envios em lote e fluxos de negócio sensíveis
Um endpoint de lote multiplica o impacto de um erro de autorização ou de validação. Aplique as mesmas verificações de propriedade de domínio, supressão, tamanho e conteúdo a cada item, imponha um tamanho máximo rígido para o lote e retorne resultados por item sem vazar dados de outro tenant. Os limites de taxa devem existir nos níveis de credencial, workspace, domínio e provedor, com controles separados para picos e para volume contínuo. Um único limite global de requisições por segundo não basta, porque uma requisição pode conter muitos destinatários. Exija confirmação deliberada em ferramentas operadas por agentes antes que um lote de alto impacto seja submetido. Separe as permissões de e-mail transacional e de marketing quando as regras de consentimento e operação forem diferentes. Monitore crescimento incomum de destinatários, domínios rejeitados repetidamente, mudanças altas de bounce ou reclamação e criação rápida de chaves. O limite de taxa ajuda na segurança, mas não substitui autenticação, autorização de objetos, consentimento verificado nem resposta a abusos.
Teste os caminhos de falha antes da produção
Use simuladores do provedor ou caixas postais controladas para testar aceitação, entrega ao servidor de destino, hard bounce, reclamação, atraso, domínio inválido, chave revogada, throttling, timeout do provedor, webhook duplicado e reentrega pela fila. Confirme que a mesma chave de idempotência cria uma única mensagem na aplicação, que um evento reenviado não produz efeito colateral duplicado e que um tenant não consegue ler nem enviar usando o domínio ou o ID de mensagem de outro tenant. Inspecione uma mensagem real recebida para verificar From, Return-Path, DKIM, SPF, alinhamento DMARC, renderização de texto e HTML, comportamento de descadastro quando aplicável e links. Faça testes de carga na fila abaixo dos limites aprovados pelo provedor e verifique o backpressure, em vez de contorná-lo. Adicione alarmes para idade da fila, novas tentativas esgotadas, falhas de ingestão de eventos, folga de cota, mudanças de bounce e reclamação e callbacks do provedor ausentes. Um checklist de lançamento deve nomear um responsável para cada alerta e ação de recuperação.
Aplique o padrão com o SendHQ com cuidado
O SendHQ fornece chaves bearer com escopo por workspace, verificações de domínio From, criação de mensagens únicas e em lote, caixas de entrada de e-mail de entrada, eventos de mensagem e recursos de supressão. Esses recursos dão suporte à arquitetura deste guia: mantenha a chave no servidor, crie um recurso de mensagem, retenha seu ID e leia eventos posteriores em vez de tratar a resposta inicial como entrega final. Independentemente da plataforma, os chamadores continuam responsáveis pelos destinatários pretendidos, e-mails legais e esperados, precisão do conteúdo e aprovação cuidadosa de envios consequentes.
Perguntas frequentes
Uma API de e-mail deve enviar de forma síncrona a partir da requisição web?
Em geral, não. Crie uma mensagem durável na aplicação e coloque-a na fila; depois, deixe um worker chamar o provedor. Isso isola a latência, permite novas tentativas limitadas e facilita a reconciliação de resultados ambíguos do provedor.
Como evitar e-mails duplicados quando uma requisição dá timeout?
Use um ID de job estável na aplicação e um limite de idempotência com uma restrição de unicidade. Em um timeout ambíguo, reconcilie o job existente antes de fazer outra submissão ao provedor com uma nova identidade.
Uma resposta bem-sucedida da API de e-mail significa entrega?
Não. Normalmente, ela indica que a API ou o provedor aceitou a requisição. Use os eventos posteriores para diferenciar entrega ao servidor de destino, bounce, reclamação, atraso, rejeição e supressão da aceitação inicial.
De quais registros DNS uma API de e-mail precisa?
Os registros exatos dependem do provedor, mas o envio em produção costuma exigir verificação de domínio e DKIM, além de uma estratégia de SPF correta e uma política DMARC alinhada aos fluxos de envio legítimos.
As chaves de API devem ficar no código do navegador?
Não. Mantenha as credenciais do workspace e do provedor em um armazenamento de segredos no servidor, guarde as chaves de API da aplicação como hash sempre que possível, mostre os segredos completos uma única vez e ofereça caminhos rápidos de revogação e rotação.
Como uma API de e-mail deve tratar bounces permanentes?
Normalize o evento do provedor, mapeie-o para a mensagem da aplicação e suprima os envios rotineiros futuros para esse destinatário dentro do escopo pretendido. A remoção deve ser deliberada e apoiada por evidências.
Fontes
- RFC 9110: HTTP Semantics — Internet Engineering Task Force (em inglês)
- RFC 5321: Simple Mail Transfer Protocol — Internet Engineering Task Force (em inglês)
- RFC 5322: Internet Message Format — Internet Engineering Task Force (em inglês)
- RFC 6376: DomainKeys Identified Mail Signatures — Internet Engineering Task Force (em inglês)
- RFC 7208: Sender Policy Framework — Internet Engineering Task Force (em inglês)
- RFC 7489: Domain-based Message Authentication, Reporting, and Conformance — Internet Engineering Task Force (em inglês)
- Monitoring Amazon SES sending activity — Amazon Web Services (em inglês)
- Amazon SES notification troubleshooting — Amazon Web Services (em inglês)
- OWASP API Security Top 10 2023 — OWASP Foundation (em inglês)
- Contrato OpenAPI do SendHQ — SendHQ