sisimai / p5-sisimai

Mail Analyzing Interface for email bounce: A Perl module to parse RFC5322 bounce mails and generating structured data as JSON from parsed results. Formerly known as bounceHammer 4: an error mail analyzer.
https://libsisimai.org
BSD 2-Clause "Simplified" License
78 stars 26 forks source link

Question: Best way to report missing responses #387

Closed jcbf closed 4 years ago

jcbf commented 4 years ago

Following the question on #385 , I'm doing an analysis of some responses from a Postfix instance:

grep status=bounced /var/log/mail.log   | perl -MSisimai -lne '
next unless  /status=bounced \((.+)\)$/; 
$a= Sisimai->match($1); 
print $a eq "undefined" ? $1 : $a ;
'  | sort -u`

I'm having some responses that assumed to be already covered, like

host feedback-smtp.eu-west-1.amazonses.com[18.200.42.95] said: 550 Mailbox does not exist! (in reply to RCPT TO command)
host feedback-smtp.eu-west-1.amazonses.com[34.250.195.198] said: 550 Mailbox does not exist! (in reply to RCPT TO command)
host feedback-smtp.us-east-1.amazonses.com[18.235.76.96] said: 554 DSN is not RFC 3464 compliant. MSGID: (rB4TeBIUGDyQyRNGoSK0-1): The DSN MUST be addressed (in both the message header and the transport envelope) to the return address from the transport envelope which accompanied the original message for which the DSN was generated. https://tools.ietf.org/html/rfc3464 (in reply to end of DATA command)
host mta5.am0.yahoodns.net[67.195.228.110] said: 554 delivery error: dd Not a valid recipient - atlas318.free.mail.gq1.yahoo.com (in reply to end of DATA command)
host mta5.am0.yahoodns.net[67.195.228.94] said: 554 delivery error: dd Not a valid recipient - atlas301.free.mail.gq1.yahoo.com (in reply to end of DATA command)
host mta5.am0.yahoodns.net[98.136.96.74] said: 554 delivery error: dd Requested mail action aborted - mta4201.mail.ne1.yahoo.com (in reply to end of DATA command)
host ferrovial365.mail.protection.outlook.com[104.47.4.36] said: 550 5.7.51 TenantInboundAttribution; There is a partner connector configured that matched the message's recipient domain. The connector had either the RestrictDomainsToIPAddresses or RestrictDomainsToCertificate set [AM5EUR02FT042.eop-EUR02.prod.protection.outlook.com] (in reply to RCPT TO command)
host xxx-xxx.mail.protection.outlook.com[104.47.0.36] said: 554 5.4.11 Agent generated message depth exceeded [AM6PR02MB4246.eurprd02.prod.outlook.com] [AM6PR10CA0042.EURPRD10.PROD.OUTLOOK.COM] [HE1EUR01FT033.eop-EUR01.prod.protection.outlook.com] (in reply to end of DATA command)
host email-teams-microsoft-com.mail.protection.outlook.com[104.47.59.138] said: 554 5.2.122 The recipient has exceeded their limit for the number of messages they can receive per hour. For more information go to http://go.microsoft.com/fwlink/?LinkId=526653. (XTHRT71732254) [DM6NAM12FT061.eop-nam12.prod.protection.outlook.com] (in reply to end of DATA command)
host au-smtp-inbound-2.mimecast.com[124.47.150.222] said: 550 Envelope blocked - User Entry - https://community.mimecast.com/docs/DOC-1369#550 [xxxxxxxxxxxxxx.au48] (in reply to RCPT TO command)

My questions are:

I'm writing a milter to parse the full bounce message but this is only done to have an idea on how may messages will be detected and classified.

Regards

azumakuniyuki commented 4 years ago

My questions are:

The code I use should have identified these bounces? Is there any simple code that can?

The most simple and reliable way is to read the entire bounce message at your milter code because each response message in a maillog is not enough to parse and detect a bounce reason.

Sisimai calls Sisimai::Reason::* and Sisimai::Rhost::* modules in addition to Sisimai::Lhost::* modules to detect a bounce reason as shown in the figure: "Sisimai Architecture" at the bottom of https://libsisimai.org/en/docs/ .

Another way? The following dirty hack code might help you, perhaps...

#!/usr/bin/env perl
use strict;
use warnings;
use Sisimai;
use Sisimai::Data;
use Sisimai::Rhost;
use Sisimai::SMTP::Error;

while(<>) {
    # For only a maillog of Postfix
    my $logmessage = $1 if $_ =~ /status=bounced (.+)$/ || next;
    my $remotehost = $1 if $_ =~ /[(]host[ ]([0-9A-Za-z.-]+?)\[/ || next;
    my $diagnostic = $1 if $_ =~ /[ ]said:[ ](.+)$/ || next;
    my $logcommand = $1 if $_ =~ /[ ](MAIL|RCPT|DATA)[ ]/;
    my $parameters = {
        'reason'         => '',
        'diagnosticcode' => $diagnostic,
        'deliverystatus' => Sisimai::SMTP::Status->find($logmessage),
        'replycode'      => Sisimai::SMTP::Reply->find($logmessage),
        'rhost'          => $remotehost,
        'smtpcommand'    => $logcommand,
    };
    my $dataobject = bless($parameters, 'Sisimai::Data');
    my $reasonname = Sisimai::Rhost->get($dataobject) || Sisimai->match($logmessage);

    $dataobject->{'reason'} = $reasonname || '';
    printf("%s\n", $dataobject->reason);
}
$ cat /var/log/maillog | perl ./script-above.pl`

Regards,

jcbf commented 4 years ago

That's perfect. Thanks!