Compare commits

..

11 Commits

Author SHA1 Message Date
cvs2svn e66a56154d This commit was manufactured by cvs2svn to create tag 'pymilter-0_8_9'.
Sprout from master 2007-09-25 17:07:32 UTC Stuart Gathman <stuart@gathman.org> 'Test on Centos5'
Cherrypick from bmsi 2005-05-31 18:23:49 UTC Stuart Gathman <stuart@gathman.org> 'Development changes since 0.7.2':
    rejects.py
    rhsbl.m4
    sample.py
    test/amazon
    test/big5
    test/bounce
    test/bounce1
    test/bound
    test/honey
    test/missingboundary
    test/samp1
    test/spam44
    test/spam7
    test/spam8
    test/test1
    test/test8
    test/virus1
    test/virus13
    test/virus2
    test/virus3
    test/virus4
    test/virus5
    test/virus6
    test/virus7
    testsample.py
2007-09-25 17:07:33 +00:00
Stuart Gathman 670e97cb79 Test on Centos5 2007-09-25 17:07:32 +00:00
Stuart Gathman 6397b7027f Tested on RH7 2007-09-25 16:37:26 +00:00
Stuart Gathman 94ce032559 Update license. 2007-09-25 02:26:29 +00:00
Stuart Gathman 91230381cb Test dns.py 2007-09-25 02:15:35 +00:00
Stuart Gathman 46ed3ddbcb Allow arbitrary object, not just spf.query like, to provide data for create_msg 2007-09-25 01:24:59 +00:00
Stuart Gathman 6048fe6e8c Remove explicit spf dependency. 2007-09-24 20:13:26 +00:00
Stuart Gathman d225384829 Create milter and milter-spf as noarch packages. 2007-09-24 18:00:58 +00:00
Stuart Gathman a84f6aa574 Specify library_dirs for Debian. 2007-09-24 17:44:51 +00:00
Stuart Gathman 344e8f0a0a Report domain on reputation reject. 2007-09-13 14:51:03 +00:00
Stuart Gathman 1fa4b72c84 Delete unparseable timestamps when loading address cache. These have
arisen because of failure to parse MAIL FROM properly.   Will have to
tighten up MAIL FROM parsing to match RFC.
2007-09-03 16:18:45 +00:00
13 changed files with 290 additions and 117 deletions
+12 -13
View File
@@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,7 +55,7 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -278,7 +278,7 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+2
View File
@@ -7,6 +7,8 @@ real, usable Python extension.
Other contributors (in random order):
Dwayne Litzenberger, B.A.Sc.
for library_dirs patch to compile on Debian
Dave MacQuigg
for noticing that smfi_insheader wasn't supported, and creating
a template to help first time pymilter users create their own milter.
+8 -1
View File
@@ -10,6 +10,9 @@
# CBV results.
#
# $Log$
# Revision 1.7 2007/01/25 22:47:26 customdesigned
# Persist blacklisting from delayed DSNs.
#
# Revision 1.6 2007/01/19 23:31:38 customdesigned
# Move parse_header to Milter.utils.
# Test case for delayed DSN parsing.
@@ -66,13 +69,17 @@ class AddrCache(object):
for ln in fp:
try:
rcpt,ts = ln.strip().split(None,1)
try:
l = time.strptime(ts,AddrCache.time_format)
t = time.mktime(l)
if t < too_old:
changed = True
continue
cache[rcpt.lower()] = (t,None)
except:
except: # unparsable timestamp - likely garbage
changed = True
continue
except: # manual entry (no timestamp)
cache[ln.strip().lower()] = (now,None)
wfp.write(ln)
if changed:
+88
View File
@@ -0,0 +1,88 @@
# provide a higher level interface to pydns
import DNS
from DNS import DNSError
MAX_CNAME = 10
def DNSLookup(name, qtype):
try:
req = DNS.DnsRequest(name, qtype=qtype)
resp = req.req()
#resp.show()
# key k: ('wayforward.net', 'A'), value v
# FIXME: pydns returns AAAA RR as 16 byte binary string, but
# A RR as dotted quad. For consistency, this driver should
# return both as binary string.
return [((a['name'], a['typename']), a['data']) for a in resp.answers]
except IOError, x:
raise DNSError, str(x)
class Session(object):
"""A Session object has a simple cache with no TTL that is valid
for a single "session", for example an SMTP conversation."""
def __init__(self):
self.cache = {}
# We have to be careful which additional DNS RRs we cache. For
# instance, PTR records are controlled by the connecting IP, and they
# could poison our local cache with bogus A and MX records.
SAFE2CACHE = {
('MX','A'): None,
('MX','MX'): None,
('CNAME','A'): None,
('CNAME','CNAME'): None,
('A','A'): None,
('AAAA','AAAA'): None,
('PTR','PTR'): None,
('TXT','TXT'): None,
('SPF','SPF'): None
}
def dns(self, name, qtype, cnames=None):
"""DNS query.
If the result is in cache, return that. Otherwise pull the
result from DNS, and cache ALL answers, so additional info
is available for further queries later.
CNAMEs are followed.
If there is no data, [] is returned.
pre: qtype in ['A', 'AAAA', 'MX', 'PTR', 'TXT', 'SPF']
post: isinstance(__return__, types.ListType)
"""
result = self.cache.get( (name, qtype) )
cname = None
if not result:
safe2cache = Session.SAFE2CACHE
for k, v in DNSLookup(name, qtype):
if k == (name, 'CNAME'):
cname = v
if (qtype,k[1]) in safe2cache:
self.cache.setdefault(k, []).append(v)
result = self.cache.get( (name, qtype), [])
if not result and cname:
if not cnames:
cnames = {}
elif len(cnames) >= MAX_CNAME:
#return result # if too many == NX_DOMAIN
raise DNSError('Length of CNAME chain exceeds %d' % MAX_CNAME)
cnames[name] = cname
if cname in cnames:
raise DNSError, 'CNAME loop'
result = self.dns(cname, qtype, cnames=cnames)
return result
DNS.DiscoverNameServers()
if __name__ == '__main__':
import sys
s = Session()
for n,t in zip(*[iter(sys.argv[1:])]*2):
print n,t
print s.dns(n,t)
+48 -23
View File
@@ -5,6 +5,12 @@
# Send DSNs, do call back verification,
# and generate DSN messages from a template
# $Log$
# Revision 1.15 2007/09/24 20:13:26 customdesigned
# Remove explicit spf dependency.
#
# Revision 1.14 2007/03/03 18:19:40 customdesigned
# Handle DNS error sending DSN.
#
# Revision 1.13 2007/01/04 18:01:11 customdesigned
# Do plain CBV when template missing.
#
@@ -19,22 +25,22 @@
#
import smtplib
import spf
import socket
from email.Message import Message
import Milter
import time
import dns
def send_dsn(mailfrom,receiver,msg=None,timeout=600):
def send_dsn(mailfrom,receiver,msg=None,timeout=600,session=None):
"""Send DSN. If msg is None, do callback verification.
Mailfrom is original sender we are sending DSN or CBV to.
Receiver is the MTA sending the DSN.
Return None for success or (code,msg) for failure."""
user,domain = mailfrom.split('@')
if not session: session = dns.Session()
try:
q = spf.query(None,None,None)
mxlist = q.dns(domain,'MX')
except spf.TempError:
mxlist = session.dns(domain,'MX')
except dns.DNSError:
return (450,'DNS Timeout: %s MX'%domain) # temp error
if not mxlist:
mxlist = (0,domain), # fallback to A record when no MX
@@ -86,23 +92,41 @@ def send_dsn(mailfrom,receiver,msg=None,timeout=600):
return (450,'No MX response within %f minutes'%(timeout/60.0))
return (450,'No MX servers available') # temp error
def create_msg(q,rcptlist,origmsg=None,template=None):
"Create a DSN message from a template. Template must be '\n' separated."
class Vars: pass
# NOTE: Caller can pass an object to create_msg that in a typical milter
# collects things like heloname or sender anyway.
def create_msg(v,rcptlist=None,origmsg=None,template=None):
"""Create a DSN message from a template. Template must be '\n' separated.
v - an object whose attributes are used for substitutions. Must
have sender and receiver attributes at a minimum.
rcptlist - used to set v.rcpt if given
origmsg - used to set v.subject and v.spf_result if given
template - a '\n' separated string with python '%(name)s' substitutions.
"""
if not template:
return None
heloname = q.h
sender = q.s
connectip = q.i
receiver = q.r
sender_domain = q.o
result = q.result
perm_error = q.perm_error
rcpt = '\n\t'.join(rcptlist)
try: subject = origmsg['Subject']
except: subject = '(none)'
if hasattr(v,'perm_error'):
# likely to be an spf.query, try translating for backward compatibility
q = v
v = Vars()
try:
spf_result = origmsg['Received-SPF']
except: spf_result = None
v.heloname = q.h
v.sender = q.s
v.connectip = q.i
v.receiver = q.r
v.sender_domain = q.o
v.result = q.result
v.perm_error = q.perm_error
except: v = q
if rcptlist:
v.rcpt = '\n\t'.join(rcptlist)
if origmsg:
try: v.subject = origmsg['Subject']
except: v.subject = '(none)'
try:
v.spf_result = origmsg['Received-SPF']
except: v.spf_result = None
msg = Message()
@@ -112,18 +136,19 @@ def create_msg(q,rcptlist,origmsg=None,template=None):
hdrs,body = template.split('\n\n',1)
for ln in hdrs.splitlines():
name,val = ln.split(':',1)
msg.add_header(name,(val % locals()).strip())
msg.set_payload(body % locals())
msg.add_header(name,(val % v.__dict__).strip())
msg.set_payload(body % v.__dict__)
# add headers if missing from old template
if 'to' not in msg:
msg.add_header('To',sender)
msg.add_header('To',v.sender)
if 'from' not in msg:
msg.add_header('From','postmaster@%s'%receiver)
msg.add_header('From','postmaster@%s'%v.receiver)
if 'auto-submitted' not in msg:
msg.add_header('Auto-Submitted','auto-generated')
return msg
if __name__ == '__main__':
import spf
q = spf.query('192.168.9.50',
'SRS0=pmeHL=RH==stuart@example.com',
'red.example.com',receiver='mail.example.com')
+4 -1
View File
@@ -1,4 +1,6 @@
Don't match dynamic ptr in bestguess.
Convert DSN to REJECT unless sender gets SPF pass or best guess pass. Make
configurable by SPF result with NOTSPAM policy (reject or deliver without DSN).
Maybe policy should be NODSN - still verify sender with CBV.
When content filtering is not installed, reject BLACKLISTed MFROM
immediately. There is no use waiting until EOM.
@@ -224,3 +226,4 @@ data structure as autowhitelist.log.
DONE Backup copies for outgoing/incoming mail.
DONE Don't match dynamic ptr in bestguess.
+16 -5
View File
@@ -1,6 +1,12 @@
#!/usr/bin/env python
# A simple milter that has grown quite a bit.
# $Log$
# Revision 1.112 2007/09/13 14:51:03 customdesigned
# Report domain on reputation reject.
#
# Revision 1.111 2007/07/25 17:14:59 customdesigned
# Move milter apps to /usr/lib/pymilter
#
# Revision 1.110 2007/07/02 03:06:10 customdesigned
# Ban ips on bad mailfrom offenses as well as bad rcpts.
#
@@ -277,6 +283,7 @@ milter_log = logging.getLogger('milter')
def read_config(list):
cp = MilterConfigParser({
'tempdir': "/var/log/milter/save",
'datadir': "/var/log/milter",
'socket': "/var/run/milter/pythonsock",
'timeout': '600',
'scan_html': 'no',
@@ -296,6 +303,7 @@ def read_config(list):
})
cp.read(list)
if cp.has_option('milter','datadir'):
print "chdir:",cp.get('milter','datadir')
os.chdir(cp.get('milter','datadir'))
# milter section
@@ -534,11 +542,8 @@ class SPFPolicy(object):
from Milter.cache import AddrCache
cbv_cache = AddrCache(renew=7)
cbv_cache.load('send_dsn.log',age=30)
auto_whitelist = AddrCache(renew=30)
auto_whitelist.load('auto_whitelist.log',age=120)
blacklist = AddrCache(renew=30)
blacklist.load('blacklist.log',age=60)
class bmsMilter(Milter.Milter):
"""Milter to replace attachments poisonous to Windows with a WARNING message,
@@ -846,6 +851,7 @@ class bmsMilter(Milter.Milter):
self.reputation = int(a[-2])
self.confidence = int(a[-1])
self.umis = umis
self.from_domain = domain
# We would like to reject on bad reputation here, but we
# need to give special consideration to postmaster. So
# we have to wait until envrcpt(). Perhaps an especially
@@ -1096,9 +1102,10 @@ class bmsMilter(Milter.Milter):
return Milter.REJECT
self.dspam = False
if userl != 'postmaster' and self.umis \
and self.reputation < -50 and self.confidence > 1:
and self.reputation < -50 and self.confidence > 3:
domain = self.from_domain
self.log('REJECT: REPUTATION, rcpt to',to,str)
self.setreply('550','5.7.1','Your domain has been sending mostly spam')
self.setreply('550','5.7.1','%s has been sending mostly spam'%domain)
return Milter.REJECT
if domain in hide_path:
@@ -1824,6 +1831,10 @@ def main():
if __name__ == "__main__":
read_config(["/etc/mail/pymilter.cfg","milter.cfg"])
cbv_cache.load('send_dsn.log',age=30)
auto_whitelist.load('auto_whitelist.log',age=120)
blacklist.load('blacklist.log',age=60)
if dspam_dict:
import dspam # low level spam check
if dspam_userdir:
+2 -2
View File
@@ -23,7 +23,7 @@ pidof() {
# Source function library.
. /etc/rc.d/init.d/functions
[ -x /var/log/milter/start.sh ] || exit 0
[ -x /usr/lib/pymilter/start.sh ] || exit 0
RETVAL=0
prog="milter"
@@ -36,7 +36,7 @@ start() {
mkdir -p /var/run/milter
chown mail:mail /var/run/milter
fi
daemon --check milter --user mail /var/log/milter/start.sh milter bms
daemon --check milter --user mail /usr/lib/pymilter/start.sh milter bms
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/milter
+2 -2
View File
@@ -23,7 +23,7 @@ pidof() {
# Source function library.
. /etc/rc.d/init.d/functions
[ -x /var/log/milter/start.sh ] || exit 0
[ -x /usr/lib/pymilter/start.sh ] || exit 0
RETVAL=0
prog="milter"
@@ -36,7 +36,7 @@ start() {
mkdir -p /var/run/milter
chown mail:mail /var/run/milter
fi
daemon --check milter --user mail /var/log/milter/start.sh milter bms
daemon --check milter --user mail /usr/lib/pymilter/start.sh milter bms
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/milter
+16 -12
View File
@@ -1,19 +1,20 @@
/* Copyright (C) 2001 James Niemira (niemira@colltech.com, urmane@urmane.org)
* Portions Copyright (C) 2001,2002,2003,2004 Stuart Gathman (stuart@bmsi.com)
* Portions Copyright (C) 2001,2002,2003,2004,2005,2006,2007
* Stuart Gathman (stuart@bmsi.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* milterContext object and thread interface contributed by
* Stuart D. Gathman <stuart@bmsi.com>
@@ -34,6 +35,9 @@ $ python setup.py help
libraries=["milter","smutil","resolv"]
* $Log$
* Revision 1.10 2006/02/12 02:00:42 customdesigned
* Resolve FIXME for wrap_close.
*
* Revision 1.9 2005/12/23 21:46:36 customdesigned
* Compile on sendmail-8.12 (ifdef SMFIR_INSHEADER)
*
+78 -44
View File
@@ -1,5 +1,4 @@
%define name pymilter
%define version 0.8.8
%define version 0.8.9
%define release 1
# what version of RH are we building for?
%define redhat7 0
@@ -18,8 +17,9 @@
%define sysvinit milter.rc
%endif
# RH9, other systems (single ps line per process)
%ifos Linux
%ifos Linux # whether to use system default python?
%define python python
#define python python2.4
%else
%define python python
%endif
@@ -29,11 +29,17 @@
%define libdir /usr/lib/pymilter
%endif
Summary: Python interface to sendmail milter API
Name: %{name}
# This spec file contains 2 noarch packages in addition to the pymilter
# module. To compile all three, use:
# rpmbuild -ba --target=i386,noarch pymilter.spec
%ifarch noarch
Name: milter
Group: Applications/System
Summary: BMS spam and reputation milter
Version: %{version}
Release: %{release}
Source: %{name}-%{version}.tar.gz
Source: pymilter-%{version}.tar.gz
#Patch: %{name}-%{version}.patch
License: GPL
Group: Development/Libraries
@@ -42,22 +48,10 @@ Prefix: %{_prefix}
Vendor: Stuart D. Gathman <stuart@bmsi.com>
Packager: Stuart D. Gathman <stuart@bmsi.com>
Url: http://www.bmsi.com/python/milter.html
Requires: %{python} >= 2.4, sendmail >= 8.13
Requires: %{python} >= 2.4, pyspf >= 2.0.4, pymilter
%ifos Linux
Requires: chkconfig
%endif
BuildRequires: %{python}-devel >= 2.4, sendmail-devel >= 8.13
%description
This is a python extension module to enable python scripts to
attach to sendmail's libmilter functionality. Additional python
modules provide for navigating and modifying MIME parts, sending
DSNs, and doing CBV.
%package -n milter
Group: Applications/System
Summary: BMS spam and reputation milter
Requires: pyspf >= 2.0.4
%description -n milter
A complex but effective spam filtering, SPF checking, and reputation tracking
@@ -66,28 +60,19 @@ mail application. It uses pydspam if installed for bayesian filtering.
%package spf
Group: Applications/System
Summary: BMS spam and reputation milter
Requires: pyspf >= 2.0.4
Requires: pyspf >= 2.0.4, pymilter
Obsoletes: pymilter-spf
%description spf
A simple mail filter to add Received-SPF headers and reject forged mail.
Rejection policy is configured via sendmail access file.
%prep
%setup
%setup -n pymilter-%{version}
#patch -p0 -b .bms
%build
%if %{redhat7}
LDFLAGS="-s"
%else # Redhat builds debug packages after 7.3
LDFLAGS="-g"
%endif
env CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$LDFLAGS" %{python} setup.py build
%install
rm -rf $RPM_BUILD_ROOT
%{python} setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
grep '.pyc$' INSTALLED_FILES | sed -e 's/c$/o/' >>INSTALLED_FILES
mkdir -p $RPM_BUILD_ROOT/var/log/milter
mkdir -p $RPM_BUILD_ROOT/etc/mail
mkdir $RPM_BUILD_ROOT/var/log/milter/save
@@ -135,7 +120,7 @@ cd /var/log/milter
#export PYTHONPATH=/usr/local/lib/python2.1/site-packages
exec /usr/local/bin/python bms.py >>milter.log 2>&1
EOF
%else
%else # not aix4.1
cp start.sh $RPM_BUILD_ROOT%{libdir}
mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
cp %{sysvinit} $RPM_BUILD_ROOT/etc/rc.d/init.d/milter
@@ -164,7 +149,7 @@ python="%{python}"
w
q
EOF
%endif
%endif # aix4.1
chmod a+x $RPM_BUILD_ROOT%{libdir}/start.sh
mkdir -p $RPM_BUILD_ROOT/var/run/milter
@@ -179,7 +164,7 @@ mkssys -s milter -p %{libdir}/start.sh -u 25 -S -n 15 -f 9 -G mail || :
if [ $1 = 0 ]; then
rmssys -s milter || :
fi
%else
%else # not aix4.1
%post -n milter
#echo "pythonsock has moved to /var/run/milter, update /etc/mail/sendmail.cf"
/sbin/chkconfig --add milter
@@ -196,20 +181,14 @@ fi
if [ $1 = 0 ]; then
/sbin/chkconfig --del spfmilter
fi
%endif
%endif # aix4.1
%clean
rm -rf $RPM_BUILD_ROOT
%files -f INSTALLED_FILES
%files
%defattr(-,root,root)
%doc README HOWTO ChangeLog NEWS TODO CREDITS sample.py milter-template.py
%config %{libdir}/start.sh
%files -n milter
%defattr(-,root,root)
/etc/logrotate.d/milter
/etc/cron.daily/milter
%{libdir}/bms.py?
%ifos aix4.1
%defattr(-,smmsp,mail)
%else
@@ -219,7 +198,6 @@ rm -rf $RPM_BUILD_ROOT
%dir /var/log/milter
%dir /var/log/milter/save
%config %{libdir}/bms.py
%{libdir}/bms.py?
%config(noreplace) /var/log/milter/strike3.txt
%config(noreplace) /var/log/milter/softfail.txt
%config(noreplace) /var/log/milter/fail.txt
@@ -236,7 +214,63 @@ rm -rf $RPM_BUILD_ROOT
%config(noreplace) /etc/mail/spfmilter.cfg
/etc/rc.d/init.d/spfmilter
%else # not noarch
%define name pymilter
Summary: Python interface to sendmail milter API
Name: %{name}
Version: %{version}
Release: %{release}
Source: %{name}-%{version}.tar.gz
#Patch: %{name}-%{version}.patch
License: GPL
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-buildroot
Prefix: %{_prefix}
Vendor: Stuart D. Gathman <stuart@bmsi.com>
Packager: Stuart D. Gathman <stuart@bmsi.com>
Url: http://www.bmsi.com/python/milter.html
Requires: %{python} >= 2.4, sendmail >= 8.13
BuildRequires: %{python}-devel >= 2.4, sendmail-devel >= 8.13
%description
This is a python extension module to enable python scripts to
attach to sendmail's libmilter functionality. Additional python
modules provide for navigating and modifying MIME parts, sending
DSNs, and doing CBV.
%prep
%setup
#patch -p0 -b .bms
%build
%if %{redhat7}
LDFLAGS="-s"
%else # Redhat builds debug packages after 7.3
LDFLAGS="-g"
%endif
env CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$LDFLAGS" %{python} setup.py build
%install
rm -rf $RPM_BUILD_ROOT
%{python} setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
%if !%{redhat7}
grep '.pyc$' INSTALLED_FILES | sed -e 's/c$/o/' >>INSTALLED_FILES
%endif
%files -f INSTALLED_FILES
%defattr(-,root,root)
%doc README HOWTO ChangeLog NEWS TODO CREDITS sample.py milter-template.py
%endif # noarch
%clean
rm -rf $RPM_BUILD_ROOT
%changelog
* Mon Sep 24 2007 Stuart Gathman <stuart@bmsi.com> 0.8.9-1
- Use %ifarch hack to build milter and milter-spf packages as noarch
- Remove spf dependency from dsn.py, add dns.py
* Fri Jan 05 2007 Stuart Gathman <stuart@bmsi.com> 0.8.8-1
- move AddrCache, parse_addr, iniplist to Milter package
- move parse_header to Milter.utils
+3 -1
View File
@@ -6,6 +6,7 @@ from distutils.core import setup, Extension
# on slackware and debian, leave it out entirely. It depends
# on how libmilter was built by the sendmail package.
libs = ["milter", "smutil"]
libdirs = ["/usr/lib/libmilter"] # needed for Debian
# patch distutils if it can't cope with the "classifiers" or
# "download_url" keywords
@@ -15,7 +16,7 @@ if sys.version < '2.2.3':
DistributionMetadata.download_url = None
# NOTE: importing Milter to obtain version fails when milter.so not built
setup(name = "pymilter", version = '0.8.8',
setup(name = "pymilter", version = '0.8.9',
description="Python interface to sendmail milter API",
long_description="""\
This is a python extension module to enable python scripts to
@@ -33,6 +34,7 @@ sending DSNs or doing CBVs.
packages = ['Milter'],
ext_modules=[
Extension("milter", ["miltermodule.c"],
library_dirs=libdirs,
libraries=libs,
# set MAX_ML_REPLY to 1 for sendmail < 8.13
define_macros = [ ('MAX_ML_REPLY',32) ]
+1 -3
View File
@@ -10,7 +10,5 @@ else
cd /usr/lib/pymilter
fi
cd /var/log/milter
exec >>${appname}.log 2>&1
${python} ${appname}.py &
${python} ${script}.py &
echo $! >/var/run/milter/${appname}.pid