Arquitetura
O mxout é stateless: cada requisição HTTP inicia um ciclo completo de montagem, assinatura e entrega sem depender de estado externo.
Diagrama de fluxo
Aplicação
│
│ POST /send (JSON: from, to[], subject, body)
▼
┌─────────────────────────────────────────────────────┐
│ mxout │
│ │
│ 1. Valida domínio do from → busca kit DKIM │
│ 2. Gera Message-ID e Date │
│ 3. Monta MIME │
│ 4. Assina DKIM (RSA-SHA256) ← ledger │
│ │
│ Por destinatário: │
│ 5. Resolve DNS MX (menor prioridade primeiro) │
│ 6. Loop de retry (imediato, +5s, +10s, +30s) │
│ └── Conecta ao MX │
│ EHLO → STARTTLS? → re-EHLO │
│ → MAIL FROM → RCPT TO → DATA → QUIT │
│ ↓ │
│ 5xx → falha permanente (aborta) │
│ 4xx → retenta │
│ 2xx → sucesso ← ledger │
└─────────────────────────────────────────────────────┘
│
▼
MX do domínio destinoCiclo por destinatário
Uma única requisição POST /send pode conter múltiplos destinatários. Para cada um, o mxout executa o ciclo abaixo de forma independente.
1. Montagem MIME
O mxout constrói o e-mail com os dados recebidos. Gera o Message-ID no formato <unixts.token@dominio-do-from> e o Date antes de qualquer assinatura. Isso é necessário porque esses campos são assinados — gerá-los depois invalidaria a assinatura.
2. Assinatura DKIM
A chave privada RSA-2048 do domínio (indicada pelo kit configurado) assina os headers From, To, Subject, Date e Message-ID. O header DKIM-Signature resultante é inserido no e-mail.
3. Resolução de MX
O mxout consulta o DNS pelo registro MX do domínio do destinatário. Os servidores são ordenados por prioridade (menor valor = maior prioridade). Se não houver registro MX, o RFC 5321 permite usar o registro A como MX implícito — o mxout segue essa regra.
4. Loop de retry
Tentativas: imediata, +5 s, +10 s, +30 s (4 ao total). As tentativas ficam em memória; não há persistência.
- Resposta
5xxdo servidor remoto indica erro permanente. O destinatário é descartado imediatamente. - Resposta
4xxou falha de conexão indica erro temporário. O mxout retenta até esgotar as tentativas. - Esgotadas as tentativas sem sucesso, o erro é registrado no ledger e o destinatário é descartado.
Stateless e ledger
O mxout não mantém banco de dados nem fila em disco. O ledger gravado em stdout (JSON por linha) é a fonte de verdade de cada envio: contém o message_id, o destinatário, o resultado e os detalhes de cada tentativa.
- Ledger — formato completo dos eventos registrados.
- Entrega MX direta — detalha resolução de MX, STARTTLS e retry.