você está aqui: Home  → Arquivo de Mensagens Saiba mais sobre o curso Programação Shell Linux

Examinando os logs do Servidor de E-Mails

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:

principal.php

(download do script php)

<?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/

Script comandos.txt

<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.

Download dos arquivos utilizados

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.


Veja a relação completa dos artigos de Ali Faiez Taha