vacation.pl: plenty of refactoring; I think this addresses all hte points at https://sourceforge.net/forum/message.php?msg_id=5205584

git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@453 a1433add-5e2c-0410-b055-b7f2511e0802
postfixadmin-2.3
David Goodwin 16 years ago
parent 21ff7c17c0
commit 320ecddbbf

@ -3,7 +3,7 @@ X-Original-To: david@example.org
Delivered-To: david@example.org
Received: by mail.palepurple.co.uk (Postfix, from userid 33)
id 1942F894CF9; Fri, 1 Aug 2008 11:23:45 +0100 (BST)
To: <david@example.org>
To: "" <david@example.org>
Subject: New Phone call - annotate it!
X-PHP-Script: admin.palepurple.co.uk/contacts/dispatch.php for 78.105.97.55
From: "asterisk@example.org" <asterisk@example.org>

@ -22,7 +22,8 @@ Received: by irc.palepurple.co.uk (Postfix, from userid 1000)
id 8869450146; Tue, 5 Aug 2008 20:15:50 +0100 (BST)
Date: Tue, 5 Aug 2008 20:15:50 +0100
From: David Goodwin <david1@example.org>
To: david@example.org
To: "DG" <david@example.org>, "Fred@Work" <fred@example.org>, "Barney Rubble"
<barney@example.org>, "Rover Dog" <rover@example.org>, roger@example.org
Subject: test email
Message-ID: <20080805191549.GA27905@codepoets.co.uk>
MIME-Version: 1.0

@ -18,25 +18,32 @@ echo "DELETE FROM vacation WHERE email = 'david@example.org'" | psql
# First time around, there should be no vacation record for david@example.org, so these should all not cause mail to be sent.
# some will trip up spam/mailing list protection etc though
echo
echo "NONE OF THESE SHOULD RESULT IN MAIL BEING SENT"
echo
cat mailing-list.txt | perl ../vacation.pl -t yes -f fw-general-return-20540-david=example.org@lists.zend.com -- david@example.org
cat test-email.txt | perl ../vacation.pl -t yes -f david1@example.org -- david@example.org
cat spam.txt | perl ../vacation.pl -t yes -f mary@ccr.org -- david@example.org
cat asterisk-email.txt | perl ../vacation.pl -t yes -f www-data@palepurple.net -- david@example.org
cat facebook.txt | perl ../vacation.pl -t yes -f notification+meynbxsa@facebookmail.com -- david@example.org
cat mail-myself.txt | perl ../vacation.pl -t yes -f david@example.org -- david@example.org
echo "INSERT INTO vacation (email, subject, body, created, active, domain) VALUES ('david@example.org', 'I am on holiday', 'Yeah, that is right', NOW(), true, 'example.org')" | psql
echo
echo "VACATION TURNED ON "
echo
echo "Still ignore mailing list"
cat mailing-list.txt | perl ../vacation.pl -t yes -f fw-general-return-20540-david=example.org@lists.zend.com -- david@example.org
echo "* Should send vacation message for this"
echo " * Should send vacation message for this *"
cat test-email.txt | perl ../vacation.pl -t yes -f david1@example.org -- david@example.org
echo "* Spam - no vacation message for this"
echo " * Spam - no vacation message for this"
cat spam.txt | perl ../vacation.pl -t yes -f mary@xxccr.org -- david@example.org
echo "* OK - should send vacation message for this"
echo " * OK - should send vacation message for this"
cat asterisk-email.txt | perl ../vacation.pl -t yes -f www-data@palepurple.net -- david@example.org
echo "* Facebook - should not send vacation message for"
echo " * Facebook - should not send vacation message for"
cat facebook.txt | perl ../vacation.pl -t yes -f notification+meynbxsa@facebookmail.com -- david@example.org
echo " * Mailing myself - should not send vacation message"
cat mail-myself.txt | perl ../vacation.pl -t yes -f david@example.org -- david@example.org
echo
echo

@ -99,8 +99,8 @@ my $db_type = 'Pg';
my $db_host = '';
# connection details
my $db_username = 'your_username';
my $db_password = 'your_password';
my $db_username = 'dg';
my $db_password = 'gingerdog';
my $db_name = 'postfix';
# smtp server used to send vacation e-mails
@ -139,16 +139,18 @@ use Mail::Sendmail;
use Getopt::Std;
use Log::Log4perl qw(get_logger :levels);
my ($from, $to, $cc, ,$bcc , $subject, $messageid, $lastheader, $smtp_sender, $smtp_recipient, %opts, $sndrhdr, $spam, $test_mode, $logger);
my ($from, $to, $cc, $replyto , $subject, $messageid, $lastheader, $smtp_sender, $smtp_recipient, %opts, $spam, $test_mode, $logger);
$subject='';
# Setup a logger...
#
getopts('f:t:', \%opts) or die "Usage: $0 [-t yes] [-f sender] [-- [recipient]]\n -t for testing only\n";
getopts('f:t:', \%opts) or die "Usage: $0 [-t yes] -f sender -- recipient\n -t for testing only\n";
$opts{f} and $smtp_sender = $opts{f};
$test_mode = 0;
$opts{t} and $test_mode = 1;
$smtp_recipient = shift || $smtp_recipient || $ENV{"USER"} || "";
my $log_layout = Log::Log4perl::Layout::PatternLayout->new("%d %p> %F:%L %M - %m%n");
@ -388,15 +390,24 @@ sub send_vacation_email {
}
}
# Remove textual stuff from a (list of) email address(es)
# e.g. convert: "aardvark" <a@b.com>, "Danger Mouse" <c@d.com>, e@f.com to
# a@b.com, c@d.com, e@f.com
sub strip_address {
my ($arg) = @_;
if(!$arg) {
return '';
}
if($arg =~ /([\w\-.%]+\@[\w.-]+)/) {
return lc($1);
my @ok;
$logger = get_logger();
for (split(/,\s*/, lc($arg))) {
my $temp = Email::Valid->address($_);
if($temp) {
push(@ok, $temp);
}
}
return '';
my $result = join(", ", @ok);
return $result;
}
sub panic_prepare {
@ -412,34 +423,52 @@ sub panic_execute {
$logger->error("Could not execute sql statement - '$arg' with parameters '$param'");
exit(0);
}
# Make sure the email wasn't sent by someone who could be a mailing list etc; if it was,
# then we abort after appropriate logging.
sub check_and_clean_from_address {
my ($address) = @_;
my $logger = get_logger();
if($address =~ /^(noreply|postmaster|mailer-daemon|listserv|majordomo|owner-|request-|bounces-)/i ||
$address =~ /-(owner|request|bounces)\@/i ) {
$logger->debug("sender $address contains $1 - will not send vacation message");
exit(0);
}
$address = strip_address($address);
if($address eq "") {
$logger->error("Address $address is not valid; exiting");
exit(0);
}
#$logger->debug("Address cleaned up to $address");
return $address;
}
########################### main #################################
# Take headers apart
#
$cc = '';
$replyto = '';
while (<STDIN>) {
last if (/^$/);
if (/^\s+(.*)/ and $lastheader) { $$lastheader .= " $1"; }
elsif (/^Return-Path:\s+(.*)\n$/i) { $smtp_sender = $1; $lastheader = \$smtp_sender; }
elsif (/^Delivered-To:\s+(.*)\n$/i) { $smtp_recipient = $1; $lastheader = \$smtp_recipient; }
elsif (/^from:\s+(.*)\n$/i) { $from = $1; $lastheader = \$from; }
elsif (/^to:\s+(.*)\n$/i) { $to = $1; $lastheader = \$to; }
elsif (/^cc:\s+(.*)\n$/i) { $cc = $1; $lastheader = \$cc; }
elsif (/^bcc:\s+(.*)\n$/i) { $bcc = $1; $lastheader = \$bcc; }
elsif (/^subject:\s+(.*)\n$/i) { $subject = $1; $lastheader = \$subject; }
elsif (/^message-id:\s+(.*)\n$/i) { $messageid = $1; $lastheader = \$messageid; }
if (/^\s+(.*)/ and $lastheader) { $$lastheader .= " $1"; next; }
elsif (/^from:\s*(.*)\s*\n$/i) { $from = $1; $lastheader = \$from; }
elsif (/^to:\s*(.*)\s*\n$/i) { $to = $1; $lastheader = \$to; }
elsif (/^cc:\s*(.*)\s*\n$/i) { $cc = $1; $lastheader = \$cc; }
elsif (/^Reply-to:\s*(.*)\s*\n$/i) { $replyto = $1; $lastheader = \$replyto; }
elsif (/^subject:\s*(.*)\s*\n$/i) { $subject = $1; $lastheader = \$subject; }
elsif (/^message-id:\s*(.*)\s*\n$/i) { $messageid = $1; $lastheader = \$messageid; }
elsif (/^x-spam-(flag|status):\s+yes/i) { $logger->debug("x-spam-$1: yes found; exiting"); exit (0); }
elsif (/^x-facebook-notify:/i) { $logger->debug('Mail from facebook, ignoring'); exit(0); }
elsif (/^precedence:\s+(bulk|list|junk)/i) { $logger->debug("precedence: $1 found; exiting"); exit (0); }
elsif (/^x-loop:\s+postfix\ admin\ virtual\ vacation/i) { $logger->debug("x-loop: postfix admin virtual vacation found; exiting"); exit (0); }
elsif (/^Auto-Submitted:\s+no/i) { next; }
elsif (/^Auto-Submitted:\s*no\s*/i) { next; }
elsif (/^Auto-Submitted:/i) { $logger->debug("Auto-Submitted: something found; exiting"); exit (0); }
elsif (/^List-(Id|Post):/i) { $logger->debug("List-$1: found; exiting"); exit (0); }
elsif (/^Sender:\s+(.*)/i) { $sndrhdr = $1; $lastheader = \$sndrhdr; }
else {$lastheader = "" ; }
}
$smtp_recipient = shift || $smtp_recipient || $ENV{"USER"} || "";
# If either From: or To: are not set, exit
if(!$from || !$to || !$messageid || !$smtp_sender || !$smtp_recipient) {
@ -447,15 +476,16 @@ if(!$from || !$to || !$messageid || !$smtp_sender || !$smtp_recipient) {
exit(0);
}
if($smtp_sender =~ /^(mailer-daemon|listserv|majordomo|owner-|request-|bounces-)/i ||
$smtp_sender =~ /-(owner|request|bounces)\@/i ) {
$logger->debug("sender $smtp_sender contains $1 - will not send vacation message");
exit(0);
$to = strip_address($to);
$from = lc ($from);
$from = check_and_clean_from_address($from);
if($replyto ne "") {
# if reply-to is invalid, or looks like a mailing list, then we probably don't want to send a reply.
$replyto = check_and_clean_from_address($replyto);
}
$smtp_sender = check_and_clean_from_address($smtp_sender);
$smtp_recipient = check_and_clean_from_address($smtp_recipient);
$smtp_sender = strip_address($smtp_sender);
$smtp_recipient = strip_address($smtp_recipient);
$sndrhdr = strip_address($sndrhdr);
if ($smtp_sender eq $smtp_recipient) {
$logger->debug("smtp sender $smtp_sender and recipient $smtp_recipient are the same; aborting");
@ -463,39 +493,28 @@ if ($smtp_sender eq $smtp_recipient) {
}
my $recipfound = 0;
for (split(/,\s*/, lc($to)), split(/,\s*/, lc($cc)), split(/,\s*/, lc($bcc))) {
for (split(/,\s*/, lc($to)), split(/,\s*/, lc($cc))) {
my $destinatario = strip_address($_);
if ($sndrhdr eq $destinatario) {
$logger->debug("sender header $sndrhdr contains recipient $destinatario (mailing myself?)");
if ($smtp_sender eq $destinatario) {
$logger->debug("sender header $smtp_sender contains recipient $destinatario (mailing myself?)");
exit(0);
}
if ($smtp_recipient eq $destinatario) { $recipfound++; }
}
if (!$recipfound) {
$logger->debug("smtp envelope recipient $smtp_recipient not found in the header recipients (therefore they were bcc'ed, so won't send vacation message)");
$logger->debug("smtp envelope recipient $smtp_recipient not found in the header recipients ($to & $cc) (therefore they were bcc'ed, so won't send vacation message)");
exit (0);
}
$from = lc ($from);
if (!Email::Valid->address($from,-mxcheck => 1)) { $logger->debug("Invalid from email address: $from; exiting."); exit(0); }
if (!Email::Valid->address($smtp_sender,-mxcheck => 1)) { $logger->debug("Invalid sender email address: $smtp_sender; exiting."); exit(0); }
if ($from =~ /([\w\-.%]+\@[\w.-]+)/) { $from = $1; }
# Does the $from address look like a mailing list etc?
if ($from eq "" ||
$from =~ /^(owner-|-(?:request|owner)\@|^(?:mailer-daemon|postmaster)\@)/i) {
$logger->debug("from $from contains $1"); exit (0);
}
my ($rv, $email) = find_real_address($smtp_recipient);
$logger->debug("find_email_address gave: rv:$rv, email:$email");
if ($rv == 1) {
$logger->debug("Attempting to send vacation response for: $messageid to: $smtp_sender, $smtp_recipient, $email (test_mode = $test_mode)");
send_vacation_email($email, $smtp_sender, $smtp_recipient, $messageid, $test_mode);
}
else {
$logger->debug("SMTP recipient $smtp_recipient which resolves to $email does not have an active vacation");
$logger->debug("SMTP recipient $smtp_recipient which resolves to $email does not have an active vacation (rv: $rv, email: $email)");
}
0;

Loading…
Cancel
Save