Padrão de e-mail
Status: canônico · Escopo: Como escrever e enviar e-mail transacional da Tactflow · Atualizado em: 2026-08-10
Cada regra aqui saiu de um defeito real, e a maioria só apareceu depois de mandar o e-mail de verdade e olhar como quem recebe. Teste com
fetchfalso passou em todos eles.
1. Onde as coisas ficam
Seção intitulada “1. Onde as coisas ficam”| o quê | onde |
|---|---|
| Cabeçalho, cores, cartão, rodapé | apps/api-worker/src/notifications/emails/layout.ts |
| Um e-mail específico | apps/api-worker/src/notifications/emails/<nome>.ts |
| O envio | apps/api-worker/src/notifications/resend-email.ts |
Existem hoje: booking-link (o prospect escolhe horário) e owner-booking (o dono é avisado de um
agendamento novo). O segundo é a coisa mais parecida com o produto que o cliente compra — ele não
liga para o agente, liga para saber que entrou trabalho.
E-mail novo monta o conteúdo e chama montarEmail. Não reescreve cabeçalho nem rodapé — mexer
no layout muda todos de uma vez, que é o ponto de ele existir.
2. Cor: a regra do site vale aqui
Seção intitulada “2. Cor: a regra do site vale aqui”elec #6e9bff SÓ sobre navyblue #2762eb SÓ sobre paper/brancoNão é gosto. elec sobre branco some, e é a primeira coisa que denuncia e-mail montado às pressas.
A fonte é global.css do site.
O gesto ousado fica em um lugar por e-mail — o número em elec sobre navy, ou o botão em blue.
Dois blocos berrantes disputando atenção viram nenhum.
3. Sempre uma versão em texto
Seção intitulada “3. Sempre uma versão em texto”text é obrigatório mesmo quando existe html. Duas razões, e as duas custam caro:
- Mensagem só-HTML é sinal clássico de spam para Gmail e Outlook, e quem paga é o domínio inteiro, não só aquele envio.
- Quem lê em texto puro precisa conseguir agir. Se a única saída é um botão, essa pessoa fica sem saída — todo link do HTML tem que aparecer como URL no texto.
4. Assunto
Seção intitulada “4. Assunto”- Sem valor financeiro.
$18,720 a year in calls you never picked upmuda o registro de “aqui está o que você pediu” para “olha essa oferta”, e o e-mail deixa de parecer o que é. - Reconhecível na primeira olhada. O primeiro e-mail que um desconhecido recebe chega com o aviso “você geralmente não recebe e-mails deste remetente” no Outlook. Não dá para remover — dá para o assunto responder “isso é o que eu pedi” antes de a pessoa decidir se confia.
5. Perguntar de onde a pessoa veio, não presumir
Seção intitulada “5. Perguntar de onde a pessoa veio, não presumir”⚠️ A regra que mais rendeu defeito. O mesmo passo de contato tem duas portas:
| porta | o que a pessoa viu |
|---|---|
| funil | setor, ligações perdidas, valor do serviço, taxa de fechamento |
formulário ou /book | nada |
O e-mail abria com “thanks for going through the numbers” para os dois. Para quem veio pelo formulário, isso cita algo que nunca aconteceu — e o efeito é pior que texto genérico: parece e-mail trocado, ou automação mal feita.
Todo e-mail que muda de contexto recebe a informação de contexto como parâmetro e tem teste para
os dois caminhos. Ver booking-link.ts (sawBreakdown).
6. Link para humano usa chat, não api
Seção intitulada “6. Link para humano usa chat, não api”chat.tactflow.io página de agendamento, embed — o que uma PESSOA abreapi.tactflow.io webhook, callback de OAuth — o que uma MÁQUINA chamaUse resolveUiOrigin(env) em e-mail, nunca resolveAppOrigin. Um dono de HVAC lê o link antes de
clicar, e “api” não diz nada para ele.
7. Visualização que precisa de legenda não entra
Seção intitulada “7. Visualização que precisa de legenda não entra”Duas tentativas de mostrar “5 de 35 ligações eram trabalho” falharam:
- Barra proporcional — 86% preenchida com um pedaço claro no fim lia como barra de progresso quase completa, que é sinal positivo. O significado era o oposto.
- 35 quadradinhos — viraram padrão decorativo, e a pergunta que surgiu foi “o que é isso?”.
A frase sozinha já entregava. Se o leitor precisa da legenda para entender o gráfico, o gráfico está pedindo trabalho dele — e a legenda já era a resposta.
8. Tabela e estilo inline, não flexbox
Seção intitulada “8. Tabela e estilo inline, não flexbox”O Outlook renderiza com o motor do Word e ignora boa parte do CSS moderno. <table> com
style="..." em cada célula é feio de escrever e previsível de receber.
Sem <style> no <head>: vários clientes removem. Sem webfont: não carrega de forma confiável — a
pilha começa com Bricolage Grotesque para quem já a tem instalada e cai na sans do sistema.
Imagem: só o logo, servido de tactflow.io, e em PNG. SVG não renderiza no Gmail. Nada essencial
pode depender de imagem carregar — metade dos clientes bloqueia por padrão, e é por isso que
“Tactflow” ao lado do logo é texto.
9. Falha de envio não derruba a resposta
Seção intitulada “9. Falha de envio não derruba a resposta”O e-mail sai depois de gravar o que importa, e a falha dele vai para o log sem mudar o que a tela mostra.
Contato é o que não dá para recuperar depois. Perder um lead porque o serviço de e-mail caiu seria trocar um problema pequeno por um irreversível.
10. Antes de subir: mande para você mesmo
Seção intitulada “10. Antes de subir: mande para você mesmo”⚠️ Teste com fetch falso não prova que o e-mail chega, nem que ele faz sentido.
Os dois defeitos mais caros deste arquivo passaram por todos os testes automáticos:
- o remetente estava em
@send.tactflow.ioe o Resend recusou com403 domain is not verified— só o envio real disse isso; - a abertura citava números para quem nunca viu número — só apareceu quando um humano leu.
Para extrair o conteúdo real do módulo (e não uma cópia) e enviar:
# teste temporário que despeja o e-mail montadopnpm --filter @voltron/api-worker exec vitest run src/notifications/emails/_preview.test.ts# depois: POST para https://api.resend.com/emails com o JSON geradoConferir na caixa: caiu na entrada ou no spam, e no cabeçalho (Gmail → Mostrar original) se
SPF, DKIM e DMARC estão todos em PASS.
11. Infraestrutura de domínio
Seção intitulada “11. Infraestrutura de domínio”| registro | estado |
|---|---|
SPF (send.tactflow.io) | ✅ include:amazonses.com |
DKIM (resend._domainkey) | ✅ |
DMARC (_dmarc) | ✅ p=none desde 10/08/2026 |
⚠️ O domínio verificado no Resend é tactflow.io, e é de lá que se envia. O send.tactflow.io
é o return-path — é contra ele que o SPF é conferido, e por isso ele aponta para o Resend enquanto
a raiz aponta para o Google Workspace, que recebe o e-mail humano. Quem alinha o DMARC aqui é o
DKIM, não o SPF.
O DMARC está em modo monitoramento de propósito: com dois remetentes no domínio, subir para
quarantine antes de confirmar alinhamento derrubaria e-mail legítimo. Falta criar o alias
dmarc@tactflow.io para receber os relatórios.
Onde continuar
Seção intitulada “Onde continuar”- A casca:
layout.ts - Identidade visual:
global.cssdo site - Contrato do funil:
talk-contract.md