Compare commits

..

1 Commits

Author SHA1 Message Date
cvs2svn adf2ca0487 This commit was manufactured by cvs2svn to create tag 'milter-0_8_0'.
Sprout from bmsi 2005-05-31 18:23:49 UTC Stuart Gathman <stuart@gathman.org> 'Development changes since 0.7.2'
Cherrypick from master 2005-06-06 18:24:59 UTC Stuart Gathman <stuart@gathman.org> 'Properly log exceptions from pydspam':
    COPYING
    MANIFEST.in
    Milter/__init__.py
    Milter/dsn.py
    Milter/dynip.py
    NEWS
    TODO
    bms.py
    milter.cfg
    milter.html
    milter.spec
    miltermodule.c
    mime.py
    setup.cfg
    setup.py
    softfail.txt
    spf.py
    spfquery.py
    strike3.txt
    test/zip1
    testmime.py
2005-06-06 18:25:00 +00:00
14 changed files with 53 additions and 190 deletions
+11 -22
View File
@@ -141,28 +141,16 @@ def closecallback(ctx):
m._setctx(None) # release milterContext m._setctx(None) # release milterContext
return rc return rc
def dictfromlist(args):
"Convert ESMTP parm list to keyword dictionary."
kw = {}
for s in args:
pos = s.find('=')
if pos > 0:
kw[s[:pos].upper()] = s[pos+1:]
return kw
def envcallback(c,args): def envcallback(c,args):
"""Call function c with ESMTP parms converted to keyword parameters. """Convert ESMTP parms to keyword parameters.
Can be used in the envfrom and/or envrcpt callbacks to process Can be used in the envfrom and/or envrcpt callbacks to process
ESMTP parameters as python keyword parameters.""" ESMTP parameters as python keyword parameters."""
kw = {} kw = {}
pargs = [args[0]]
for s in args[1:]: for s in args[1:]:
pos = s.find('=') pos = s.find('=')
if pos > 0: if pos > 0:
kw[s[:pos].upper()] = s[pos+1:] kw[s[:pos]] = s[pos+1:]
else: return apply(c,args,kw)
pargs.append(s)
return c(*pargs,**kw)
def runmilter(name,socketname,timeout = 0): def runmilter(name,socketname,timeout = 0):
# This bit is here on the assumption that you will be starting this filter # This bit is here on the assumption that you will be starting this filter
@@ -189,13 +177,14 @@ def runmilter(name,socketname,timeout = 0):
# milter.set_flags(milter.ADDHDRS) # milter.set_flags(milter.ADDHDRS)
milter.set_connect_callback(connectcallback) milter.set_connect_callback(connectcallback)
milter.set_helo_callback(lambda ctx, host: ctx.getpriv().hello(host)) milter.set_helo_callback(lambda ctx, host: ctx.getpriv().hello(host))
# For envfrom and envrcpt, we would like to convert ESMTP parms to keyword milter.set_envfrom_callback(lambda ctx,*str:
# parms, but then all existing users would have to include **kw to accept ctx.getpriv().envfrom(*str))
# arbitrary keywords without crashing. We do provide envcallback and # envcallback(ctx.getpriv().envfrom,str))
# dictfromlist to make parsing the ESMTP args convenient. milter.set_envrcpt_callback(lambda ctx,*str:
milter.set_envfrom_callback(lambda ctx,*str: ctx.getpriv().envfrom(*str)) ctx.getpriv().envrcpt(*str))
milter.set_envrcpt_callback(lambda ctx,*str: ctx.getpriv().envrcpt(*str)) # envcallback(ctx.getpriv().envrcpt,str))
milter.set_header_callback(lambda ctx,fld,val: ctx.getpriv().header(fld,val)) milter.set_header_callback(lambda ctx,fld,val:
ctx.getpriv().header(fld,val))
milter.set_eoh_callback(lambda ctx: ctx.getpriv().eoh()) milter.set_eoh_callback(lambda ctx: ctx.getpriv().eoh())
milter.set_body_callback(lambda ctx,chunk: ctx.getpriv().body(chunk)) milter.set_body_callback(lambda ctx,chunk: ctx.getpriv().body(chunk))
milter.set_eom_callback(lambda ctx: ctx.getpriv().eom()) milter.set_eom_callback(lambda ctx: ctx.getpriv().eom())
+5 -8
View File
@@ -95,10 +95,7 @@ Received-SPF: %(spf_result)s
""" """
def send_dsn(mailfrom,receiver,msg=None): def send_dsn(mailfrom,receiver,msg=None):
"""Send DSN. If msg is None, do callback verification. "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('@') user,domain = mailfrom.split('@')
q = spf.query(None,None,None) q = spf.query(None,None,None)
mxlist = q.dns(domain,'MX') mxlist = q.dns(domain,'MX')
@@ -115,7 +112,7 @@ def send_dsn(mailfrom,receiver,msg=None):
if resp.split()[0] == receiver: if resp.split()[0] == receiver:
return (553,'Fraudulent MX for %s' % domain) return (553,'Fraudulent MX for %s' % domain)
if not (200 <= code <= 299): if not (200 <= code <= 299):
raise smtplib.SMTPHeloError(code, resp) raise SMTPHeloError(code, resp)
if msg: if msg:
try: try:
smtp.sendmail('<>',mailfrom,msg) smtp.sendmail('<>',mailfrom,msg)
@@ -125,7 +122,7 @@ def send_dsn(mailfrom,receiver,msg=None):
else: # CBV else: # CBV
code,resp = smtp.docmd('MAIL FROM: <>') code,resp = smtp.docmd('MAIL FROM: <>')
if code != 250: if code != 250:
raise smtplib.SMTPSenderRefused(code, resp, '<>') raise SMTPSenderRefused(code, resp, '<>')
code,resp = smtp.rcpt(mailfrom) code,resp = smtp.rcpt(mailfrom)
if code not in (250,251): if code not in (250,251):
return (code,resp) # permanent error return (code,resp) # permanent error
@@ -134,9 +131,9 @@ def send_dsn(mailfrom,receiver,msg=None):
except smtplib.SMTPRecipientsRefused,x: except smtplib.SMTPRecipientsRefused,x:
return x.recipients[mailfrom] # permanent error return x.recipients[mailfrom] # permanent error
except smtplib.SMTPSenderRefused,x: except smtplib.SMTPSenderRefused,x:
return x.args[:2] # does not accept DSN return x # does not accept DSN
except smtplib.SMTPDataError,x: except smtplib.SMTPDataError,x:
return x.args # permanent error return x # permanent error
except smtplib.SMTPException: except smtplib.SMTPException:
pass # any other error, try next MX pass # any other error, try next MX
except socket.error: except socket.error:
-5
View File
@@ -1,16 +1,11 @@
Here is a history of user visible changes to Python milter. Here is a history of user visible changes to Python milter.
0.8.1 Fix zip in zip loop in mime.py
Fix HeaderParseError in bms.py header callback
Check internal_domains for outgoing mail
Fix inconsistent results from send_dsn
0.8.0 Move Milter module to subpackage. 0.8.0 Move Milter module to subpackage.
DSN support for Three strikes rule and SPF SOFTFAIL DSN support for Three strikes rule and SPF SOFTFAIL
Move /*mime*/ and dynip to Milter subpackage Move /*mime*/ and dynip to Milter subpackage
Fix SPF unknown mechanism list not cleared Fix SPF unknown mechanism list not cleared
Make banned extensions configurable. Make banned extensions configurable.
Option to scan zipfiles for bad extensions. Option to scan zipfiles for bad extensions.
Properly log pydspam exceptions
0.7.3 Experimental release with python2.4 support 0.7.3 Experimental release with python2.4 support
0.7.2 Return unknown for invalid ip address in mechanism 0.7.2 Return unknown for invalid ip address in mechanism
Recognize dynamic PTR names, and don't count them as authentication. Recognize dynamic PTR names, and don't count them as authentication.
+2 -23
View File
@@ -1,15 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
# A simple milter that has grown quite a bit. # A simple milter that has grown quite a bit.
# $Log$ # $Log$
# Revision 1.10 2005/06/16 18:35:51 customdesigned
# Ignore HeaderParseError decoding header
#
# Revision 1.9 2005/06/14 21:55:29 customdesigned
# Check internal_domains for outgoing mail.
#
# Revision 1.8 2005/06/06 18:24:59 customdesigned
# Properly log exceptions from pydspam
#
# Revision 1.7 2005/06/04 19:41:16 customdesigned # Revision 1.7 2005/06/04 19:41:16 customdesigned
# Fix bugs from testing RPM # Fix bugs from testing RPM
# #
@@ -466,9 +457,9 @@ def parse_addr(t):
return t.split('@') return t.split('@')
def parse_header(val): def parse_header(val):
h = decode_header(val)
if not len(h) or (not h[0][1] and len(h) == 1): return val
try: try:
h = decode_header(val)
if not len(h) or (not h[0][1] and len(h) == 1): return val
u = [] u = []
for s,enc in h: for s,enc in h:
if enc: if enc:
@@ -485,7 +476,6 @@ def parse_header(val):
except UnicodeError: continue except UnicodeError: continue
except UnicodeDecodeError: pass except UnicodeDecodeError: pass
except LookupError: pass except LookupError: pass
except email.errors.HeaderParseError: pass
return val return val
class bmsMilter(Milter.Milter): class bmsMilter(Milter.Milter):
@@ -630,17 +620,6 @@ class bmsMilter(Milter.Milter):
self.log("REJECT: spam from self",pat) self.log("REJECT: spam from self",pat)
self.setreply('550','5.7.1','I hate talking to myself.') self.setreply('550','5.7.1','I hate talking to myself.')
return Milter.REJECT return Milter.REJECT
elif internal_domains:
for pat in internal_domains:
if fnmatchcase(domain,pat): break
else:
self.log("REJECT: zombie PC at ",self.connectip," sending MAIL FROM ",
self.canon_from)
self.setreply('550','5.7.1','Get rid of your virus!',
'Your PC is using an unauthorized MAIL FROM.',
'It is either badly misconfigured or controlled by organized crime.'
)
return Milter.REJECT
self.rejectvirus = domain in reject_virus_from self.rejectvirus = domain in reject_virus_from
if user in wiretap_users.get(domain,()): if user in wiretap_users.get(domain,()):
self.add_recipient(wiretap_dest) self.add_recipient(wiretap_dest)
+4 -12
View File
@@ -72,9 +72,6 @@ milter-0.4.5 or later to remove this dependency.
<code>set_flags()</code> before calling <code>runmilter()</code>. For <code>set_flags()</code> before calling <code>runmilter()</code>. For
instance, <code>Milter.set_flags(Milter.ADDRCPT)</code>. You must add together instance, <code>Milter.set_flags(Milter.ADDRCPT)</code>. You must add together
all of <code>ADDHDRS, CHGBODY, ADDRCPT, DELRCPT, CHGHDRS</code> that apply. all of <code>ADDHDRS, CHGBODY, ADDRCPT, DELRCPT, CHGHDRS</code> that apply.
<p> NOTE - recent versions default flags to enabling all features. You
must now call <code>set_flags()</code> if you wish to disable features for
efficiency.
<p> <p>
<li> Q. Why does sendmail sometimes print something like: <li> Q. Why does sendmail sometimes print something like:
@@ -97,19 +94,14 @@ for your specific needs. We will of course continue to move generic
code out of the sample as the project evolves. Think of sample.py as code out of the sample as the project evolves. Think of sample.py as
an active config file. an active config file.
<p> <p>
If you are running bms.py, then the block_chinese option in
<code>/etc/mail/pymilter.cfg</code> controls this feature.
<p>
<li> Q. Why does sendmail coredump with milters on OpenBSD? <li> Q. Why does sendmail coredump with milters on OpenBSD?
<p> A. Sendmail has a problem with unix sockets on old versions of OpenBSD. <p> A. Sendmail has a problem with unix sockets on OpenBSD. Use
Use an internet domain socket instead. For example, in an internet domain socket instead. For example, in <code>sendmail.cf</code> use
<code>sendmail.cf</code> use
<pre> <pre>
Xpythonfilter, S=inet:1234@localhost Xpythonfilter, S=inet:1234@localhost
</pre> </pre>
and change sample.py accordingly. and change sample.py accordingly.
<p> OpenBSD users report that this problem has been fixed.
<p> <p>
<li> Q. How can I change the bounce message for an invalid recipient? <li> Q. How can I change the bounce message for an invalid recipient?
@@ -151,8 +143,8 @@ everything up for you. For other systems:
<li> Arrange to run bms.py in the background (as a service perhaps) and <li> Arrange to run bms.py in the background (as a service perhaps) and
redirect output and errors to a logfile. For instance, on AIX you'll want redirect output and errors to a logfile. For instance, on AIX you'll want
to use SRC (System Resource Controller). to use SRC (System Resource Controller).
<li> Copy pymilter.cfg to the /etc/mail or the directory you run bms.py in, <li> Copy milter.cfg to the directory you run bms.py in, and edit it. The
and edit it. The comments should explain the options. comments should explain the options.
<li> Start bms.py in the background as arranged. <li> Start bms.py in the background as arranged.
<li> Add Xpythonfilter to sendmail.cf or add an INPUT_MAIL_FILTER to <li> Add Xpythonfilter to sendmail.cf or add an INPUT_MAIL_FILTER to
sendmail.mc. Regen sendmail.cf if you use sendmail.mc and restart sendmail.mc. Regen sendmail.cf if you use sendmail.mc and restart
+8 -13
View File
@@ -1,29 +1,25 @@
[milter] [milter]
# the socket used to communicate with sendmail. Must match sendmail.cf # the socket used to communicate with sendmail. Must match sendmail.cf
socket=/var/run/milter/pythonsock ;socket=/var/run/milter/pythonsock
# where to save original copies of defanged and failed messages # where to save original copies of defanged and failed messages
tempdir = /var/log/milter/save tempdir = /var/log/milter/save
# how long to wait for a response from sendmail before giving up # how long to wait for a response from sendmail before giving up
;timeout=600 ;timeout=600
log_headers = 0 log_headers = 0
# connection ips and hostnames are matched against this glob style list # connection ips and hostnames are matched against this glob style list
# to recognize internal senders. # to recognize internal senders
;internal_connect = 192.168.*.* ;internal_connect = 192.168.*.*
# mail that is not an internal_connect and claims to be from an # mail that is not an internal_connect and claims to be from an
# internal domain is rejected. Furthermore, internal mail that # internal domain is rejected. You should enable SPF instead if you can.
# does not claim to be from an internal domain is rejected. # SPF is much more comprehensive and flexible.
# You should enable SPF instead if you can. SPF is much more comprehensive and
# flexible. However, SPF is not currently checked for outgoing
# (internal_connect) mail because it doesn't yet handle authorizing
# internal IPs locally.
;internal_domains = mycorp.com ;internal_domains = mycorp.com
# connections from a trusted relay can trust the first Received header # connections from a trusted relay can trust the first Received header
# SPF checks are bypassed for internal connections and trusted relays. # SPF checks are bypassed for internal connections and trusted relays.
;trusted_relay = 1.2.3.4, 66.12.34.56 ;trusted_relay = 1.2.3.4, 66.12.34.56
# Reject external senders with hello names no legit external sender would use. # reject external senders with hello names no legit external sender would use
# SPF will do this also, but listing your own domain and mailserver here # SPF will do this also, but listing your own domain and mailserver here
# will save some DNS lookups when rejecting certain viruses. # will save some DNS lookups when rejecting certain viruses.
;hello_blacklist = mycorp.com, 66.12.34.56 ;hello_blacklist = mycorp.com, 66.12.34.56
@@ -50,7 +46,7 @@ porn_words = penis, breast, pussy, horse cock, porn, xenical, diet pill, d1ck,
p-e-n-i-s, hydrocodone, vicodin, xanax, vicod1n, x@nax, diazepam, p-e-n-i-s, hydrocodone, vicodin, xanax, vicod1n, x@nax, diazepam,
v1@gra, xan@x, cialis, ci@lis, frëe, xãnax, valíum, vãlium, via-gra, v1@gra, xan@x, cialis, ci@lis, frëe, xãnax, valíum, vãlium, via-gra,
x@n3x, vicod3n, penís, c0d1n, phentermine, en1arge, dip1oma, v1codin, x@n3x, vicod3n, penís, c0d1n, phentermine, en1arge, dip1oma, v1codin,
valium, rolex, sexual, fuck valium, rolex, sexual
# reject mail with these case sensitive strings in the subject # reject mail with these case sensitive strings in the subject
spam_words = $$$, !!!, XXX, FREE, HGH spam_words = $$$, !!!, XXX, FREE, HGH
# attachments with these extensions will be replaced with a warning # attachments with these extensions will be replaced with a warning
@@ -80,10 +76,9 @@ reject_spoofed = 0
;reject_neutral = aol.com ;reject_neutral = aol.com
# use a default (v=spf1 a/24 mx/24 ptr) when no SPF records are published # use a default (v=spf1 a/24 mx/24 ptr) when no SPF records are published
;best_guess = 0 ;best_guess = 0
# Reject senders that have neither PTR nor valid HELO nor SPF records, or send # reject senders that have neither PTR nor SPF records, or DSN if false
# DSN otherwise
;reject_noptr = 0 ;reject_noptr = 0
# always accept softfail from these domains, or send DSN otherwise # always accept softfail from these domains, or DSN otherwise
;accept_softfail = bounces.amazon.com ;accept_softfail = bounces.amazon.com
# features intended to clean up outgoing mail # features intended to clean up outgoing mail
+8 -19
View File
@@ -24,13 +24,11 @@ ALT="Viewable With Any Browser" BORDER="0"></A>
Stuart D. Gathman</a><br> Stuart D. Gathman</a><br>
This web page is written by Stuart D. Gathman<br>and<br>sponsored by This web page is written by Stuart D. Gathman<br>and<br>sponsored by
<a href="http://www.bmsi.com">Business Management Systems, Inc.</a> <br> <a href="http://www.bmsi.com">Business Management Systems, Inc.</a> <br>
Last updated Jun 09, 2005</h4> Last updated May 31, 2005</h4>
See the <a href="faq.html">FAQ</a> | <a href="http://sourceforge.net/project/showfiles.php?group_id=139894">Download now</a> | See the <a href="faq.html">FAQ</a> | <a href="http://sourceforge.net/project/showfiles.php?group_id=139894">Download now</a> |
<a href="/mailman/listinfo/pymilter">Subscribe to mailing list</a> | <a href="/mailman/listinfo/pymilter">Subscribe to mailing list</a> |
<a href="#overview">Overview</a> | <a href="#overview">Overview</a>
<a href="/python/dspam.html">pydspam</a> |
<a href="/libdspam/dspam.html">libdspam</a>
<p> <p>
<a href="//www.python.org"> <a href="//www.python.org">
<img src="python55.gif" align=left alt="A Python"></a> <img src="python55.gif" align=left alt="A Python"></a>
@@ -41,26 +39,17 @@ provides a python interface to libmilter that exploits all its features.
<p> <p>
Sendmail 8.12 officially releases libmilter. Sendmail 8.12 officially releases libmilter.
Version 8.12 seems to be more robust, and includes new privilege Version 8.12 seems to be more robust, and includes new privilege
separation features to enhance security. Even better, sendmail 8.13 separation features to enhance security.
supports socket maps, which makes <a href="pysrs.html">pysrs</a> much more I recommend upgrading.
efficient and secure. I recommend upgrading.
<h2> Recent Changes </h2> <h2> Recent Changes </h2>
Python milter is being moved to Python milter is being moved to
<a href="http://sourceforge.net/projects/pymilter/">pymilter Sourceforge <a href="http://sourceforge.net/projects/pymilter/">Sourceforge</a> for
project</a> for development. development.
<p>
Release 0.8.0 is the first <a href="http://sourceforge.net/">Sourceforge</a>
release. It supports Python-2.4, and provides an option to accept mail
that gets an SPF softfail or fails the 3 strikes rule, provided the
alleged sender accepts a DSN explaining the problem. Python-2.3 is
no longer supported by the reworked mime.py module, although API changes
could be backported. There are too many incompatible changes to the
python email package.
<p> <p>
Release 0.7.2 tightens the authentication screws with a "3 strikes and Release 0.7.2 tightens the authentication screws with a "3 strikes and
you're out" policy. A sender must have a valid PTR, HELO, or SPF record your out" policy. A sender must have a valid PTR, HELO, or SPF record
to send email. Specific senders can be whitelisted using the to send email. Specific senders can be whitelisted using the
"delegate" option in the spf configuration section by adding a "delegate" option in the spf configuration section by adding a
default SPF record for them. The PTR and HELO are required default SPF record for them. The PTR and HELO are required
+2 -9
View File
@@ -1,6 +1,6 @@
%define name milter %define name milter
%define version 0.8.1 %define version 0.8.0
%define release 1.RH7 %define release 3.RH7
# what version of RH are we building for? # what version of RH are we building for?
%define redhat9 0 %define redhat9 0
%define redhat7 1 %define redhat7 1
@@ -166,13 +166,6 @@ rm -rf $RPM_BUILD_ROOT
/usr/share/sendmail-cf/hack/rhsbl.m4 /usr/share/sendmail-cf/hack/rhsbl.m4
%changelog %changelog
* Thu Jun 16 2005 Stuart Gathman <stuart@bmsi.com> 0.8.1-1
- Fix zip in zip loop in mime.py
- Fix HeaderParseError in bms.py header callback
- Check internal_domains for outgoing mail
- Fix inconsistent results from send_dsn
* Mon Jun 06 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-3
- properly log pydspam exceptions
* Sat Jun 04 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-2 * Sat Jun 04 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-2
- Include default softfail, strike3 templates - Include default softfail, strike3 templates
* Wed May 25 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-1 * Wed May 25 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-1
+5 -15
View File
@@ -1,7 +1,4 @@
# $Log$ # $Log$
# Revision 1.3 2005/06/02 15:00:17 customdesigned
# Configure banned extensions. Scan zipfile option with test case.
#
# Revision 1.2 2005/06/02 04:18:55 customdesigned # Revision 1.2 2005/06/02 04:18:55 customdesigned
# Update copyright notices after reading article on /. # Update copyright notices after reading article on /.
# #
@@ -90,16 +87,6 @@ from email import Errors
from types import ListType,StringType from types import ListType,StringType
def zipnames(txt):
fp = StringIO.StringIO(txt)
zipf = zipfile.ZipFile(fp,'r')
names = []
for nm in zipf.namelist():
names.append(('zipname',nm))
if nm.lower().endswith('.zip'):
names += zipnames(zipf.read(nm))
return names
class MimeGenerator(Generator): class MimeGenerator(Generator):
def _dispatch(self, msg): def _dispatch(self, msg):
# Get the Content-Type: for the message, then try to dispatch to # Get the Content-Type: for the message, then try to dispatch to
@@ -190,10 +177,13 @@ class MimeMessage(Message):
names.append((attr,val)) names.append((attr,val))
names += [("filename",self.get_filename())] names += [("filename",self.get_filename())]
if scan_zip: if scan_zip:
for key,name in tuple(names): # copy by converting to tuple for key,name in names:
if name and name.lower().endswith('.zip'): if name and name.lower().endswith('.zip'):
txt = self.get_payload(decode=True) txt = self.get_payload(decode=True)
names += zipnames(txt) fp = StringIO.StringIO(txt)
zipf = zipfile.ZipFile(fp,'r')
for nm in zipf.namelist():
names.append(('zipname',nm))
return names return names
def ismodified(self): def ismodified(self):
+1 -1
View File
@@ -12,7 +12,7 @@ if sys.version < '2.2.3':
DistributionMetadata.classifiers = None DistributionMetadata.classifiers = None
DistributionMetadata.download_url = None DistributionMetadata.download_url = None
setup(name = "milter", version = "0.8.1", setup(name = "milter", version = "0.8.0",
description="Python interface to sendmail milter API", description="Python interface to sendmail milter API",
long_description="""\ long_description="""\
This is a python extension module to enable python scripts to This is a python extension module to enable python scripts to
+5 -7
View File
@@ -46,9 +46,6 @@ For news, bugfixes, etc. visit the home page for this implementation at
# Terrence is not responding to email. # Terrence is not responding to email.
# #
# $Log$ # $Log$
# Revision 1.4 2005/06/02 04:18:55 customdesigned
# Update copyright notices after reading article on /.
#
# Revision 1.3 2005/06/02 02:08:12 customdesigned # Revision 1.3 2005/06/02 02:08:12 customdesigned
# Reject on PermErr # Reject on PermErr
# #
@@ -687,12 +684,13 @@ class query(object):
p = CIDParser(q=self) p = CIDParser(q=self)
try: try:
return p.spf_txt(domain) return p.spf_txt(domain)
except xml.sax._exceptions.SAXParseException: except xml.sax._exceptions.SAXParseException,x:
raise PermError("Caller-ID parse error",domain) raise PermError("Caller-ID parse error",domain)
if len(a) == 1: if len(a) == 1:
return a[0] return a[0]
return None else:
return None
def dns_txt(self, domainname): def dns_txt(self, domainname):
"Get a list of TXT records for a domain name." "Get a list of TXT records for a domain name."
@@ -976,12 +974,12 @@ def bin2addr(addr):
def expand_one(expansion, str, joiner): def expand_one(expansion, str, joiner):
if not str: if not str:
return expansion return expansion
ln, reverse, delimiters = RE_ARGS.split(str)[1:4] len, reverse, delimiters = RE_ARGS.split(str)[1:4]
if not delimiters: if not delimiters:
delimiters = '.' delimiters = '.'
expansion = split(expansion, delimiters, joiner) expansion = split(expansion, delimiters, joiner)
if reverse: expansion.reverse() if reverse: expansion.reverse()
if ln: expansion = expansion[-int(ln)*2+1:] if len: expansion = expansion[-int(len)*2+1:]
return ''.join(expansion) return ''.join(expansion)
def split(str, delimiters, joiner=None): def split(str, delimiters, joiner=None):
+1 -1
View File
@@ -23,7 +23,7 @@ SMTP (email) servers to prevent criminals from forging your
domain. The simplest step is usually to publish an SPF record domain. The simplest step is usually to publish an SPF record
with your Sender Policy. with your Sender Policy.
For more information, see: http://spf.pobox.com For more information, see: http://spfhelp.net
I hate to annoy you with a DSN (Delivery Status I hate to annoy you with a DSN (Delivery Status
Notification) from a possibly forged email, but since you Notification) from a possibly forged email, but since you
-47
View File
@@ -1,47 +0,0 @@
From ttaie1@thfalcon.com Thu Jun 16 10:23:13 2005
Received: from thfalcon.com (unknown [202.90.113.150])
by thfalcon.com (Postfix) with ESMTP id 32F0DD819C
for <stuart@bmsi.com>; Thu, 16 Jun 2005 15:42:08 +0700 (ICT)
From: ttaie1@thfalcon.com
To: stuart@bmsi.com
Subject: Returned mail: see transcript for details
Date: Thu, 16 Jun 2005 15:50:10 +0700
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_NextPart_000_0014_E4E04420.5619685C"
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 6.00.2600.0000
X-MIMEOLE: Produced By Microsoft MimeOLE V6.00.2600.0000
Message-Id: <20050616084208.32F0DD819C@thfalcon.com>
Received-SPF: pass (mail.bmsi.com: guessing: domain of thfalcon.com designates 203.147.3.44 as permitted sender) client-ip=203.147.3.44; envelope-from=ttaie1@thfalcon.com; helo=thfalcon.com;
This is a multi-part message in MIME format.
------=_NextPart_000_0014_E4E04420.5619685C
Content-Type: text/plain;
charset=us-ascii
Content-Transfer-Encoding: 7bit
Message could not be delivered
------=_NextPart_000_0014_E4E04420.5619685C
Content-Type: application/octet-stream;
name="stuart@bmsi.com.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="stuart@bmsi.com.zip"
UEsDBAoAAAAAAM6r0DL7SfbCBAEAAAQBAAAFABUAdC56aXBVVAkAA7MnskK4J7JCVXgEAIYD
ZQBQSwMECgAAAAAANVXCMtpXacQaAAAAGgAAADMAFQB6aXAuZG9jICAgICAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgICAgICAgIC5leGVVVAkAA6Yan0KmGp9CVXgEAIYDZQBUaGlz
IHByb2dyYW0gd2FzIGEgdmlydXMuClBLAQIXAwoAAAAAADVVwjLaV2nEGgAAABoAAAAzAA0A
AAAAAAEAAAC0gQAAAAB6aXAuZG9jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICAgICAgIC5leGVVVAUAA6Yan0JVeAAAUEsFBgAAAAABAAEAbgAAAIAAAAAAAFBLAQIXAwoA
AAAAAM6r0DL7SfbCBAEAAAQBAAAFAA0AAAAAAAAAAAC0gQAAAAB0LnppcFVUBQADsyeyQlV4
AABQSwUGAAAAAAEAAQBAAAAAPAEAAAAA
------=_NextPart_000_0014_E4E04420.5619685C--
+1 -8
View File
@@ -1,7 +1,4 @@
# $Log$ # $Log$
# Revision 1.2 2005/06/02 15:00:17 customdesigned
# Configure banned extensions. Scan zipfile option with test case.
#
# Revision 1.1.1.2 2005/05/31 18:23:49 customdesigned # Revision 1.1.1.2 2005/05/31 18:23:49 customdesigned
# Development changes since 0.7.2 # Development changes since 0.7.2
# #
@@ -129,12 +126,10 @@ class MimeTestCase(unittest.TestCase):
self.failUnless(name == "Jim&amp;amp;Girlz.jpg","name=%s"%name) self.failUnless(name == "Jim&amp;amp;Girlz.jpg","name=%s"%name)
def testZip(self,vname="zip1",fname='zip.zip'): def testZip(self,vname="zip1",fname='zip.zip'):
self.testDefang(vname,1,'zip.zip') self.testDefang('zip1',1,'zip.zip')
msg = mime.message_from_file(open('test/'+vname,"r")) msg = mime.message_from_file(open('test/'+vname,"r"))
mime.defang(msg,scan_zip=False) mime.defang(msg,scan_zip=False)
self.failIf(msg.ismodified()) self.failIf(msg.ismodified())
# test zip within zip
self.testDefang('ziploop',1,'stuart@bmsi.com.zip')
def testHTML(self,fname=""): def testHTML(self,fname=""):
result = StringIO.StringIO() result = StringIO.StringIO()
@@ -158,5 +153,3 @@ if __name__ == '__main__':
for fname in sys.argv[1:]: for fname in sys.argv[1:]:
fp = open(fname,'r') fp = open(fname,'r')
msg = mime.message_from_file(fp) msg = mime.message_from_file(fp)
mime.defang(msg,scan_zip=True)
print msg.as_string()