|
|
|
@ -1,11 +1,6 @@
|
|
|
|
|
#!/usr/bin/perl -X
|
|
|
|
|
# Note - 2017/02/08 DG :
|
|
|
|
|
# Yes - I know -X (^) is not ideal.
|
|
|
|
|
# Patches are welcome to remove the dependency on Mail::Sender.
|
|
|
|
|
# Until then, we need -X to stop it failing with warnings like
|
|
|
|
|
# defined(@array) is deprecated at .../perl5/Mail/Sender.pm line 318.
|
|
|
|
|
#!/usr/bin/perl
|
|
|
|
|
#
|
|
|
|
|
# Virtual Vacation 4.0
|
|
|
|
|
# Virtual Vacation 4.1
|
|
|
|
|
#
|
|
|
|
|
# $Revision$
|
|
|
|
|
# Originally by Mischa Peters <mischa at high5 dot net>
|
|
|
|
@ -86,25 +81,33 @@
|
|
|
|
|
# Add capability to include the subject of the original mail in the subject of the vacation message.
|
|
|
|
|
# A good vacation subject could be: 'Re: $SUBJECT'
|
|
|
|
|
# Also corrected log entry about "Already informed ..." to show the $orig_from, not $email
|
|
|
|
|
#
|
|
|
|
|
# 2017-07-14 Thomas Kempf <tkempf@hueper.de>
|
|
|
|
|
# Replacing deprecated Mail::Sender by Email::Sender
|
|
|
|
|
# Add configuration parameter $no_vacation_pattern in order to exlude specific alias-recipients from
|
|
|
|
|
# sending vacation mails, even if one or multiple of the recipients the alias points to has vacation
|
|
|
|
|
# currently active.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
# Requirements - the following perl modules are required:
|
|
|
|
|
# DBD::Pg or DBD::mysql
|
|
|
|
|
# Mail::Sender, Email::Valid MIME::Charset, Log::Log4perl, Log::Dispatch, MIME::EncWords and GetOpt::Std
|
|
|
|
|
# EMail::Sender,Email::Simple,Email::Valid,Try::Tiny,MIME::Charset, MIME::EncWords, Log::Log4perl, Log::Dispatch, and GetOpt::Std
|
|
|
|
|
#
|
|
|
|
|
# You may install these via CPAN, or through your package tool.
|
|
|
|
|
# CPAN: 'perl -MCPAN -e shell', then 'install Module::Whatever'
|
|
|
|
|
#
|
|
|
|
|
# On Debian based systems :
|
|
|
|
|
# libmail-sender-perl
|
|
|
|
|
# libdbd-pg-perl
|
|
|
|
|
# libemail-sender-perl
|
|
|
|
|
# libemail-simple-perl
|
|
|
|
|
# libemail-valid-perl
|
|
|
|
|
# libtry-tiny-perl
|
|
|
|
|
# libdbd-pg-perl
|
|
|
|
|
# libmime-perl
|
|
|
|
|
# liblog-log4perl-perl
|
|
|
|
|
# liblog-dispatch-perl
|
|
|
|
|
# libgetopt-argvfile-perl
|
|
|
|
|
# libmime-charset-perl (currently in testing, see instructions below)
|
|
|
|
|
# libmime-encwords-perl (currently in testing, see instructions below)
|
|
|
|
|
# libmime-charset-perl
|
|
|
|
|
# libmime-encwords-perl
|
|
|
|
|
#
|
|
|
|
|
# Note: When you use this module, you may start seeing error messages
|
|
|
|
|
# like "Cannot insert a duplicate key into unique index
|
|
|
|
@ -118,16 +121,18 @@
|
|
|
|
|
# One such package collection (for Linux) is:
|
|
|
|
|
# http://dag.wieers.com/home-made/apt/packages.php
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
use utf8;
|
|
|
|
|
use DBI;
|
|
|
|
|
use MIME::Base64 qw(encode_base64);
|
|
|
|
|
use Encode qw(encode decode);
|
|
|
|
|
use Encode qw(decode);
|
|
|
|
|
use MIME::EncWords qw(:all);
|
|
|
|
|
use Email::Valid;
|
|
|
|
|
use strict;
|
|
|
|
|
use Mail::Sender;
|
|
|
|
|
use Getopt::Std;
|
|
|
|
|
use Email::Sender::Simple qw(sendmail);
|
|
|
|
|
use Email::Sender::Transport::SMTP;
|
|
|
|
|
use Email::Simple;
|
|
|
|
|
use Email::Simple::Creator;
|
|
|
|
|
use Try::Tiny;
|
|
|
|
|
use Log::Log4perl qw(get_logger :levels);
|
|
|
|
|
use File::Basename;
|
|
|
|
|
|
|
|
|
@ -153,21 +158,29 @@ our $vacation_domain = 'autoreply.example.org';
|
|
|
|
|
|
|
|
|
|
# smtp server used to send vacation e-mails
|
|
|
|
|
our $smtp_server = 'localhost';
|
|
|
|
|
# port to connect to; defaults to 25 for non-SSL, 465 for 'ssl', 587 for 'starttls'
|
|
|
|
|
our $smtp_server_port = 25;
|
|
|
|
|
|
|
|
|
|
# this is the helo we [the vacation script] use on connection; you may need to change this to your hostname or something,
|
|
|
|
|
# depending upon what smtp helo restrictions you have in place within Postfix.
|
|
|
|
|
our $smtp_client = 'localhost';
|
|
|
|
|
|
|
|
|
|
# SMTP authentication protocol used for sending.
|
|
|
|
|
# Can be 'PLAIN', 'LOGIN', 'CRAM-MD5' or 'NTLM'
|
|
|
|
|
# see "perldoc Mail::Sender" (search for "auth") for more options and details
|
|
|
|
|
# Leave it blank if you don't use authentication
|
|
|
|
|
our $smtp_auth = undef;
|
|
|
|
|
# username used to login to the server
|
|
|
|
|
our $smtp_authid = 'someuser';
|
|
|
|
|
# password used to login to the server
|
|
|
|
|
our $smtp_authpwd = 'somepass';
|
|
|
|
|
# send mail encrypted or plaintext
|
|
|
|
|
# if 'starttls', use STARTTLS; if 'ssl' (or 1), connect securely; otherwise, no security
|
|
|
|
|
our $smtp_ssl = 'starttls';
|
|
|
|
|
|
|
|
|
|
# passed to Net::SMTP constructor for 'ssl' connections or to starttls for 'starttls' connections; should contain extra options for IO::Socket::SSL
|
|
|
|
|
our $ssl_options = {
|
|
|
|
|
SSL_verifycn_name => $smtp_server
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# maximum time in secs to wait for server; default is 120
|
|
|
|
|
our $smtp_timeout = '120';
|
|
|
|
|
|
|
|
|
|
# sasl_username: the username to use for auth; optional
|
|
|
|
|
our $smtp_authid = '';
|
|
|
|
|
# sasl_password: the password to use for auth; required if username is provided
|
|
|
|
|
our $smtp_authpwd = '';
|
|
|
|
|
|
|
|
|
|
# This specifies the mail 'from' name which is shown to recipients of vacation replies.
|
|
|
|
|
# If you leave it empty, the vacation mail will contain:
|
|
|
|
@ -176,9 +189,6 @@ our $smtp_authpwd = 'somepass';
|
|
|
|
|
# From: Some Friendly Name <original@recipient.domain>
|
|
|
|
|
our $friendly_from = '';
|
|
|
|
|
|
|
|
|
|
# use TLS for the SMTP connection?
|
|
|
|
|
# while in general this would be a good idea, TLS with Mail::Sender 0.8.22 is buggy - https://rt.cpan.org/Public/Bug/Display.html?id=85438
|
|
|
|
|
our $smtp_tls_allowed = 0;
|
|
|
|
|
|
|
|
|
|
# Set to 1 to enable logging to syslog.
|
|
|
|
|
our $syslog = 0;
|
|
|
|
@ -207,6 +217,15 @@ our $interval = 0;
|
|
|
|
|
our $custom_noreply_pattern = 0;
|
|
|
|
|
our $noreply_pattern = 'bounce|do-not-reply|facebook|linkedin|list-|myspace|twitter';
|
|
|
|
|
|
|
|
|
|
# Never send vacation mails for the following recipient email addresses.
|
|
|
|
|
# Useful for e.g. aliases pointing to multiple recipients which have vacation active
|
|
|
|
|
# hence an email to the alias should not trigger vacation messages.
|
|
|
|
|
# By default vacation email addresses will be sent for all recipients.
|
|
|
|
|
# default = ''
|
|
|
|
|
# preventing vacation notifications for recipient info@example.org would look like this:
|
|
|
|
|
# our $no_vacation_pattern = 'info\@example\.org';
|
|
|
|
|
our $no_vacation_pattern = 'info\@example\.org';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# instead of changing this script, you can put your settings to /etc/mail/postfixadmin/vacation.conf
|
|
|
|
|
# or /etc/postfixadmin/vacation.conf just use Perl syntax there to fill the variables listed above
|
|
|
|
@ -216,6 +235,8 @@ if (-f '/etc/mail/postfixadmin/vacation.conf') {
|
|
|
|
|
require '/etc/mail/postfixadmin/vacation.conf';
|
|
|
|
|
} elsif (-f '/etc/postfixadmin/vacation.conf') {
|
|
|
|
|
require '/etc/postfixadmin/vacation.conf';
|
|
|
|
|
} elsif (-f './vacation.conf') {
|
|
|
|
|
require './vacation.conf';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# =========== end configuration ===========
|
|
|
|
@ -249,6 +270,7 @@ if($test_mode == 1) {
|
|
|
|
|
$appender->layout($log_layout);
|
|
|
|
|
$logger->add_appender($appender);
|
|
|
|
|
$logger->debug('Test mode enabled');
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
$logger = get_logger();
|
|
|
|
|
if($log_to_file == 1) {
|
|
|
|
@ -536,45 +558,51 @@ sub send_vacation_email {
|
|
|
|
|
my $body = $row[1];
|
|
|
|
|
my $from = $email;
|
|
|
|
|
my $to = $orig_from;
|
|
|
|
|
my %smtp_connection;
|
|
|
|
|
%smtp_connection = (
|
|
|
|
|
'smtp' => $smtp_server,
|
|
|
|
|
'port' => $smtp_server_port,
|
|
|
|
|
'auth' => $smtp_auth,
|
|
|
|
|
'authid' => $smtp_authid,
|
|
|
|
|
'authpwd' => $smtp_authpwd,
|
|
|
|
|
'tls_allowed' => $smtp_tls_allowed,
|
|
|
|
|
'smtp_client' => $smtp_client,
|
|
|
|
|
'skip_bad_recipients' => 'true',
|
|
|
|
|
'encoding' => 'Base64',
|
|
|
|
|
'ctype' => 'text/plain; charset=UTF-8',
|
|
|
|
|
'headers' => 'Precedence: junk',
|
|
|
|
|
'headers' => 'X-Loop: Postfix Admin Virtual Vacation',
|
|
|
|
|
'on_errors' => 'die', # raise exception on error
|
|
|
|
|
);
|
|
|
|
|
my %mail;
|
|
|
|
|
%mail = (
|
|
|
|
|
'subject' => encode_mimewords($subject, 'Charset', 'UTF-8'),
|
|
|
|
|
'from' => $from,
|
|
|
|
|
'fake_from' => $friendly_from . " <$from>",
|
|
|
|
|
'to' => $to,
|
|
|
|
|
'msg' => encode_base64(encode("UTF-8", $body))
|
|
|
|
|
|
|
|
|
|
my $smtp_params = {
|
|
|
|
|
host => $smtp_server,
|
|
|
|
|
port => $smtp_server_port,
|
|
|
|
|
ssl_options => $ssl_options,
|
|
|
|
|
ssl => $smtp_ssl,
|
|
|
|
|
timeout => $smtp_timeout,
|
|
|
|
|
localaddr => $smtp_client,
|
|
|
|
|
debug => 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if($smtp_authid ne ''){
|
|
|
|
|
$smtp_params->{sasl_username}=$smtp_authid;
|
|
|
|
|
$smtp_params->{sasl_password}=$smtp_authpwd;
|
|
|
|
|
$logger->info("Doing SASL Authentication with user $smtp_params->{sasl_username}\n");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
my $transport = Email::Sender::Transport::SMTP->new($smtp_params);
|
|
|
|
|
|
|
|
|
|
$email = Email::Simple->create(
|
|
|
|
|
header => [
|
|
|
|
|
To => $to,
|
|
|
|
|
From => $from,
|
|
|
|
|
Subject => encode_mimewords($subject, 'Charset', 'UTF-8'),
|
|
|
|
|
Precedence => 'junk',
|
|
|
|
|
'Content-Type' => "text/plain; charset=utf-8",
|
|
|
|
|
'X-Loop' => 'Postfix Admin Virtual Vacation',
|
|
|
|
|
],
|
|
|
|
|
body => $body,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if($test_mode == 1) {
|
|
|
|
|
$logger->info("** TEST MODE ** : Vacation response sent to $to from $from subject $subject (not) sent\n");
|
|
|
|
|
$logger->info(%mail);
|
|
|
|
|
$logger->info($email);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
eval {
|
|
|
|
|
$Mail::Sender::NO_X_MAILER = 1;
|
|
|
|
|
my $sender = new Mail::Sender({%smtp_connection});
|
|
|
|
|
$sender->Open({%mail});
|
|
|
|
|
$sender->SendLineEnc($body);
|
|
|
|
|
$sender->Close();
|
|
|
|
|
$logger->debug("Vacation response sent to $to, from $from");
|
|
|
|
|
};
|
|
|
|
|
if ($@) {
|
|
|
|
|
$logger->error("Failed to send vacation response: $@ / " . $Mail::Sender::Error);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
sendmail($email, { transport => $transport });
|
|
|
|
|
} finally {
|
|
|
|
|
if (@_) {
|
|
|
|
|
$logger->error("Failed to send vacation response to $to from $from subject $subject: @_");
|
|
|
|
|
} else {
|
|
|
|
|
$logger->debug("Vacation response sent to $to from $from subject $subject sent\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -655,6 +683,7 @@ $cc = '';
|
|
|
|
|
$replyto = '';
|
|
|
|
|
|
|
|
|
|
$logger->debug("Script argument SMTP recipient is : '$smtp_recipient' and smtp_sender : '$smtp_sender'");
|
|
|
|
|
|
|
|
|
|
while (<STDIN>) {
|
|
|
|
|
last if (/^$/);
|
|
|
|
|
if (/^\s+(.*)/ and $lastheader) { $$lastheader .= " $1"; next; }
|
|
|
|
@ -695,6 +724,12 @@ if(!$from || !$to || !$messageid || !$smtp_sender || !$smtp_recipient) {
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
$logger->debug("Email headers have to: '$to' and From: '$from'");
|
|
|
|
|
|
|
|
|
|
if ($to =~ /^.*($no_vacation_pattern).*/i) {
|
|
|
|
|
$logger->debug("Will not send vacation reply for messages to $to");
|
|
|
|
|
exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$to = strip_address($to);
|
|
|
|
|
$cc = strip_address($cc);
|
|
|
|
|
$from = check_and_clean_from_address($from);
|
|
|
|
|