De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Ali Faiez Taha
Data de Publicação: 07 de outubro de 2011
A dica é bem simples. Examinar os logs de um Postfix. É lógico que tem ferramentas apropriadas, mas fazer alguns scripts para personalizar e mostrar dados que o usuário final possa entender facilita bastante.
Utilizando o PHP e alguns Shell Scripts para ajudar, dá para pegar muita informação importante do Postfix e analisar seus resultados, obter detalhes difíceis de enxergar nos logs e fazer consultas interessantes. Dá para se fazer muita coisa modificando os scripts ao seu gosto e suas necessidades.
O nome genérico do servidor de E-Mails é "servidor.com.br"
Foi utilizado o "pflogsumm" para fazer os relatórios do Postfix.
O arquivo principal.php é o interpretador dos scripts que vão examinar
os logs do Postfix:
<?php
$html = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"iso-8859-1\" xml:lang=\"iso-8859-1\">
<head>
<META HTTP-EQUIV=\"Content-Language\" content=\"pt-br\" />
<META HTTP-EQUIV=\"Expires: Mon, 26 Jul 1997 05:00:00 GMT\" />
<title>SERVIDOR.COM.BR - Relatorio de E-mails</title>
<style type=\"text/css\">
body {
font-family: arial;
font-size:15px;
color:black;
background-color:#ffffff;
font-weight:bold;
}
input {
border: 1px solid grey;
}
h1 {
text-align:center;
border-bottom: 1px solid black;
}
h2 {
margin-top:0px;
margin-bottom:0px;
}
.erro {
font-weight:bold;
color:red;
}
.inexistentes {
font-weight:bold;
color:black;
background-color:yellow;
}
</style>
</head>
<body>
<h1>Relatório de E-mails do SERVIDOR.COM.BR</h1>
<br>
<center>
<h2>
<form action=\"" . htmlentities($_SERVER['PHP_SELF']) . "\" method=\"post\">
Seu e-mail: <input type=\"text\" name=\"email\" size=\"15\" maxlength=\"20\" value=\"{$_POST['email']}\" />@servidor.com.br
<input type=\"submit\" value=\"Analisar\">
</form>
</h2>
</center>
<br />
<hr />
";
$emailServidor = $_POST['email'];
if (($emailServidor != '') and (!preg_match('/^[a-zA-Z0-9_.-]+$/',$emailServidor))) {
$html .= '<span class="erro">E-mail inválido !!!</span>';
} else if ($emailServidor != '') {
$emailServidor .= '@servidor.com.br'; //concatena resto do e-mail
$comandos = file('comandos.txt');
$resultados = array();
foreach ($comandos as $comando) {
list($rotulo,$cmd) = explode("\t",$comando);
$cmd = str_replace('email_aqui',$emailServidor,$cmd);
$r = shell_exec($cmd);
$resultados[] = array($rotulo,$r);
}
$novalinha = true;
foreach ($resultados as $resultado) {
list($rotulo,$linhas) = $resultado;
$html .= "<h2>{$rotulo}</h2>\n";
$linhas = htmlentities($linhas);
$linhas = explode("\n",$linhas);
foreach ($linhas as $linha) {
$linha = trim($linha);
if ($linha != '') {
$linha = str_replace('_frmi_','<span class="inexistentes">',$linha);
$linha = str_replace('_frmf_','</span>',$linha);
$html .= "{$linha}<br />\n";
}
}
}
}
$html .= "\n</body>\n</html>";
echo $html;
?>
Os scripts que preparei para minhas necessidades estão no
arquivo "comandos.txt".
(download do arquivo comandos.txt).
Deve-se usar 'tab' depois da tag </font> e antes do comando awk
(e outros), sempre! Por exemplo:
Lista de E-Mails RECEBIDOS:</b></font> awk
A variável email_aqui é usada como parâmetro de entrada para o principal.php (acima).
É o e-mail do usuário cadastrado no Servidor Postfix.
O pflogsumm gera os relatórios e estes ficam armazenados no diretório /php/relatorios/
<br>
<font color="red"><b>
Data: date "+%d-%B-%Y"
</b></font><br>
<font color="blue"><b>
<hr>
<center>Informações do usuário</center>
</b></font>
<hr>
<font color="black"><b>
Lista de E-Mails RECEBIDOS:</b></font> awk '{print $1,$2,$3,$6,$7}' /var/log/maillog | egrep -A 3 -w "from" | grep -v "message-id" | grep -v "removed" | grep -v "connect from" | grep -v "client=" | egrep -B 2 -w "email_aqui" | awk '{print $0}' | awk -F"from=" '{print $2}' | grep "<" | sort | uniq -c | sort -r | tr -d "," | head -20
<hr>
<font color="black"><b>
E-Mails enviados pelo usuário:</b></font> cat /var/log/maillog | egrep '(postfix/qmgr\[|postfix/smtp\[)' | egrep '(from|to)' | awk '{print $1,$2,$3,$6,$7}' | grep -A 1 "email_aqui" | sed '/^$/d' | awk -F"to=" '{print $2}' | tr -d "," | sort -u
<hr>
<font color="black"><b>
E-Mails enviados para o Servidor.com.br:</font></b> cat /var/log/maillog | grep "postfix/qmgr" | grep from | grep "queue active" | awk '{print $7}' | sort | uniq -c | sort | grep "email_aqui" | tr -d ","
<hr>
<font color="#990000"><b>
Endereço de remetente recusado - Domínios não encontrados:</b></font> cat /var/log/maillog | grep "Sender address rejected" | grep "Domain not found" | awk '{print "--> Origem: "$10,$20,$21}' | sort | uniq -c | grep "email_aqui"
<hr>
<font color="#990000"><b>
Endereço de remetente recusado - Endereço de E-Mail inválido:</b></font> cat /var/log/maillog | grep "Sender address rejected" | grep "Endereco de e-mail invalido" | awk '{print $21,$22}' | sort | uniq -c | grep "email_aqui"
<hr>
<font color="#990000"><b>
Endereço de remetente recusado - Endereços de Marketing não permitidos:</b></font> cat /var/log/maillog | grep "Sender address rejected" | grep "Enderecos de Marketing nao permitidos" | awk '{print $22,$23}' | uniq -c | grep "email_aqui"
<hr>
<font color="black"><b>
E-mails descartados:</b></font> grep "DISCARD" /var/log/maillog | sed 's/\(proto*\).*//' | awk -F"from=" '{print "_frmi_"$2"_frmf_"}' | sort -u | grep "email_aqui"
<hr>
<font color="black"><b>
Falhas de autenticação:</b></font> cat /var/log/maillog | grep "SASL authentication failure" | sort -u | grep "email_aqui"
<hr>
<font color="#990000"><b>
Impossível enviar:</b></font> grep "status=undeliverable" /var/log/maillog | grep "Recipient address rejected" | awk '{print $7,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33}' | sort -u | grep "email_aqui"
<hr>
<font color="#990000"><b>
Não enviados por Timed out:</b></font> egrep -w "status=undeliverable" /var/log/maillog | grep "Operation timed out" | awk '{print $7,$13,$14,$15,$16,$17,$18}' | sort -u | grep "email_aqui"
<hr>
<font color="#990000"><b>
Hostname sem FQDN:</b></font> grep "Helo command rejected: need fully-qualified hostname" /var/log/maillog | awk '{print $10}' | sort -u | tr -d ":"
<hr>
<font color="black"><b>
Hosts rejeitados:</b></font> grep "Client host rejected: Access denied " /var/log/maillog | awk -F"host" '{print $2}' | awk '{print $1}' | sort -u
<hr>
<font color="black"><b>
Não enviados por problemas de RELAY:</b></font> grep "Relay access denied" /var/log/maillog | grep "status=undeliverable" | awk '{print "_frmi_"$7,$8,$12,$13,$14"_frmf_"}' | sort -u
<hr>
<font color="black"><b>
Fila de E-mails (mailq):</font> mailq | sort -r | grep Request | awk '{print $5} ' | tee total.fila >& /dev/null ; mailq | sort -r | egrep -B `cat total.fila` -e "-Queue ID-" ; echo "Total: `cat total.fila`"
</b>
<hr>
<font color="blue">
E-Mails em Greylist:</font> cat /var/log/maillog | grep "[Gg]reylist" | awk '{print $1,$2,$3,$28,$29,$30,$31,"_frmi_"$38"_frmf_"}' | grep "email_aqui"
<hr>
<hr>
<font color="red">
RESET nas conexões SMTP:</font> grep -i rset /var/log/maillog | awk -F"from" '{print $2}' | sort | uniq -c | sort -r
<hr>
<hr>
<center><font color="black"><h2>Remetentes BLOQUEADOS em Listas <a href="rbl.html">RBL</a></h2></font></center>
<hr>
<hr>
<font color="red">
Lista Barracudacentral.org:</font> grep "blocked using b.barracudacentral.org" /var/log/maillog | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista bogusmx.rfc-ignorant.org:</font> grep "blocked using bogusmx.rfc-ignorant.org" /var/log/maillog | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista cbl.abuseat.org:</font> grep "blocked using cbl.abuseat.org" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista BL.SPAMCOP.NET:</font> grep "blocked using bl.spamcop.net" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista COMBINED.NJABL.ORG:</font> grep "blocked using combined.njabl.org" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista DNSBL.NJABL.ORG:</font> grep "blocked using dnsbl.njabl.org" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista ZEN.DNSBL:</font> grep "blocked using zen.dnsbl" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista DSN.RFC.IGNORANT.ORG:</font> grep "blocked using dsn.rfc.ignorant.org" /var/log/maillog | sort -u | grep "email_aqui"| awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista RDDB.DNSBL.NET.AU:</font> grep "blocked using rddb.dnsbl.net.au" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<font color="red">
Lista ENDN.DNSBL.NET.AU:</font> grep "blocked using endn.dnsbl.net.au" /var/log/maillog | sort -u | grep "email_aqui" | awk -F"from=" '{print "from: "$2}' | sed 's/to=.*//'
<hr>
<hr>
<center><font color="black" size="+2">Informações gerais do servidor - Resumo geral</font> <font size="-1"> <a href="http://servidor.com.br/php/relatorios/">Mais detalhes do relatório</a></font></center>
<hr>
<font color="green">
<hr>
Resumo de mensagens ENVIADAS PELO SERVIDOR e PARA o SERVIDOR:</font> cat /var/log/maillog | grep -e "status=sent" | grep -e "@*.usp.br" | awk '{print $7}' | sort | uniq -c | sort -r | head -20 | tr -d ","
<hr>
<font color="green">
<hr>
Resumo de mensagens DEFERIDAS:</font> cat /var/log/maillog | grep -e "status=deferred" | grep -e "@*.usp.br" | awk '{print $7}' | sort | uniq -c | sort | head -20 | tr -d ","
<font color="green">
<hr>
Resumo de mensagens ENTREGUES:</font> cat /var/log/maillog | grep -e "status=deliverable" | grep -e "@*.usp.br" | awk '{print $7}' | sort | uniq -c | sort | head -20 | tr -d ","
<font color="green">
<hr>
Resumo de mensagens NÃO ENTREGUES:</font> cat /var/log/maillog | grep -e "status=undeliverable" | grep -e "@*.usp.br" | awk '{print $7,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30}' | sort | uniq -c | sort | head -20
<font color="green">
<hr>
Resumo de mensagens DEVOLVIDAS:</font> cat /var/log/maillog | grep -e "status=bounced" | awk '{print $7,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28}' | sort | uniq -c | sort | head -20
<hr>
<font color="green">
E-Mails encaminhados para outos endereços:</font> egrep -w "relay" /var/log/maillog | awk '{print $8,"_frmi_"$7"_frmf_"}' | grep "orig_to" | sort -u | tr -d ","
<hr>
<font color="#990000"><b>
E-Mails enviados para o SERVIDOR (top 20):</b></font> cat /var/log/maillog | grep "postfix/qmgr" | grep from | grep "queue active" | awk '{print $7}' | sort | uniq -c | sort -r | head -20 | tr -d ","
<hr>
<font color="#990000"><b>
Endereço de remetente recusado - Endereço não verificado (top 20):</b></font> cat /var/log/maillog | grep "Sender address rejected" | grep "unverified address" | awk '{print $13}' | sort | uniq -c | sort -r | tr -d ":" | head -20
<hr>
<font color="#990000"><b>
Remetentes recusados e usuários inexistentes:</b></font> egrep -w "NOQUEUE\: reject\:" /var/log/maillog | grep "Recipient address rejected" | grep -v "Sender address rejected" | awk -F"from=" '{print $2}' | sed 's/\(proto*\).*//' | sort | awk -F"to=" '{print $1" ---> ","_frmi_"$2"_frmf_"}' | grep "servidor.com.br" | uniq -c | sort -r
<hr>
<font color="#990000"><b>
Destinatários inexistentes no SERVIDOR.COM.BR:</b></font> cat /var/log/maillog | grep "Recipient address rejected" | grep "User unknown in local recipient table" | awk '{print "_frmi_"$13"_frmf_"}' |grep "servidor.com.br" | sort -u | tr -d ":"
<hr>
É isso. Como há muitas ferramentas para esta função, esta pode ser útil para alguém.
A ideia inicial é mostrar para o usuário final a situação dos e-mails. E para o administrador do Postfix mostrar um pouco da situação do servidor.
O detalhe é a personalização dos scripts e adequação das necessidades. Esta é a filosofia do Software Livre, a qual nos faz progredir sempre.
Ali Faiez Taha é Eng. Eletricista e Analista de Sistemas e trabalha no Centro de Informática da USP de Ribeirão Preto, na Seção de Redes.