mirror of
https://github.com/postfixadmin/postfixadmin.git
synced 2024-09-19 19:22:14 +02:00
plenty of updates to vacation.pl - add log4perl support and crude testing harness
git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@440 a1433add-5e2c-0410-b055-b7f2511e0802
This commit is contained in:
parent
77b3627667
commit
be1b5b2eac
22
VIRTUAL_VACATION/tests/asterisk-email.txt
Normal file
22
VIRTUAL_VACATION/tests/asterisk-email.txt
Normal file
@ -0,0 +1,22 @@
|
||||
Return-Path: <www-data@palepurple.co.uk>
|
||||
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>
|
||||
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>
|
||||
Date: Fri, 01 Aug 2008 11:23:45 +0100
|
||||
Content-Type: text/plain; charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
Message-Id: <20080801102345.1942F894CF9@mail.palepurple.co.uk>
|
||||
Content-Length: 250
|
||||
Lines: 5
|
||||
|
||||
|
||||
=0AVisit the following URL(s) to annotate these phone calls... :=0A=0A htt=
|
||||
ps://admin.palepurple.co.uk/contacts/phone_communication/browse.php=0Ahttp=
|
||||
s://admin.palepurple.co.uk/contacts/phone_communication/view.php?phone_com=
|
||||
munication_id=3D3532
|
55
VIRTUAL_VACATION/tests/facebook.txt
Normal file
55
VIRTUAL_VACATION/tests/facebook.txt
Normal file
@ -0,0 +1,55 @@
|
||||
Return-Path: <notification+meynbxsa@facebookmail.com>
|
||||
X-Original-To: david@example.org
|
||||
Delivered-To: david@example.org
|
||||
Received: by mail.palepurple.co.uk (Postfix, from userid 1007)
|
||||
id B735A894CF8; Mon, 4 Aug 2008 16:28:13 +0100 (BST)
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 79230894CF9
|
||||
for <david@example.org>; Mon, 4 Aug 2008 16:28:13 +0100 (BST)
|
||||
X-Virus-Scanned: by Amavis+SpamAssassin+ClamAV and more at palepurple.co.uk
|
||||
X-Spam-Score: -3.565
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-3.565 tagged_above=-99 required=5 tests=[AWL=0.035,
|
||||
BAYES_00=-2.599, RCVD_IN_DNSWL_LOW=-1, SPF_PASS=-0.001]
|
||||
Received: from mail.palepurple.co.uk ([127.0.0.50])
|
||||
by localhost (oak.palepurple.co.uk [127.0.0.50]) (amavisd-new, port 10024)
|
||||
with ESMTP id AajG3+FXGWMd for <david@example.org>;
|
||||
Mon, 4 Aug 2008 16:28:10 +0100 (BST)
|
||||
Received: from mx-out.facebook.com (outmail003.ash1.tfbnw.net [69.63.184.103])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 36DD4894CF8
|
||||
for <david@example.org>; Mon, 4 Aug 2008 16:28:09 +0100 (BST)
|
||||
Received: from www.new.facebook.com (intlb01-mip1.sctm.tfbnw.net [10.1.240.6])
|
||||
by mx-out.facebook.com [email023.ash1.facebook.com] (8.13.7/8.13.6) with ESMTP id m74FS8Oa030908
|
||||
for <david@example.org>; Mon, 4 Aug 2008 08:28:09 -0700
|
||||
X-Facebook: from zuckmail ([207.118.59.216])
|
||||
by www.new.facebook.com with HTTP (ZuckMail);
|
||||
Date: Mon, 4 Aug 2008 08:28:08 -0700
|
||||
To: David Goodwin <david@example.org>
|
||||
From: Facebook <notification+meynbxsa@facebookmail.com>
|
||||
Reply-to: noreply <noreply@facebookmail.com>
|
||||
Subject: Mark Spencer also commented on Jon Masters's note...
|
||||
Message-ID: <dummycontentgoeshere27efe2cde474@www.new.facebook.com>
|
||||
X-Priority: 3
|
||||
X-Mailer: ZuckMail [version 1.00]
|
||||
X-Facebook-Notify: note_reply
|
||||
Errors-To: notification+meynbxsa@facebookmail.com
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Content-Type: text/plain; charset="UTF-8"
|
||||
Content-Length: 374
|
||||
Lines: 14
|
||||
|
||||
Mark also commented on Jon Masters's note "Visiting the UK"
|
||||
|
||||
To read all the comments, follow the link below:
|
||||
|
||||
http://www.facebook.com/n/?note.php¬e_id=whatever
|
||||
|
||||
Thanks,
|
||||
The Facebook Team
|
||||
|
||||
___
|
||||
Want to control which emails you receive from Facebook? Go to:
|
||||
http://www.facebook.com/editaccount.php?notifications&md=sheepmightfly
|
||||
|
||||
|
110
VIRTUAL_VACATION/tests/mailing-list.txt
Normal file
110
VIRTUAL_VACATION/tests/mailing-list.txt
Normal file
@ -0,0 +1,110 @@
|
||||
Return-Path: <fw-general-return-20540-david=example.org@lists.zend.com>
|
||||
X-Original-To: david@example.org
|
||||
Delivered-To: david@example.org
|
||||
Received: by mail.palepurple.co.uk (Postfix, from userid 1007)
|
||||
id A41BE894CF8; Tue, 5 Aug 2008 19:46:09 +0100 (BST)
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 6786E894CF9
|
||||
for <david@example.org>; Tue, 5 Aug 2008 19:46:09 +0100 (BST)
|
||||
X-Virus-Scanned: by Amavis+SpamAssassin+ClamAV and more at palepurple.co.uk
|
||||
X-Spam-Score: -2.478
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-2.478 tagged_above=-99 required=5 tests=[AWL=0.545,
|
||||
BAYES_00=-2.599, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-1,
|
||||
SPF_HELO_NEUTRAL=0.576, SPF_PASS=-0.001]
|
||||
Received: from mail.palepurple.co.uk ([127.0.0.50])
|
||||
by localhost (oak.palepurple.co.uk [127.0.0.50]) (amavisd-new, port 10024)
|
||||
with ESMTP id F7C1kX6O4LsN for <david@example.org>;
|
||||
Tue, 5 Aug 2008 19:46:01 +0100 (BST)
|
||||
Received: from www.zend.com (lists.zend.com [67.15.86.102])
|
||||
by mail.palepurple.co.uk (Postfix) with SMTP id 83287894CF8
|
||||
for <david@example.org>; Tue, 5 Aug 2008 19:46:01 +0100 (BST)
|
||||
Received: (qmail 28760 invoked by uid 505); 5 Aug 2008 18:45:46 -0000
|
||||
Mailing-List: contact fw-general-help@lists.zend.com; run by ezmlm
|
||||
Precedence: bulk
|
||||
List-Post: <mailto:fw-general@lists.zend.com>
|
||||
List-Help: <mailto:fw-general-help@lists.zend.com>
|
||||
List-Unsubscribe: <mailto:fw-general-unsubscribe@lists.zend.com>
|
||||
List-Subscribe: <mailto:fw-general-subscribe@lists.zend.com>
|
||||
Delivered-To: mailing list fw-general@lists.zend.com
|
||||
Received: (qmail 28753 invoked from network); 5 Aug 2008 18:45:46 -0000
|
||||
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
|
||||
s=s1024; d=yahoo.com;
|
||||
h=Received:X-Mailer:Date:From:Subject:To:Cc:MIME-Version:Content-Type:Message-ID;
|
||||
b=RX7cjkrkpdsfHOXg2TRzzF2P5UXe0S5UVRucVl9FdqyE070/mV2za8ehvsGVRTh11tjkhkzh9QJoijpzHTTyu8F4HUHHoql4wUS6zJJC/PgdcCpBVXf0Im4RkyXqhIOAndNk1d9tCPmUnKDjC6SvO6i0Xd5+CqFH9f+eaKzUFAI=;
|
||||
X-Mailer: YahooMailRC/1042.48 YahooMailWebService/0.7.218
|
||||
Date: Tue, 5 Aug 2008 11:45:44 -0700 (PDT)
|
||||
From: =?iso-8859-1?Q?P=E1draic_Brady?= <some.one@yahoo.com>
|
||||
To: Some one Else <someone.else@gmail.com>
|
||||
Cc: Zend Framework General <overthere@example.org>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary="0-283769398-1217961944=:498"
|
||||
Message-ID: <944272.498.qm@web55003.mail.re4.yahoo.com>
|
||||
X-pstn-neptune: 0/0/0.00/0
|
||||
X-pstn-levels: (S:99.90000/99.90000 CV:99.0000 P:95.9108 M:97.0282 C:98.6951 )
|
||||
X-pstn-settings: 1 (0.1500:0.1500) cv gt3 gt2 gt1 p m c
|
||||
X-pstn-addresses: from <some.one@yahoo.com> [638/31]
|
||||
Subject: Re: [fw-general] Zend_Paginate how to integrate?
|
||||
Content-Length: 4072
|
||||
Lines: 60
|
||||
|
||||
--0-283769398-1217961944=:498
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
I do pretty much what Giorgio suggests and tie it into the Model as much as=
|
||||
possible - fits into the concept of doing as little as possible in your co=
|
||||
ntrollers by pushing reusable code into Model (or other) objects if appropr=
|
||||
iate.=0A=0A P=E1draic Brady=0A=0Ahttp://blog.astrumfutura.com=0Ahttp://www.=
|
||||
patternsforphp.com=0AOpenID Europe Foundation=0A=0A=0A=0A=0A----- Original =
|
||||
Message ----=0AFrom: Giorgio Sironi <whatever@example.org>=0ATo=
|
||||
: Axel W=FCstemann <awu@xxxqbus.de>=0ACc: fw-general@xxlists.zend.com=0ASent: Tu=
|
||||
esday, August 5, 2008 7:20:48 PM=0ASubject: Re: [fw-general] Zend_Paginate =
|
||||
how to integrate?=0A=0A2008/8/5 Axel W=FCstemann <awuxxxx@qbus.de>:=0A> Yes, it=
|
||||
seems to me a good idea to let reside the paginator in the model.=0A> What=
|
||||
happens in the controller? How the view comes into play?=0A=0AThe controll=
|
||||
er simply calls the method prepareArticles with the right=0Apage (a param o=
|
||||
f request) and pass the paginator to the view, so the=0Aview script can use=
|
||||
it for helpers like PaginationControl. Note that=0Abecause the paginator g=
|
||||
oes into the view, it return only=0Amultidimensional array and not objects.=
|
||||
=0A=0A-- =0AGiorgio Sironi=0APiccolo Principe & Ossigeno Scripter=0Ahttp://=
|
||||
www.sourceforge.net/projects/ossigeno=0A
|
||||
--0-283769398-1217961944=:498
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<html><head><style type=3D"text/css"><!-- DIV {margin:0px;} --></style></he=
|
||||
ad><body><div style=3D"font-family:Courier New,courier,monaco,monospace,san=
|
||||
s-serif;font-size:10pt"><font style=3D"font-family: times new roman,new yor=
|
||||
k,times,serif;" size=3D"3">I do pretty much what Giorgio suggests and tie i=
|
||||
t into the Model as much as possible - fits into the concept of doing as li=
|
||||
ttle as possible in your controllers by pushing reusable code into Model (o=
|
||||
r other) objects if appropriate.</font><br><div> </div><span style=3D"=
|
||||
color: rgb(0, 0, 191);"><font style=3D"font-family: times new roman,new yor=
|
||||
k,times,serif;" size=3D"3"><span style=3D"font-weight: bold;">P=E1draic Bra=
|
||||
dy<br><br></span></font><span style=3D"font-style: italic;"><font style=3D"=
|
||||
font-family: times new roman,new york,times,serif;" size=3D"3"><a rel=3D"no=
|
||||
follow" target=3D"_blank" href=3D"http://blog.astrumfutura.com">http://blog=
|
||||
.astrumfutura.com</a><br><a rel=3D"nofollow" target=3D"_blank"
|
||||
href=3D"http://www.patternsforphp.com">http://www.patternsforphp.com</a><b=
|
||||
r><a rel=3D"nofollow" target=3D"_blank" href=3D"http://www.openideurope.eu/=
|
||||
">OpenID Europe Foundation</a><br></font></span></span><div><br></div><div =
|
||||
style=3D"font-family: Courier New,courier,monaco,monospace,sans-serif; font=
|
||||
-size: 10pt;"><br><div style=3D"font-family: arial,helvetica,sans-serif; fo=
|
||||
nt-size: 10pt;">----- Original Message ----<br>From: Giorgio Sironi <pic=
|
||||
coloprincipeazzurroxxxxx@gxxxmail.com><br>To: Axel W=FCstemann <awuxx@qbus.de&g=
|
||||
t;<br>Cc: fw-general@xxxlists.zend.com<br>Sent: Tuesday, August 5, 2008 7:20:4=
|
||||
8 PM<br>Subject: Re: [fw-general] Zend_Paginate how to integrate?<br><br>=
|
||||
=0A2008/8/5 Axel W=FCstemann <<a ymailto=3D"mailto:awuxxx@xxxqbus.de" href=3D"=
|
||||
mailto:awuxx@xxqbus.de">xxawu@qxxxbus.de</a>>:<br>> Yes, it seems to me a good=
|
||||
idea to let reside the paginator in the model.<br>> What happens in the=
|
||||
controller? How the view comes into play?<br><br>The controller simply cal=
|
||||
ls the method prepareArticles with the right<br>page (a param of request) a=
|
||||
nd pass the paginator to the view, so the<br>view script can use it for hel=
|
||||
pers like PaginationControl. Note that<br>because the paginator goes into t=
|
||||
he view, it return only<br>multidimensional array and not objects.<br><br>-=
|
||||
- <br>Giorgio Sironi<br>Piccolo Principe & Ossigeno Scripter<br><a href=
|
||||
=3D"http://www.sourceforge.net/projects/ossigeno" target=3D"_blank">http://=
|
||||
www.sourceforge.net/projects/ossigeno</a><br></div></div></div></body></htm=
|
||||
l>
|
||||
--0-283769398-1217961944=:498--
|
105
VIRTUAL_VACATION/tests/spam.txt
Normal file
105
VIRTUAL_VACATION/tests/spam.txt
Normal file
@ -0,0 +1,105 @@
|
||||
Return-Path: <mary@ccr.org>
|
||||
X-Original-To: david@codepoets.co.uk
|
||||
Delivered-To: david@codepoets.co.uk
|
||||
Received: by mail.palepurple.co.uk (Postfix, from userid 1007)
|
||||
id A7BB7894CF8; Tue, 5 Aug 2008 19:32:19 +0100 (BST)
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 673E4894CF9
|
||||
for <david@codepoets.co.uk>; Tue, 5 Aug 2008 19:32:19 +0100 (BST)
|
||||
X-Quarantine-ID: <KOCPqIot+eWP>
|
||||
X-Virus-Scanned: by Amavis+SpamAssassin+ClamAV and more at palepurple.co.uk
|
||||
X-Spam-Flag: YES
|
||||
X-Spam-Score: 35.511
|
||||
X-Spam-Level: ***********************************
|
||||
X-Spam-Status: Yes, score=35.511 tagged_above=-99 required=5
|
||||
tests=[BAYES_99=3.5, DIGEST_MULTIPLE=0.001, FH_HELO_EQ_D_D_D_D=0.001,
|
||||
HELO_DYNAMIC_HCC=4.295, HELO_DYNAMIC_IPADDR2=4.395,
|
||||
HTML_EXTRA_CLOSE=2.809, HTML_MESSAGE=0.001, PYZOR_CHECK=3.7,
|
||||
RAZOR2_CF_RANGE_51_100=0.5, RAZOR2_CF_RANGE_E4_51_100=1.5,
|
||||
RAZOR2_CF_RANGE_E8_51_100=1.5, RAZOR2_CHECK=0.5, RCVD_IN_PBL=0.905,
|
||||
RDNS_DYNAMIC=0.1, TVD_RCVD_IP=1.931, URIBL_AB_SURBL=1.86,
|
||||
URIBL_BLACK=1.955, URIBL_JP_SURBL=1.501, URIBL_OB_SURBL=1.5,
|
||||
URIBL_RHS_DOB=1.083, URIBL_SC_SURBL=0.474, URIBL_WS_SURBL=1.5]
|
||||
X-Spam-Report:
|
||||
* 3.5 BAYES_99 BODY: Bayesian spam probability is 99 to 100%
|
||||
* [score: 0.9982]
|
||||
* 4.3 HELO_DYNAMIC_HCC Relay HELO'd using suspicious hostname (HCC)
|
||||
* 4.4 HELO_DYNAMIC_IPADDR2 Relay HELO'd using suspicious hostname (IP addr
|
||||
* 2)
|
||||
* 0.0 FH_HELO_EQ_D_D_D_D Helo is d-d-d-d
|
||||
* 1.9 TVD_RCVD_IP TVD_RCVD_IP
|
||||
* 0.9 RCVD_IN_PBL RBL: Received via a relay in Spamhaus PBL
|
||||
* [189.31.157.78 listed in zen.spamhaus.org]
|
||||
* 2.8 HTML_EXTRA_CLOSE BODY: HTML contains far too many close tags
|
||||
* 0.0 HTML_MESSAGE BODY: HTML included in message
|
||||
* 1.5 RAZOR2_CF_RANGE_E8_51_100 Razor2 gives engine 8 confidence level
|
||||
* above 50%
|
||||
* [cf: 100]
|
||||
* 1.5 RAZOR2_CF_RANGE_E4_51_100 Razor2 gives engine 4 confidence level
|
||||
* above 50%
|
||||
* [cf: 100]
|
||||
* 0.5 RAZOR2_CHECK Listed in Razor2 (http://razor.sf.net/)
|
||||
* 0.5 RAZOR2_CF_RANGE_51_100 Razor2 gives confidence level above 50%
|
||||
* [cf: 100]
|
||||
* 3.7 PYZOR_CHECK Listed in Pyzor (http://pyzor.sf.net/)
|
||||
* 1.1 URIBL_RHS_DOB Contains an URI of a new domain (Day Old Bread)
|
||||
* [URIs: heartremember.com]
|
||||
* 2.0 URIBL_BLACK Contains an URL listed in the URIBL blacklist
|
||||
* [URIs: heartremember.com]
|
||||
* 1.9 URIBL_AB_SURBL Contains an URL listed in the AB SURBL blocklist
|
||||
* [URIs: heartremember.com]
|
||||
* 1.5 URIBL_WS_SURBL Contains an URL listed in the WS SURBL blocklist
|
||||
* [URIs: heartremember.com]
|
||||
* 1.5 URIBL_JP_SURBL Contains an URL listed in the JP SURBL blocklist
|
||||
* [URIs: heartremember.com]
|
||||
* 1.5 URIBL_OB_SURBL Contains an URL listed in the OB SURBL blocklist
|
||||
* [URIs: heartremember.com]
|
||||
* 0.5 URIBL_SC_SURBL Contains an URL listed in the SC SURBL blocklist
|
||||
* [URIs: heartremember.com]
|
||||
* 0.0 DIGEST_MULTIPLE Message hits more than one network digest check
|
||||
* 0.1 RDNS_DYNAMIC Delivered to trusted network by host with
|
||||
* dynamic-looking rDNS
|
||||
Received: from mail.palepurple.co.uk ([127.0.0.50])
|
||||
by localhost (oak.palepurple.co.uk [127.0.0.50]) (amavisd-new, port 10024)
|
||||
with ESMTP id KOCPqIot+eWP for <david@codepoets.co.uk>;
|
||||
Tue, 5 Aug 2008 19:32:13 +0100 (BST)
|
||||
Received: from 189-31-157-78.gnace704.dsl.brasiltelecom.net.br (189-31-157-78.gnace704.dsl.brasiltelecom.net.br [189.31.157.78])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 02E02894CF8
|
||||
for <postmaster@codepoets.co.uk>; Tue, 5 Aug 2008 19:32:11 +0100 (BST)
|
||||
Date: Tue, 05 Aug 2008 16:44:31 +0000
|
||||
Message-ID: <45605.clarke@shan>
|
||||
From: "ferd clarke" <mary@ccr.org>
|
||||
To: <postmaster@codepoets.co.uk>
|
||||
Subject: *** SPAM *** Super eustace proposition
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
boundary="=_xjl52j6iKNOFLD"
|
||||
Content-Length: 628
|
||||
Lines: 26
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
--=_xjl52j6iKNOFLD
|
||||
Content-Type: text/plain;
|
||||
charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
view, medicine todays best solution check out here
|
||||
--=_xjl52j6iKNOFLD
|
||||
Content-Type: text/html;
|
||||
charset="iso-8859-1"
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META http-equiv=3DContent-Type content=3D"text/html; =
|
||||
charset=3Diso-8859-1">
|
||||
</HEAD>
|
||||
<P> view, medicine todays best solution <A =
|
||||
href=3D"http://heartremember.com">check out here</A></P>
|
||||
</BODY>
|
||||
</HTML>
|
||||
--=_xjl52j6iKNOFLD--
|
||||
|
||||
|
42
VIRTUAL_VACATION/tests/test-email.txt
Normal file
42
VIRTUAL_VACATION/tests/test-email.txt
Normal file
@ -0,0 +1,42 @@
|
||||
Return-Path: <david1@example.org>
|
||||
X-Original-To: david@example.org
|
||||
Delivered-To: david@example.org
|
||||
Received: by mail.palepurple.co.uk (Postfix, from userid 1007)
|
||||
id 83AE0894CF8; Tue, 5 Aug 2008 20:15:53 +0100 (BST)
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id 4A249894CF9
|
||||
for <david@example.org>; Tue, 5 Aug 2008 20:15:53 +0100 (BST)
|
||||
X-Virus-Scanned: by Amavis+SpamAssassin+ClamAV and more at palepurple.co.uk
|
||||
X-Spam-Score: -2.836
|
||||
X-Spam-Level:
|
||||
X-Spam-Status: No, score=-2.836 tagged_above=-99 required=5 tests=[AWL=-0.237,
|
||||
BAYES_00=-2.599]
|
||||
Received: from mail.palepurple.co.uk ([127.0.0.50])
|
||||
by localhost (oak.palepurple.co.uk [127.0.0.50]) (amavisd-new, port 10024)
|
||||
with ESMTP id gHB1TKpjKIKX for <david@example.org>;
|
||||
Tue, 5 Aug 2008 20:15:50 +0100 (BST)
|
||||
Received: from irc.palepurple.co.uk (irc.palepurple.co.uk [89.16.169.131])
|
||||
by mail.palepurple.co.uk (Postfix) with ESMTP id CAF82894CF8
|
||||
for <david@example.org>; Tue, 5 Aug 2008 20:15:50 +0100 (BST)
|
||||
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
|
||||
Subject: test email
|
||||
Message-ID: <20080805191549.GA27905@codepoets.co.uk>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Disposition: inline
|
||||
X-GnuPG-Key-URL: http://codepoets.co.uk/files/pubkey.txt
|
||||
X-PGP-Key: 0x117957A6
|
||||
User-Agent: Mutt/1.5.13 (2006-08-11)
|
||||
Content-Length: 136
|
||||
Lines: 7
|
||||
|
||||
hello world; this is in plain text only.
|
||||
|
||||
--
|
||||
David Goodwin
|
||||
|
||||
[ http://www.codepoets.co.uk ]
|
42
VIRTUAL_VACATION/tests/test.sh
Normal file
42
VIRTUAL_VACATION/tests/test.sh
Normal file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is an extremely simplistic test harness for the vacation functionality.
|
||||
# To judge success or failure you (unfortunately) need to tail -f the log file, which sucks a little,
|
||||
# but hey - it's better than no tests, right?
|
||||
|
||||
# Original author: David Goodwin (hence all the palepurple.co.uk references!)
|
||||
# It would be nice if we could get some sort of status back from the vacation.pl script to indicate mail being sent, or not.
|
||||
|
||||
|
||||
|
||||
export PGPASSWORD=gingerdog
|
||||
export PGUSER=dg
|
||||
export PGDATABASE=postfix
|
||||
export PGHOST=pgsqlserver
|
||||
|
||||
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 "NONE OF THESE SHOULD RESULT IN MAIL BEING SENT"
|
||||
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
|
||||
|
||||
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 "VACATION TURNED ON "
|
||||
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"
|
||||
cat test-email.txt | perl ../vacation.pl -t yes -f david1@example.org -- david@example.org
|
||||
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"
|
||||
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"
|
||||
cat facebook.txt | perl ../vacation.pl -t yes -f notification+meynbxsa@facebookmail.com -- david@example.org
|
@ -50,19 +50,25 @@
|
||||
# http://www.irbs.net/internet/postfix/0707/0954.html
|
||||
# (needs to be tested);
|
||||
#
|
||||
# Requirements:
|
||||
# You need to have the DBD::Pg or DBD::mysql perl-module installed.
|
||||
# You need to have the Mail::Sendmail module installed.
|
||||
# You need to have the Email::Valid module installed.
|
||||
# You need to have the MIME::Charset module installed.
|
||||
# You need to have the MIME::EncWords module installed.
|
||||
# You need to have the GetOpt::Std module installed.
|
||||
# 2008-08-04 David Goodwin <david at palepurple dot co dot uk>
|
||||
# Use Log4Perl
|
||||
# Added better testing (and -t option)
|
||||
#
|
||||
# Requirements - the following perl modules are required:
|
||||
# DBD::Pg or DBD::mysql
|
||||
# Mail::Sendmail, Email::Valid MIME::Charset, Log::Log4perl, Log::Dispatch, MIME::EncWords 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-sendmail-perl
|
||||
# libdbd-pg-perl
|
||||
# libemail-valid-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)
|
||||
#
|
||||
@ -93,21 +99,22 @@ my $db_type = 'Pg';
|
||||
my $db_host = '';
|
||||
|
||||
# connection details
|
||||
my $db_username = 'vacation';
|
||||
my $db_password = '';
|
||||
my $db_username = 'dg';
|
||||
my $db_password = 'gingerdog';
|
||||
my $db_name = 'postfix';
|
||||
|
||||
# smtp server used to send vacation e-mails
|
||||
my $smtp_server = 'localhost';
|
||||
my $smtp_server = '192.168.1.4';
|
||||
|
||||
my $syslog = 1;
|
||||
my $syslog = 0;
|
||||
|
||||
# path to logfile, when empty logging is supressed
|
||||
my $logfile='';
|
||||
#my $logfile = "/var/log/vacation/vacation.log";
|
||||
# path to file for debugging, debug supressed when empty
|
||||
my $debugfile='';
|
||||
#my $debugfile = "/var/log/vacation/vacation.debug";
|
||||
# change to e.g. /dev/null if you want nothing logged.
|
||||
# if we can't write to this, we try /tmp/vacation.log instead
|
||||
my $logfile='/var/spool/vacation/vacation.log';
|
||||
# 2 = debug + info, 1 = info only, 0 = error only
|
||||
my $log_level = 2;
|
||||
|
||||
|
||||
# notification interval, in seconds
|
||||
# set to 0 to notify only once
|
||||
@ -118,6 +125,10 @@ my $interval = 0;
|
||||
|
||||
# =========== end configuration ===========
|
||||
|
||||
if ( ! -w $logfile ) {
|
||||
$logfile = "/tmp/vacation.log";
|
||||
}
|
||||
|
||||
use DBI;
|
||||
use MIME::Base64;
|
||||
use MIME::EncWords qw(:all);
|
||||
@ -125,312 +136,365 @@ use Email::Valid;
|
||||
use strict;
|
||||
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);
|
||||
|
||||
$subject='';
|
||||
|
||||
# Setup a logger...
|
||||
#
|
||||
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;
|
||||
|
||||
my $log_layout = Log::Log4perl::Layout::PatternLayout->new("%d %p> %F:%L %M - %m%n");
|
||||
|
||||
if($test_mode == 1) {
|
||||
$logger = get_logger();
|
||||
# log to stdout
|
||||
my $appender = Log::Log4perl::Appender->new('Log::Dispatch::Screen');
|
||||
$appender->layout($log_layout);
|
||||
$logger->add_appender($appender);
|
||||
$logger->debug("Test mode enabled");
|
||||
}
|
||||
else {
|
||||
# log to file.
|
||||
my $appender = Log::Log4perl::Appender->new(
|
||||
'Log::Dispatch::File',
|
||||
filename => $logfile,
|
||||
mode => 'append');
|
||||
|
||||
my $logger = get_logger();
|
||||
$appender->layout($log_layout);
|
||||
$logger->add_appender($appender);
|
||||
|
||||
if($syslog == 1) {
|
||||
my $syslog_appender = Log::Log4perl::Appender->new(
|
||||
'Log::Dispatch::Syslog',
|
||||
Facility => 'user',
|
||||
);
|
||||
$logger->add_appender($syslog_appender);
|
||||
}
|
||||
}
|
||||
|
||||
# change to $DEBUG, $INFO or $ERROR depending on how much logging you want.
|
||||
$logger->level($ERROR);
|
||||
if($log_level == 1) {
|
||||
$logger->level($INFO);
|
||||
}
|
||||
if($log_level == 2) {
|
||||
$logger->level($DEBUG);
|
||||
}
|
||||
|
||||
|
||||
binmode (STDIN,':utf8');
|
||||
|
||||
my $dbh;
|
||||
if ($db_host) {
|
||||
$dbh = DBI->connect("DBI:$db_type:dbname=$db_name;host=$db_host","$db_username", "$db_password", { RaiseError => 1 });
|
||||
$dbh = DBI->connect("DBI:$db_type:dbname=$db_name;host=$db_host","$db_username", "$db_password", { RaiseError => 1 });
|
||||
} else {
|
||||
$dbh = DBI->connect("DBI:$db_type:dbname=$db_name","$db_username", "$db_password", { RaiseError => 1 });
|
||||
$dbh = DBI->connect("DBI:$db_type:dbname=$db_name","$db_username", "$db_password", { RaiseError => 1 });
|
||||
}
|
||||
|
||||
if (!$dbh) {
|
||||
panic("Could not connect to database");
|
||||
exit(0);
|
||||
$logger->error("Could not connect to database"); # eval { } etc better here?
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $db_true; # MySQL and PgSQL use different values for TRUE, and unicode support...
|
||||
if ($db_type eq "mysql") {
|
||||
$dbh->do("SET CHARACTER SET utf8;");
|
||||
$db_true = '1';
|
||||
$dbh->do("SET CHARACTER SET utf8;");
|
||||
$db_true = '1';
|
||||
} else { # Pg
|
||||
$dbh->do("SET CLIENT ENCODING 'UTF8'");
|
||||
$db_true = 'True';
|
||||
$dbh->do("SET CLIENT_ENCODING TO 'UTF8'");
|
||||
$db_true = 'True';
|
||||
}
|
||||
|
||||
# used to detect infinite address lookup loops
|
||||
my $loopcount=0;
|
||||
|
||||
sub do_debug {
|
||||
if ( $debugfile ) {
|
||||
my $date;
|
||||
open (DEBUG, ">> $debugfile") or die ("Unable to open debug file");
|
||||
binmode (DEBUG, ':utf8');
|
||||
chop ($date = `date "+%Y/%m/%d %H:%M:%S"`);
|
||||
print DEBUG "====== $date ======\n";
|
||||
my $i;
|
||||
for ($i=0;$i<$#_;$i++) {
|
||||
print DEBUG $_[$i], ' | ';
|
||||
}
|
||||
print DEBUG $_[($#_)], "\n";
|
||||
close (DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
sub already_notified {
|
||||
my ($to, $from) = @_;
|
||||
my $query = qq{INSERT into vacation_notification (on_vacation,notified) values (?,?)};
|
||||
my $stm = $dbh->prepare($query);
|
||||
if (!$stm) {
|
||||
do_log('',$to,$from,'',"Could not prepare query $query");
|
||||
return 1;
|
||||
}
|
||||
$stm->{'PrintError'} = 0;
|
||||
$stm->{'RaiseError'} = 0;
|
||||
if (!$stm->execute($to,$from)) {
|
||||
my $e=$dbh->errstr;
|
||||
my ($to, $from) = @_;
|
||||
my $logger = get_logger();
|
||||
my $query = qq{INSERT into vacation_notification (on_vacation,notified) values (?,?)};
|
||||
my $stm = $dbh->prepare($query);
|
||||
if (!$stm) {
|
||||
$logger->error("Could not prepare query '$query' to: $to, from:$from");
|
||||
return 1;
|
||||
}
|
||||
$stm->{'PrintError'} = 0;
|
||||
$stm->{'RaiseError'} = 0;
|
||||
if (!$stm->execute($to,$from)) {
|
||||
my $e=$dbh->errstr;
|
||||
|
||||
# Violation of a primay key constraint may happen here, and that's
|
||||
# fine. All other error conditions are not fine, however.
|
||||
if ($e !~ /(?:_pkey|^Duplicate entry)/) {
|
||||
do_log('',$to,$from,'',"Unexpected error: '$e' from query '$query'");
|
||||
|
||||
# Let's play safe and notify anyway
|
||||
return 0;
|
||||
}
|
||||
if ($interval) {
|
||||
$query = qq{SELECT NOW()-notified_at FROM vacation_notification WHERE on_vacation=? AND notified=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($to,$from) or panic_execute($query,"on_vacation='$to', notified='$from'");
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $int = $row[0];
|
||||
if ($int > $interval) {
|
||||
do_debug ("[Interval elapsed, sending the message]: ", $from, $to);
|
||||
$query = qq{UPDATE vacation_notification SET notified_at=NOW() WHERE on_vacation=? AND notified=?};
|
||||
$stm = $dbh->prepare($query);
|
||||
if (!$stm) {
|
||||
do_log('',$to,$from,'',"Could not prepare query $query");
|
||||
return 0;
|
||||
}
|
||||
if (!$stm->execute($to,$from)) {
|
||||
$e=$dbh->errstr;
|
||||
do_log('',$to,$from,'',"Unexpected error: '$e' from query '$query'");
|
||||
}
|
||||
if ($e !~ /(?:_pkey|^Duplicate entry)/) {
|
||||
$logger->error("Failed to insert into vacation_notification table (to:$to from:$from error:'$e' query:'$query')");
|
||||
# Let's play safe and notify anyway
|
||||
return 0;
|
||||
} else {
|
||||
do_debug ("[Interval not elapsed, not sending the message]: ", $from, $to);
|
||||
}
|
||||
if ($interval) {
|
||||
$query = qq{SELECT NOW()-notified_at FROM vacation_notification WHERE on_vacation=? AND notified=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($to,$from) or panic_execute($query,"on_vacation='$to', notified='$from'");
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $int = $row[0];
|
||||
if ($int > $interval) {
|
||||
$logger->debug("[Interval elapsed, sending the message]: From: $from To:$to");
|
||||
$query = qq{UPDATE vacation_notification SET notified_at=NOW() WHERE on_vacation=? AND notified=?};
|
||||
$stm = $dbh->prepare($query);
|
||||
if (!$stm) {
|
||||
$logger->error("Could not prepare query '$query' (to: '$to', from: '$from')");
|
||||
return 0;
|
||||
}
|
||||
if (!$stm->execute($to,$from)) {
|
||||
$e=$dbh->errstr;
|
||||
$logger->error("Error from running query '$query' (to: '$to', from: '$from', error: '$e')");
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
$logger->debug("Notification interval not elapsed; not sending vacation reply (to: '$to', from: '$from')");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub do_log {
|
||||
my ($messageid, $to, $from, $subject, $logmessage) = @_;
|
||||
my $date;
|
||||
if ( $syslog ) {
|
||||
open (SYSLOG, "|/usr/bin/logger -p mail.info -t Vacation") or die ("Unable to open logger");
|
||||
binmode(SYSLOG, ':utf8');
|
||||
if ($logmessage) {
|
||||
printf SYSLOG "Orig-To: %s From: %s MessageID: %s Subject: %s. Log message: %s", $to, $from, $messageid, $subject, $logmessage;
|
||||
} else {
|
||||
printf SYSLOG "Orig-To: %s From: %s MessageID: %s Subject: %s", $to, $from, $messageid, $subject;
|
||||
}
|
||||
close (SYSLOG);
|
||||
}
|
||||
if ( $logfile ) {
|
||||
open (LOG, ">> $logfile") or die ("Unable to open log file");
|
||||
binmode (LOG, ':utf8');
|
||||
chop ($date = `date "+%Y/%m/%d %H:%M:%S"`);
|
||||
if ($logmessage) {
|
||||
print LOG "$date: To: $to From: $from Subject: $subject MessageID: $messageid. Log message: $logmessage\n";
|
||||
} else {
|
||||
print LOG "$date: To: $to From: $from Subject: $subject MessageID: $messageid\n";
|
||||
}
|
||||
close (LOG);
|
||||
}
|
||||
}
|
||||
|
||||
sub do_mail {
|
||||
# from, to, subject, body
|
||||
my ($from, $to, $subject, $body) = @_;
|
||||
my $vacation_subject = encode_mimewords($subject, 'Encoding'=> 'q', 'Charset'=>'utf-8', 'Field'=>'Subject');
|
||||
my %mail;
|
||||
%mail = (
|
||||
'smtp' => $smtp_server,
|
||||
'Subject' => $vacation_subject,
|
||||
'From' => $from,
|
||||
'To' => $to,
|
||||
'MIME-Version' => '1.0',
|
||||
'Content-Type' => 'text/plain; charset=UTF-8',
|
||||
'Content-Transfer-Encoding' => 'base64',
|
||||
'Precedence' => 'junk',
|
||||
'X-Loop' => 'Postfix Admin Virtual Vacation',
|
||||
'Message' => encode_base64($body)
|
||||
);
|
||||
sendmail(%mail) or do_log($Mail::Sendmail::error);
|
||||
do_debug('Mail::Sendmail said :' . $Mail::Sendmail::log);
|
||||
}
|
||||
|
||||
sub panic {
|
||||
my ($arg) = @_;
|
||||
do_log('','','','',"$arg");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub panic_prepare {
|
||||
my ($arg) = @_;
|
||||
do_log('','','','',"Could not prepare '$arg'");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub panic_execute {
|
||||
my ($arg,$param) = @_;
|
||||
do_log('','','','',"Could not execute '$arg' with parameters $param");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
# try and determine if email address has vacation turned on; we
|
||||
# have to do alias searching, and domain aliasing resolution for this.
|
||||
# If found, return ($num_matches, $real_email);
|
||||
sub find_real_address {
|
||||
my ($email) = @_;
|
||||
if (++$loopcount > 20) {
|
||||
do_log ("find_real_address loop!", "currently: $email", "ERROR", "ERROR");
|
||||
panic("possible infinite loop in find_real_address for <$email>. Check for alias loop\n");
|
||||
}
|
||||
my $realemail;
|
||||
my $query = qq{SELECT email FROM vacation WHERE email=? and active=$db_true};
|
||||
my $stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"email='$email'");
|
||||
my $rv = $stm->rows;
|
||||
my ($email) = @_;
|
||||
my $logger = get_logger();
|
||||
if (++$loopcount > 20) {
|
||||
$logger->error("find_real_address loop! (more than 20 attempts!) currently: $email");
|
||||
exit(1);
|
||||
}
|
||||
my $realemail = '';
|
||||
my $query = qq{SELECT email FROM vacation WHERE email=? and active=$db_true};
|
||||
my $stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"email='$email'");
|
||||
my $rv = $stm->rows;
|
||||
|
||||
# Recipient has vacation
|
||||
if ($rv == 1) {
|
||||
$realemail = $email;
|
||||
} else {
|
||||
$query = qq{SELECT goto FROM alias WHERE address=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"address='$email'");
|
||||
$rv = $stm->rows;
|
||||
if ($rv == 1) {
|
||||
$realemail = $email;
|
||||
$logger->debug("Found $email has vacation active");
|
||||
} else {
|
||||
# XXX why aren't we doing a join here?
|
||||
$logger->debug("Looking for alias records that $email resolves to with vacation turned on");
|
||||
$query = qq{SELECT goto FROM alias WHERE address=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"address='$email'");
|
||||
$rv = $stm->rows;
|
||||
|
||||
# Recipient is an alias, check if mailbox has vacation
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $alias = $row[0];
|
||||
$query = qq{SELECT email FROM vacation WHERE email=? and active=$db_true};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($alias) or panic_prepare($query,"email='$alias'");
|
||||
$rv = $stm->rows;
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $alias = $row[0];
|
||||
$query = qq{SELECT email FROM vacation WHERE email=? and active=$db_true};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($alias) or panic_prepare($query,"email='$alias'");
|
||||
$rv = $stm->rows;
|
||||
|
||||
# Alias has vacation
|
||||
if ($rv == 1) {
|
||||
$realemail = $alias;
|
||||
}
|
||||
if ($rv == 1) {
|
||||
$realemail = $alias;
|
||||
}
|
||||
|
||||
# We still have to look for domain level aliases...
|
||||
} else {
|
||||
my ($user, $domain) = split(/@/, $email);
|
||||
$query = qq{SELECT goto FROM alias WHERE address=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute("\@$domain") or panic_execute($query,"address='\@$domain'");
|
||||
$rv = $stm->rows;
|
||||
|
||||
} else {
|
||||
my ($user, $domain) = split(/@/, $email);
|
||||
$query = qq{SELECT goto FROM alias WHERE address=?};
|
||||
$stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute("\@$domain") or panic_execute($query,"address='\@$domain'");
|
||||
$rv = $stm->rows;
|
||||
$logger->debug("Looking for domain level aliases for $domain / $email / $user");
|
||||
# The receipient has a domain level alias
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $wildcard_dest = $row[0];
|
||||
my ($wilduser, $wilddomain) = split(/@/, $wildcard_dest);
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
my $wildcard_dest = $row[0];
|
||||
my ($wilduser, $wilddomain) = split(/@/, $wildcard_dest);
|
||||
|
||||
# Check domain alias
|
||||
if ($wilduser) {
|
||||
($rv, $realemail) = find_real_address ($wildcard_dest);
|
||||
} else {
|
||||
my $new_email = $user . '@' . $wilddomain;
|
||||
($rv, $realemail) = find_real_address ($new_email);
|
||||
if ($wilduser) {
|
||||
($rv, $realemail) = find_real_address ($wildcard_dest);
|
||||
} else {
|
||||
my $new_email = $user . '@' . $wilddomain;
|
||||
($rv, $realemail) = find_real_address ($new_email);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ($rv, $realemail);
|
||||
else {
|
||||
$logger->debug("No domain level alias present for $domain / $email / $user");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ($rv, $realemail);
|
||||
}
|
||||
|
||||
# sends the vacation mail to the original sender.
|
||||
#
|
||||
sub send_vacation_email {
|
||||
my ($email, $orig_from, $orig_to, $orig_messageid) = @_;
|
||||
my $query = qq{SELECT subject,body FROM vacation WHERE email=?};
|
||||
my $stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"email='$email'");
|
||||
my $rv = $stm->rows;
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
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", "VACATION SUBJECT: $row[0]\n", "VACATION BODY: $row[1]\n");
|
||||
|
||||
# do_mail(from, to, subject, body);
|
||||
do_mail ($email, $orig_from, $row[0], $row[1]);
|
||||
do_log ($orig_messageid, $orig_to, $orig_from, '');
|
||||
}
|
||||
my ($email, $orig_from, $orig_to, $orig_messageid, $test_mode) = @_;
|
||||
my $logger = get_logger();
|
||||
$logger->debug("Asked to send vacation reply to $email thanks to $orig_messageid");
|
||||
my $query = qq{SELECT subject,body FROM vacation WHERE email=?};
|
||||
my $stm = $dbh->prepare($query) or panic_prepare($query);
|
||||
$stm->execute($email) or panic_execute($query,"email='$email'");
|
||||
my $rv = $stm->rows;
|
||||
if ($rv == 1) {
|
||||
my @row = $stm->fetchrow_array;
|
||||
if (already_notified($email, $orig_from) == 1) {
|
||||
$logger->debug("Already notified $email, or some error prevented us from doing so");
|
||||
return;
|
||||
}
|
||||
|
||||
$logger->debug("Will send vacation response for $orig_messageid: FROM: $email (orig_to: $orig_to), TO: $orig_from; VACATION SUBJECT: $row[0] ; VACATION BODY: $row[1]");
|
||||
my $subject = $row[0];
|
||||
my $body = $row[1];
|
||||
my $from = $email;
|
||||
my $to = $orig_from;
|
||||
my $vacation_subject = encode_mimewords($subject, 'Encoding'=> 'q', 'Charset'=>'utf-8', 'Field'=>'Subject');
|
||||
my %mail;
|
||||
%mail = (
|
||||
'smtp' => $smtp_server,
|
||||
'Subject' => $vacation_subject,
|
||||
'From' => $from,
|
||||
'To' => $to,
|
||||
'MIME-Version' => '1.0',
|
||||
'Content-Type' => 'text/plain; charset=UTF-8',
|
||||
'Content-Transfer-Encoding' => 'base64',
|
||||
'Precedence' => 'junk',
|
||||
'X-Loop' => 'Postfix Admin Virtual Vacation',
|
||||
'Message' => encode_base64($body)
|
||||
);
|
||||
if($test_mode == 1) {
|
||||
$logger->info("** TEST MODE ** : Vacation response sent to $to from $from subject $subject - NOT sent\n");
|
||||
$logger->info(%mail);
|
||||
return 0;
|
||||
}
|
||||
sendmail(%mail) or $logger->error("Failed to send vacation response: " . $Mail::Sendmail::error);
|
||||
$logger->debug("Vacation response sent, Mail::Sendmail said : " . $Mail::Sendmail::log);
|
||||
}
|
||||
}
|
||||
|
||||
sub strip_address {
|
||||
my $arg = shift;
|
||||
$arg =~ /([\w\-.%]+\@[\w.-]+)/;
|
||||
return lc($1);
|
||||
my ($arg) = @_;
|
||||
if(!$arg) {
|
||||
return '';
|
||||
}
|
||||
if($arg =~ /([\w\-.%]+\@[\w.-]+)/) {
|
||||
return lc($1);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
sub panic_prepare {
|
||||
my ($arg) = @_;
|
||||
my $logger = get_logger();
|
||||
$logger->error("Could not prepare sql statement: '$arg'");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
sub panic_execute {
|
||||
my ($arg,$param) = @_;
|
||||
my $logger = get_logger();
|
||||
$logger->error("Could not execute sql statement - '$arg' with parameters '$param'");
|
||||
exit(0);
|
||||
}
|
||||
########################### main #################################
|
||||
|
||||
my ($from, $to, $cc, ,$bcc , $subject, $messageid, $lastheader, $sender, $recipient, %opts, $sndrhdr, $spam);
|
||||
|
||||
$subject='';
|
||||
|
||||
# Take headers apart
|
||||
#
|
||||
while (<STDIN>) {
|
||||
last if (/^$/);
|
||||
if (/^\s+(.*)/ and $lastheader) { $$lastheader .= " $1"; }
|
||||
elsif (/^Return-Path:\s+(.*)\n$/i) { $sender = $1; $lastheader = \$sender; }
|
||||
elsif (/^Delivered-To:\s+(.*)\n$/i) { $recipient = $1; $lastheader = \$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; }
|
||||
elsif (/^x-spam-(flag|status):\s+yes/i) { do_debug("x-spam-$1: yes found"); exit (0); }
|
||||
elsif (/^precedence:\s+(bulk|list|junk)/i) { do_debug("precedence: $1 found"); exit (0); }
|
||||
elsif (/^x-loop:\s+postfix\ admin\ virtual\ vacation/i) { do_debug("x-loop: postfix admin virtual vacation found"); exit (0); }
|
||||
elsif (/^Auto-Submitted:\s+no/i) { next; }
|
||||
elsif (/^Auto-Submitted:/i) { do_debug("Auto-Submitted: something found"); exit (0); }
|
||||
elsif (/^List-(Id|Post):/i) { do_debug("List-$1: found"); exit (0); }
|
||||
elsif (/^Sender:\s+(.*)/i) { $sndrhdr = $1; $lastheader = \$sndrhdr; }
|
||||
else {$lastheader = "" ; }
|
||||
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; }
|
||||
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:/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 = "" ; }
|
||||
}
|
||||
|
||||
getopts('f:', \%opts) or die "Usage: $0 [-f sender] [-- [recipient]]";
|
||||
$opts{f} and $sender = $opts{f};
|
||||
$recipient = shift || $recipient || $ENV{"USER"} || "";
|
||||
|
||||
$smtp_recipient = shift || $smtp_recipient || $ENV{"USER"} || "";
|
||||
|
||||
# If either From: or To: are not set, exit
|
||||
if (!$from || !$to || !$messageid || !$sender || !$recipient) { do_debug("One of from=$from, to=$to, $messageid=$messageid, sender=$sender, recipient=$recipient is empty"); exit (0); }
|
||||
if ( $sender =~ /^(mailer-daemon|listserv|majordomo|owner-|request-|bounces-)/i) { do_debug("sender $sender contains $1"); exit (0); }
|
||||
if ( $sender =~ /-(owner|request|bounces)\@/i) { do_debug("sender $sender contains $1"); exit (0); }
|
||||
my $ss = strip_address($sender);
|
||||
my $sr = strip_address($recipient);
|
||||
my $ssh = strip_address($sndrhdr);
|
||||
if ($ss eq $sr) { do_debug("sender $ss and recipient $sr are the same"); exit(0); }
|
||||
if(!$from || !$to || !$messageid || !$smtp_sender || !$smtp_recipient) {
|
||||
$logger->info("One of from=$from, to=$to, messageid=$messageid, smtp sender=$smtp_sender, smtp recipient=$smtp_recipient empty");
|
||||
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);
|
||||
}
|
||||
|
||||
$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");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
my $recipfound = 0;
|
||||
for (split(/,\s*/, lc($to)), split(/,\s*/, lc($cc)), split(/,\s*/, lc($bcc))) {
|
||||
my $destinatario = strip_address($_);
|
||||
if ($ssh eq $destinatario) { do_debug("sender header $sender contains recipient $destinatario"); exit(0); }
|
||||
if ($sr eq $destinatario) { $recipfound++; }
|
||||
my $destinatario = strip_address($_);
|
||||
if ($sndrhdr eq $destinatario) {
|
||||
$logger->debug("sender header $sndrhdr 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)");
|
||||
exit (0);
|
||||
}
|
||||
if (!$recipfound) { do_debug("envelope recipient $sr not found in the header recipients"); exit (0); }
|
||||
|
||||
$from = lc ($from);
|
||||
|
||||
if (!Email::Valid->address($from,-mxcheck => 1)) { do_debug("Invalid from email address: $from; exiting."); exit(0); }
|
||||
if (!Email::Valid->address($ss,-mxcheck => 1)) { do_debug("Invalid sender email address: $ss; exiting."); exit(0); }
|
||||
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); }
|
||||
|
||||
# Check if it's an obvious sender, exit
|
||||
if ($from =~ /([\w\-.%]+\@[\w.-]+)/) { $from = $1; }
|
||||
if ($from eq "" || $from =~ /^(owner-|-(?:request|owner)\@|^(?:mailer-daemon|postmaster)\@)/i) { do_debug("from $from contains $1"); exit (0); }
|
||||
# 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 ($sr);
|
||||
my ($rv, $email) = find_real_address($smtp_recipient);
|
||||
$logger->debug("find_email_address gave: rv:$rv, email:$email");
|
||||
if ($rv == 1) {
|
||||
do_debug ("[FOUND VACATION]: ", $messageid, $sender, $recipient, $email);
|
||||
send_vacation_email( $email, $sender, $recipient, $messageid);
|
||||
$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");
|
||||
}
|
||||
|
||||
0;
|
||||
|
Loading…
Reference in New Issue
Block a user