Today i was asked by several people what does this bounce email means...
So i came up with this idea, this is a small script which goes in a .qmail-bps file, (bps stands for bounce parse system), so when an user is unsure about a bounce they just create a new message and send it to bps@mydomain.com and includes as many bounces messages as attachments and in a few seconds they got an answer of their meaning, that means more time for me to have tea in the morning :)
Here you go, enjoy and i will enjoy my tea
#!/usr/bin/perl
use strict;
use warnings;
use Email::MIME;
use File::Basename;
use LWP::Simple;
use Mail::Header;
use MIME::Parser;
use Data::Dumper;
use Net::SMTP_auth;
use Time::HiRes qw(time);
use Digest::MD5 qw(md5_hex);
use Mail::DeliveryStatus::BounceParser;
my $outDir = md5_hex(time());
my $tmpMail = '/tmp/mails/' . $outDir . '/';
mkdir($tmpMail);
sub sendMail{
my $to = shift;
my $body = shift;
my $smtp = Net::SMTP_auth->new('YOURSERVER', 'Debug' => '0');
$smtp->auth('LOGIN', 'SMTPUSER', 'PASSWORD') or die q(Cannot auth);
$smtp->mail('YOUREMAIL');
$smtp->to($to);
$smtp->data();
$smtp->datasend("Subject: Bounces\n");
$smtp->datasend('From: Bounce Parser System ' . "\n");
$smtp->datasend('To:' . $to . "\n");
$smtp->datasend("\n");
$smtp->datasend($body);
$smtp->dataend();
$smtp->quit;
}
my $finalMessage = "";
my $mail;
while (<>){
$mail .= $_;
}
my $emailArr = ();
@{$emailArr} = split /\n/, $mail;
my $header = new Mail::Header $emailArr , Modify => 0;
my $from = $header->get('From');
my $em = Email::MIME->new($mail);
for ( my @parts = $em->parts ) {
my $filename = basename( $_->filename || '' );
my $basefilename = $filename || 'UNNAMED';
my $cnt = 0;
while ( -e $tmpMail . "/$filename" ) {
my ( $d, $m, $y ) = (localtime)[ 3 .. 5 ];
$filename = sprintf( "%s_%04d%02d%02d_%04d", $basefilename, $y + 1900, $m + 1, $d, ++$cnt );
}
open my $fh, ">", $tmpMail . "$filename";
binmode $fh;
print $fh $_->body;
}
chdir($tmpMail);
opendir(DIR, $tmpMail) || die "can't opendir " . $tmpMail . " $!";
my @filelist = grep { /\.[eml]/ && -f "$_" } readdir(DIR);
foreach (@filelist){
open (MSG, $tmpMail .$_ ) or die ($!);
my $status = {};
my $message = join "", ;
close (MSG);
my $bounce = eval { Mail::DeliveryStatus::BounceParser->new($message ) };
if ($@) {
$finalMessage .= qq(couldn't parse.);
next;
}
next unless $bounce->is_bounce ;
my @report = $bounce->reports; # Mail::Header objects
if ( ! scalar(@report) ) {
next;
}
$status->{'rcpt'} = $report[0]->get('email');
$status->{'posible_cause'} = $report[0]->get('std_reason');
if ( ! $report[0]->get('reason') ){
if ( $report[0]->get('raw') =~ m/(http:.+)/ ) {
my $url = get($1);
$url =~ s/\n//gi;
$url =~ m/(<p><b>EXPLANATION:<\/b><\/p>(.+)<p><b>SOLUTION:<\/b><\/p>)/;
my $error = $2;
$error =~ s/<\/*p>//gi;
$error =~ s/\s{2,}/ /gi;
$status->{'reason'} = $error;
} elsif ($report[0]->get('raw') =~ m/Blacklisted/i) {
$status->{'reason'} = "We're blacklisted";
} elsif ($report[0]->get('raw') =~ m/establish an SMTP/i) {
$status->{'reason'} = "Our server couldn't open a connection to the remote one, maybe remote server down or incorrect";
} else {
$status->{'reason'} = 'Bad Email address or server reject email';
}
} else {
$status->{'reason'} = $report[0]->get('reason');
}
$finalMessage .= $_ . qq(\n) . "Recipent: " . $status->{'rcpt'} . qq(\nReason: ) . $status->{'reason'} . qq(\n\n\n);
}
&sendMail($from,$finalMessage);
unlink <*.*>;
chdir('/tmp');
rmdir($tmpMail);