Quem gerencia servidores de e-mail com frequência se depara com mensagens retidas na fila de saída sem um motivo óbvio à primeira vista. Muitas vezes, o que parece ser uma instabilidade no servidor de relay ou uma falha de rede é apenas um caractere a mais digitado pelo remetente ao preencher o endereço do destinatário.
No entanto, a forma como o Mail Transfer Agent (MTA) local e o servidor de entrega intermediário (smarthost) reagem a esse detalhe revela uma cadeia interessante de eventos: forks de processos, checagens de DNS em código C, filtros de spam intermediários e bancos de dados locais de retentativas.
Neste artigo, vamos analisar um trecho real extraído dos logs do Exim para entender o ciclo de vida completo de uma mensagem com domínio incorreto, por que ela não retorna imediatamente como erro permanente e como limpar esse acúmulo pelo terminal.
1. O log de eventos no Exim#
Ao investigar mensagens represadas em servidores Linux (como cPanel, DirectAdmin ou instalações dedicadas do Exim), o primeiro passo é buscar referências no arquivo /var/log/exim_mainlog.
O trecho abaixo mostra o rastro de uma mensagem enviada com múltiplos destinatários legítimos, mas com um endereço digitado incorretamente ([email protected] em vez de .com.br):
2026-04-23 10:30:51 1wFu8p-000000062Hd-1Bob <= [email protected] H=(ADMCON037) [186.237.144.42]:58230 P=esmtpsa X=TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256 A=dovecot_login:[email protected] S=49523 [email protected] T="RES: Listagem de cobranca" for [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
2026-04-23 10:30:51 cwd=/ 13 args: exim -bm -oem -oi -oMr spam-scanner -oMm 1wFu8p-000000062Hd-1Bob -oMai [email protected] -f [email protected] <[email protected]>
2026-04-23 10:30:51 1wFu8p-000000062NQ-2GiD <= [email protected] R=1wFu8p-000000062Hd-1Bob U=mailnull P=spam-scanner S=50322 [email protected] T="RES: Listagem de cobranca" for [email protected]
2026-04-23 10:30:51 1wFu8p-000000062Hd-1Bob <[email protected]>: imunifyemail_spamfilter_transport transport output: action=no action score=-4.359000/6.000000
2026-04-23 10:30:51 1wFu8p-000000062Hd-1Bob => [email protected] R=imunifyemail_spamfilter_router T=imunifyemail_spamfilter_transport
2026-04-23 10:30:52 1wFu8p-000000062NQ-2GiD == [email protected] R=smarthost_auth T=dkim_remote_smtp defer (-44) H=smarthost.domain.com [216.55.99.57]: SMTP error from remote mail server after RCPT TO:<[email protected]>: 450 4.1.2 <[email protected]>: Recipient address rejected: Domain not found
2026-04-23 10:43:06 1wFu8p-000000062NQ-2GiD == [email protected] routing defer (-52): retry time not reached
2026-04-23 10:58:06 1wFu8p-000000062NQ-2GiD == [email protected] R=smarthost_auth T=dkim_remote_smtp defer (-44) H=smarthost.domain.com [216.55.99.57]: SMTP error from remote mail server after RCPT TO:<[email protected]>: 450 4.1.2 <[email protected]>: Recipient address rejected: Domain not found
2. Decodificando o fluxo linha por linha#
Para entender o motivo pelo qual a mensagem permaneceu no spool, vamos examinar os quatro passos fundamentais desse processo.
Passo 1: Ingress e autenticação do remetente (<=)#
2026-04-23 10:30:51 1wFu8p-000000062Hd-1Bob <= [email protected] H=(ADMCON037) [186.237.144.42]:58230 P=esmtpsa ... A=dovecot_login:[email protected]
Nessa primeira linha, o Exim aceita a conexão de entrada:
- Identificador de mensagem: o identificador
1wFu8p-000000062Hd-1Bobé gerado para registrar a mensagem no spool local. - Símbolo de entrada (
<=): indica que a mensagem acabou de ser recebida pelo servidor. - Autenticação SASL (
A=dovecot_login): o Exim consulta o socket de autenticação do Dovecot para checar login e senha da conta[email protected]. Como a validação foi bem-sucedida, a submissão é autorizada. - Segurança da conexão (
P=esmtpsa X=TLS1.2...): a siglaesmtpsamostra que a transmissão ocorreu via ESMTP autenticado (a) sob camada TLS (s). - Destinatários múltiplos: o remetente incluiu vários destinatários no comando
RCPT TO, entre eles destinatários válidos e o endereço com erro tipográfico:[email protected].
Passo 2: O filtro de segurança e o fork com novo ID#
2026-04-23 10:30:51 cwd=/ 13 args: exim -bm -oem -oi -oMr spam-scanner ...
2026-04-23 10:30:51 1wFu8p-000000062NQ-2GiD <= [email protected] R=1wFu8p-000000062Hd-1Bob U=mailnull P=spam-scanner ...
Antes de entregar a mensagem à rede externa, o servidor a submete a um verificador antispam local (como ImunifyEmail ou SpamAssassin):
- O Exim executa um novo processo via
execve()com o parâmetro-oMr spam-scanner. - A mensagem original é copiada e re-injetada no spool sob o usuário de sistema
mailnull. - Essa nova instância recebe um novo ID:
1wFu8p-000000062NQ-2GiD, mantendo o vínculoR=1wFu8p-000000062Hd-1Bobpara fins de auditoria. - O filtro atribui uma pontuação de
-4.359000(abaixo do limiar de descarte de6.0), liberando o envio para o transporte de saída.
Passo 3: O adiamento no smarthost (defer -44)#
2026-04-23 10:30:52 1wFu8p-000000062NQ-2GiD == [email protected] R=smarthost_auth T=dkim_remote_smtp defer (-44) H=smarthost.domain.com [216.55.99.57]: SMTP error from remote mail server after RCPT TO:<[email protected]>: 450 4.1.2 <[email protected]>: Recipient address rejected: Domain not found
Aqui ocorre a primeira retenção:
- Símbolo de adiamento (
==): indica que a entrega não pôde ser completada nesta tentativa, mas a mensagem permanece na fila. - Roteador e transporte (
R=smarthost_auth T=dkim_remote_smtp): em vez de enviar diretamente para os registros MX do destinatário, o servidor local encaminha o fluxo para um smarthost de relay (216.55.99.57). - Resposta remota do smarthost: durante o diálogo SMTP, logo após o comando
RCPT TO:<[email protected]>, o smarthost consulta os registros DNS do domíniodomain.copm.br. Como não encontra registros MX ou A, ele recusa o recebimento temporariamente:
450 4.1.2 Recipient address rejected: Domain not found
Passo 4: O algoritmo de recuo e o banco de retentativas (defer -52)#
2026-04-23 10:43:06 1wFu8p-000000062NQ-2GiD == [email protected] routing defer (-52): retry time not reached
Cerca de 12 minutos depois, uma varredura periódica de fila (exim -q) tenta reprocessar as mensagens pendentes. O Exim consulta seu banco de dados de retentativas (retry.db) e identifica a marca routing defer (-52): retry time not reached.
Isso significa que o tempo mínimo de espera calculado pelo algoritmo de recuo exponencial (exponential backoff) ainda não expirou, poupando ciclos de CPU e conexões de rede desnecessárias com o smarthost.
3. Por que o smarthost responde com 450 em vez de 550#
Uma dúvida muito frequente em auditorias de e-mail é: se o domínio não existe, por que o servidor não rejeitou de imediato com um código 550 (erro permanente)?
A resposta está na convenção do protocolo SMTP (RFC 5321) e na implementação interna dos servidores de relay.
O comportamento interno da checagem em c#
Muitos smarthosts utilizam Postfix com a diretiva reject_unknown_recipient_domain ativada nas restrições de destinatário (smtpd_recipient_restrictions).
No código-fonte em C do Postfix (módulo smtpd_check.c), a verificação de domínio chama rotas de biblioteca que realizam consultas DNS:
/* Lógica simplificada de verificação DNS em smtpd_check.c */
int check_domain_dns(const char *domain) {
unsigned char reply[1024];
int len;
/* 1. Consulta MX (Mail Exchanger) */
len = res_search(domain, C_IN, T_MX, reply, sizeof(reply));
if (len >= 0) return DNS_FOUND;
/* 2. Fallback para registro A (IPv4) */
len = res_search(domain, C_IN, T_A, reply, sizeof(reply));
if (len >= 0) return DNS_FOUND;
/* 3. Avaliação do código de erro da biblioteca */
if (h_errno == HOST_NOT_FOUND) {
return DNS_NXDOMAIN;
}
return DNS_RETRY;
}
Quando a consulta retorna sem sucesso, o servidor precisa decidir entre:
- Erro permanente (550): o domínio definitivamente não existe no DNS raiz e não há dúvidas sobre isso.
- Erro temporário (450): a consulta falhou, mas pode ter ocorrido uma perda temporária de pacotes UDP na porta 53, timeout dos resolvers locais do smarthost ou uma zona recém-propagada.
Muitos provedores de relay corporativo configuram deliberadamente a recusa como código 450 para evitar descartes incorretos em caso de instabilidades pontuais no DNS. O efeito colateral é que erros de digitação óbvios (como .copm.br ou .gmial.com) não geram um bounce instantâneo para o usuário; em vez disso, a mensagem fica presa na fila tentando ser enviada por horas ou dias.
4. Descartando outras hipóteses antes de agir#
Mesmo quando um erro de digitação parece evidente, vale a pena descartar rapidamente dois cenários antes de limpar a fila:
Cenário 1: Falha na resolução de DNS do servidor local ou do relay#
Para confirmar se o domínio realmente não existe ou se o problema é uma falha pontual de DNS:
# 1. Consulta direcionada a servidores públicos globais
dig MX domain.copm.br @8.8.8.8 +trace +nodnssec
# 2. Verificar se há alguma entrada residual em /etc/hosts
grep -i "domain.copm.br" /etc/hosts
Se o retorno for status: NXDOMAIN, fica confirmado que o domínio não está registrado.
Cenário 2: Bloqueio ou greylisting disfarçado de erro de rota#
Alguns filtros corporativos retornam mensagens genéricas de recusa de endereço quando o remetente atinge limites de frequência ou quando o IP cai em regras de greylisting. É possível simular a conversa SMTP manualmente com o utilitário netcat:
nc -vv smarthost.domain.com 25 << 'EOF'
EHLO meu-servidor.local
MAIL FROM:<[email protected]>
RCPT TO:<[email protected]>
QUIT
EOF
Se a resposta permanecer consistente com 450 Recipient address rejected, trata-se da validação estrita de destinatário do relay.
5. Comandos práticos para inspecionar e limpar a fila#
Abaixo estão os comandos necessários para investigar mensagens retidas no Exim e removê-las com segurança.
Inspecionando metadados, corpo e logs de uma mensagem#
Para inspecionar os cabeçalhos salvos no spool (/var/spool/exim/input/<ID>-H):
exim -Mvh 1wFu8p-000000062NQ-2GiD
Para ler o corpo textual armazenado em disco (/var/spool/exim/input/<ID>-D):
exim -Mvb 1wFu8p-000000062NQ-2GiD
Para listar todos os eventos de log associados exclusivamente a esse identificador:
exim -Mvl 1wFu8p-000000062NQ-2GiD
Consultando o banco de retentativas (retry database)#
O Exim armazena o histórico de tentativas com falha em um banco de dados binário em /var/spool/exim/db/retry. Para consultar esses registros:
exim_dumpdb /var/spool/exim retry
Para forçar o envio imediato da mensagem ignorando o tempo de espera do banco de retentativas:
exim -M -v 1wFu8p-000000062NQ-2GiD
A flag -v exibe a negociação SMTP linha por linha no terminal em tempo real.
Removendo mensagens malformadas da fila#
Depois de confirmar que o endereço contém um erro de digitação e que os outros destinatários da mensagem já receberam suas cópias, remova o item da fila:
exim -Mrm 1wFu8p-000000062NQ-2GiD
Esse comando aciona internamente as chamadas unlink() para os arquivos de cabeçalho (-H) e dados (-D), liberando os inodes e o espaço em disco do servidor.
Se houver muitas mensagens presas para o mesmo domínio inexistente, você pode combinar o utilitário exiqgrep com xargs:
exiqgrep -i -r 'domain.copm.br' | xargs -r exim -Mrm
6. Depuração avançada de conexões com strace#
Se você precisar acompanhar a interação exata de rede entre o Exim e o smarthost (incluindo o envio do comando RCPT TO e o recebimento do código 450), anexe o strace ao processo forçando uma tentativa de entrega:
strace -f -s 512 -e trace=network,write,read exim -M 1wFu8p-000000062NQ-2GiD
Os parâmetros utilizados funcionam da seguinte forma:
-f: acompanha processos filhos criados porfork(), necessário porque o Exim delega o transporte para sub-processos.-s 512: expande o tamanho das strings exibidas na saída, permitindo ler os comandos SMTP por completo.-e trace=network,write,read: isola chamadas de rede (connect(),sendto(),recvfrom()) e operações de escrita/leitura, eliminando o ruído de checagens de bibliotecas e arquivos de configuração.
Rotina prática para evitar acúmulo de mensagens por erros de digitação#
Para manter a fila do Exim limpa sem depender de intervenções manuais diárias:
- Ajuste os tempos de expiração de fila: revise as diretivas
ignore_bounce_errors_afteretimeout_frozen_afterno arquivo de configuração do Exim para que mensagens com erros irreparáveis sejam descartadas automaticamente após 24 ou 48 horas. - Monitore destinatários com falhas recorrentes: crie um script simples em cron para alertar quando um mesmo domínio acumular dezenas de mensagens em estado de adiamento.
- Oriente os remetentes: quando notar mensagens retidas por erros tipográficos comuns (
.copm.br,.con.br,.gmai.com), avise o usuário da conta para que ele corrija o endereço no cliente de e-mail e evite reenvios sucessivos que alimentam o banco de retentativas.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários