@ -29,12 +29,20 @@
# Uses the Email::Valid package to avoid sending notices
# Uses the Email::Valid package to avoid sending notices
# to obviously invalid addresses.
# to obviously invalid addresses.
#
#
# 2007-08-15 David Goodwin <david@palepurple.co.uk>
# Use the Perl Mail::Sendmail module for sending mail
# Check for headers that start with blank lines (patch from forum)
#
#
# Requirements:
# Requirements:
# You need to have the DBD::Pg perl-module installed.
# You need to have the DBD::Pg perl-module installed.
# You need to have the Mail::Sendmail module installed.
#
# On Fedora Core Linux, e.g., this entails installing the
# On Fedora Core Linux, e.g., this entails installing the
# libdbi-dbd-pgsql and perl-DBD-Pg-1.22-1 packages.
# libdbi-dbd-pgsql and perl-DBD-Pg-1.22-1 packages.
#
#
# On Debian based systems :
# libmail-sendmail-perl libdbd-pg-perl libemail-valid-perl libmime-perl
#
# Note: When you use this module, you may start seeing error messages
# Note: When you use this module, you may start seeing error messages
# like "Cannot insert a duplicate key into unique index
# like "Cannot insert a duplicate key into unique index
# vacation_notification_pkey" in your system logs. This is expected
# vacation_notification_pkey" in your system logs. This is expected
@ -51,6 +59,7 @@ use DBI;
use MIME::Words qw( :all ) ;
use MIME::Words qw( :all ) ;
use Email::Valid ;
use Email::Valid ;
use strict ;
use strict ;
use Mail::Sendmail ;
my $ db_host ; # leave alone
my $ db_host ; # leave alone
# ========== begin configuration ==========
# ========== begin configuration ==========
@ -63,11 +72,11 @@ my $db_type = 'Pg';
# $db_host = 'localhost'; # Uncomment (and adjust, if needed) your DB
# $db_host = 'localhost'; # Uncomment (and adjust, if needed) your DB
# host-name here, if you want to connect via
# host-name here, if you want to connect via
# a TCP socket
# a TCP socket
my $ db_user = 'vacation' ; # What DB-user to connect as
my $ db_user = 'vacation' ; # What DB-user to connect as
my $ db_pass = '' ; # What password (if any) to connect with
my $ db_pass = '' ; # What password (if any) to connect with
my $ db_name = 'postfix' ; # Name of database to use
my $ db_name = 'postfix' ; # Name of database to use
my $ sendmail = "/usr/sbin/sendmail" ;
my $ charset = 'ISO-8859-1' ; # Character set of vacation messages.
my $ charset = 'ISO-8859-1' ; # Character set of vacation messages.
@ -156,19 +165,23 @@ sub do_log {
}
}
sub do_mail {
sub do_mail {
# from, to, subject, body
my ( $ from , $ to , $ plainsubject , $ body ) = @ _ ;
my ( $ from , $ to , $ plainsubject , $ body ) = @ _ ;
my $ subject = encode_mimewords ( $ plainsubject ) ;
my $ subject = encode_mimewords ( $ plainsubject ) ;
open ( MAIL , "| $sendmail -t -f $from" ) or die ( "Unable to open sendmail" ) ;
my % mail ;
print MAIL "From: $from\n" ;
% mail = (
print MAIL "To: $to\n" ;
'To' = > $ to ,
print MAIL "Subject: $subject\n" ;
'From' = > $ from ,
print MAIL "MIME-Version: 1.0\n" ;
'Subject' = > $ subject ,
print MAIL "Content-Type: text/plain; charset=\"$charset\"\n" ;
'MIME-Version' = > '1.0' ,
print MAIL "Precedence: junk\n" ;
'Content-Type' = > "text/plain; charset=\"$charset\"" ,
print MAIL "X-Loop: Postfix Admin Virtual Vacation\n\n" ;
'Precedence' = > 'junk' ,
print MAIL "$body" ;
'X-Loop' = > 'Postfix Admin Virtual Vacation' ,
close ( MAIL ) ;
'Message' = > $ body
) ;
sendmail ( % mail ) or do_log ( $ Mail:: Sendmail:: error ) ;
do_debug ( "Mail::Sendmail said : " . $ Mail:: Sendmail:: log ) ;
}
}
sub panic {
sub panic {
@ -261,7 +274,9 @@ sub send_vacation_email {
my @ row = $ stm - > fetchrow_array ;
my @ row = $ stm - > fetchrow_array ;
if ( already_notified ( $ email , $ orig_from ) ) { return ; }
if ( already_notified ( $ email , $ orig_from ) ) { return ; }
do_debug ( "[SEND RESPONSE] for $orig_messageid:\n" , "FROM: $email (orig_to: $orig_to)\n" , "TO: $orig_from\n" , "SUBJECT: $orig_subject\n" , "VACATION SUBJECT: $row[0]\n" , "VACATION BODY: $row[1]\n" ) ;
do_debug ( "[SEND RESPONSE] for $orig_messageid:\n" , "FROM: $email (orig_to: $orig_to)\n" , "TO: $orig_from\n" , "SUBJECT: $orig_subject\n" , "VACATION SUBJECT: $row[0]\n" , "VACATION BODY: $row[1]\n" ) ;
do_mail ( $ orig_to , $ orig_from , $ row [ 0 ] , $ row [ 1 ] ) ;
# do_mail(from, to, subject, body);
do_mail ( $ email , $ orig_from , $ row [ 0 ] . " (Re: $orig_subject)" , $ row [ 1 ] ) ;
do_log ( $ orig_messageid , $ orig_to , $ orig_from , $ orig_subject ) ;
do_log ( $ orig_messageid , $ orig_to , $ orig_from , $ orig_subject ) ;
}
}
@ -269,18 +284,19 @@ sub send_vacation_email {
########################### main #################################
########################### main #################################
my ( $ from , $ to , $ cc , $ subject , $ messageid );
my ( $ from , $ to , $ cc , $ subject , $ messageid , $ lastheader );
$ subject = '' ;
$ subject = '' ;
# Take headers apart
# Take headers apart
while ( <STDIN> ) {
while ( <STDIN> ) {
last if ( /^$/ ) ;
last if ( /^$/ ) ;
if ( /^from:\s+(.*)\n$/i ) { $ from = $ 1 ; }
if ( /^\s+(.*)/ and $ lastheader ) { $$ lastheader . = " $1" ; }
if ( /^to:\s+(.*)\n$/i ) { $ to = $ 1 ; }
if ( /^from:\s+(.*)\n$/i ) { $ from = $ 1 ; $ lastheader = \ $ from ; }
if ( /^cc:\s+(.*)\n$/i ) { $ cc = $ 1 ; }
if ( /^to:\s+(.*)\n$/i ) { $ to = $ 1 ; $ lastheader = \ $ to ; }
if ( /^subject:\s+(.*)\n$/i ) { $ subject = $ 1 ; }
if ( /^cc:\s+(.*)\n$/i ) { $ cc = $ 1 ; $ lastheader = \ $ cc ; }
if ( /^message-id:\s+(.*)\n$/i ) { $ messageid = $ 1 ; }
if ( /^subject:\s+(.*)\n$/i ) { $ subject = $ 1 ; $ lastheader = \ $ subject ; }
if ( /^message-id:\s+(.*)\n$/i ) { $ messageid = $ 1 ; $ lastheader = \ $ messageid ; }
if ( /^precedence:\s+(bulk|list|junk)/i ) { exit ( 0 ) ; }
if ( /^precedence:\s+(bulk|list|junk)/i ) { exit ( 0 ) ; }
if ( /^x-loop:\s+postfix\ admin\ virtual\ vacation/i ) { exit ( 0 ) ; }
if ( /^x-loop:\s+postfix\ admin\ virtual\ vacation/i ) { exit ( 0 ) ; }
}
}
@ -290,7 +306,7 @@ if (!$from || !$to || !$messageid) { exit (0); }
$ from = lc ( $ from ) ;
$ from = lc ( $ from ) ;
if ( ! Email::Valid - > address ( $ from , - mxcheck = > 1 ) ) { exit ( 0 ) ; }
if ( ! Email::Valid - > address ( $ from , - mxcheck = > 1 ) ) { do_debug ( "" , "" , "" , "" , "" , "Invalid from email address: $from; exiting." ) ; exit ( 0 ) ; }
# Check if it's an obvious sender, exit
# Check if it's an obvious sender, exit
if ( $ from =~ /([\w\-.%]+\@[\w.-]+)/ ) { $ from = $ 1 ; }
if ( $ from =~ /([\w\-.%]+\@[\w.-]+)/ ) { $ from = $ 1 ; }
@ -314,7 +330,9 @@ for (@strip_to_array) {
# Search for email address which has vacation
# Search for email address which has vacation
for ( @ search_array ) {
for ( @ search_array ) {
my ( $ rv , $ email ) = find_real_address ( $ _ ) ;
/([\w\-.%]+\@[\w.-]+)/ or next ;
my $ addr = $ 1 ;
my ( $ rv , $ email ) = find_real_address ( $ addr ) ;
if ( $ rv == 1 ) {
if ( $ rv == 1 ) {
do_debug ( "[FOUND VACATION]: " , $ messageid , $ from , $ to , $ email , $ subject ) ;
do_debug ( "[FOUND VACATION]: " , $ messageid , $ from , $ to , $ email , $ subject ) ;
send_vacation_email ( $ email , $ subject , $ from , $ to , $ messageid ) ;
send_vacation_email ( $ email , $ subject , $ from , $ to , $ messageid ) ;