Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f24197009 |
+22
-11
@@ -141,16 +141,28 @@ def closecallback(ctx):
|
||||
m._setctx(None) # release milterContext
|
||||
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):
|
||||
"""Convert ESMTP parms to keyword parameters.
|
||||
"""Call function c with ESMTP parms converted to keyword parameters.
|
||||
Can be used in the envfrom and/or envrcpt callbacks to process
|
||||
ESMTP parameters as python keyword parameters."""
|
||||
kw = {}
|
||||
pargs = [args[0]]
|
||||
for s in args[1:]:
|
||||
pos = s.find('=')
|
||||
if pos > 0:
|
||||
kw[s[:pos]] = s[pos+1:]
|
||||
return apply(c,args,kw)
|
||||
kw[s[:pos].upper()] = s[pos+1:]
|
||||
else:
|
||||
pargs.append(s)
|
||||
return c(*pargs,**kw)
|
||||
|
||||
def runmilter(name,socketname,timeout = 0):
|
||||
# This bit is here on the assumption that you will be starting this filter
|
||||
@@ -177,14 +189,13 @@ def runmilter(name,socketname,timeout = 0):
|
||||
# milter.set_flags(milter.ADDHDRS)
|
||||
milter.set_connect_callback(connectcallback)
|
||||
milter.set_helo_callback(lambda ctx, host: ctx.getpriv().hello(host))
|
||||
milter.set_envfrom_callback(lambda ctx,*str:
|
||||
ctx.getpriv().envfrom(*str))
|
||||
# envcallback(ctx.getpriv().envfrom,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))
|
||||
# For envfrom and envrcpt, we would like to convert ESMTP parms to keyword
|
||||
# parms, but then all existing users would have to include **kw to accept
|
||||
# arbitrary keywords without crashing. We do provide envcallback and
|
||||
# dictfromlist to make parsing the ESMTP args convenient.
|
||||
milter.set_envfrom_callback(lambda ctx,*str: ctx.getpriv().envfrom(*str))
|
||||
milter.set_envrcpt_callback(lambda ctx,*str: ctx.getpriv().envrcpt(*str))
|
||||
milter.set_header_callback(lambda ctx,fld,val: ctx.getpriv().header(fld,val))
|
||||
milter.set_eoh_callback(lambda ctx: ctx.getpriv().eoh())
|
||||
milter.set_body_callback(lambda ctx,chunk: ctx.getpriv().body(chunk))
|
||||
milter.set_eom_callback(lambda ctx: ctx.getpriv().eom())
|
||||
|
||||
+8
-5
@@ -95,7 +95,10 @@ Received-SPF: %(spf_result)s
|
||||
"""
|
||||
|
||||
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('@')
|
||||
q = spf.query(None,None,None)
|
||||
mxlist = q.dns(domain,'MX')
|
||||
@@ -112,7 +115,7 @@ def send_dsn(mailfrom,receiver,msg=None):
|
||||
if resp.split()[0] == receiver:
|
||||
return (553,'Fraudulent MX for %s' % domain)
|
||||
if not (200 <= code <= 299):
|
||||
raise SMTPHeloError(code, resp)
|
||||
raise smtplib.SMTPHeloError(code, resp)
|
||||
if msg:
|
||||
try:
|
||||
smtp.sendmail('<>',mailfrom,msg)
|
||||
@@ -122,7 +125,7 @@ def send_dsn(mailfrom,receiver,msg=None):
|
||||
else: # CBV
|
||||
code,resp = smtp.docmd('MAIL FROM: <>')
|
||||
if code != 250:
|
||||
raise SMTPSenderRefused(code, resp, '<>')
|
||||
raise smtplib.SMTPSenderRefused(code, resp, '<>')
|
||||
code,resp = smtp.rcpt(mailfrom)
|
||||
if code not in (250,251):
|
||||
return (code,resp) # permanent error
|
||||
@@ -131,9 +134,9 @@ def send_dsn(mailfrom,receiver,msg=None):
|
||||
except smtplib.SMTPRecipientsRefused,x:
|
||||
return x.recipients[mailfrom] # permanent error
|
||||
except smtplib.SMTPSenderRefused,x:
|
||||
return x # does not accept DSN
|
||||
return x.args[:2] # does not accept DSN
|
||||
except smtplib.SMTPDataError,x:
|
||||
return x # permanent error
|
||||
return x.args # permanent error
|
||||
except smtplib.SMTPException:
|
||||
pass # any other error, try next MX
|
||||
except socket.error:
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
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
|
||||
0.8.0 Move Milter module to subpackage.
|
||||
DSN support for Three strikes rule and SPF SOFTFAIL
|
||||
Move /*mime*/ and dynip to Milter subpackage
|
||||
Fix SPF unknown mechanism list not cleared
|
||||
Make banned extensions configurable.
|
||||
Option to scan zipfiles for bad extensions.
|
||||
Properly log pydspam exceptions
|
||||
0.7.3 Experimental release with python2.4 support
|
||||
0.7.2 Return unknown for invalid ip address in mechanism
|
||||
Recognize dynamic PTR names, and don't count them as authentication.
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
# A simple milter that has grown quite a bit.
|
||||
# $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
|
||||
# Fix bugs from testing RPM
|
||||
#
|
||||
@@ -457,9 +466,9 @@ def parse_addr(t):
|
||||
return t.split('@')
|
||||
|
||||
def parse_header(val):
|
||||
h = decode_header(val)
|
||||
if not len(h) or (not h[0][1] and len(h) == 1): return val
|
||||
try:
|
||||
h = decode_header(val)
|
||||
if not len(h) or (not h[0][1] and len(h) == 1): return val
|
||||
u = []
|
||||
for s,enc in h:
|
||||
if enc:
|
||||
@@ -476,6 +485,7 @@ def parse_header(val):
|
||||
except UnicodeError: continue
|
||||
except UnicodeDecodeError: pass
|
||||
except LookupError: pass
|
||||
except email.errors.HeaderParseError: pass
|
||||
return val
|
||||
|
||||
class bmsMilter(Milter.Milter):
|
||||
@@ -620,6 +630,17 @@ class bmsMilter(Milter.Milter):
|
||||
self.log("REJECT: spam from self",pat)
|
||||
self.setreply('550','5.7.1','I hate talking to myself.')
|
||||
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
|
||||
if user in wiretap_users.get(domain,()):
|
||||
self.add_recipient(wiretap_dest)
|
||||
|
||||
@@ -72,6 +72,9 @@ milter-0.4.5 or later to remove this dependency.
|
||||
<code>set_flags()</code> before calling <code>runmilter()</code>. For
|
||||
instance, <code>Milter.set_flags(Milter.ADDRCPT)</code>. You must add together
|
||||
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>
|
||||
|
||||
<li> Q. Why does sendmail sometimes print something like:
|
||||
@@ -94,14 +97,19 @@ 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
|
||||
an active config file.
|
||||
<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?
|
||||
<p> A. Sendmail has a problem with unix sockets on OpenBSD. Use
|
||||
an internet domain socket instead. For example, in <code>sendmail.cf</code> use
|
||||
<p> A. Sendmail has a problem with unix sockets on old versions of OpenBSD.
|
||||
Use an internet domain socket instead. For example, in
|
||||
<code>sendmail.cf</code> use
|
||||
<pre>
|
||||
Xpythonfilter, S=inet:1234@localhost
|
||||
</pre>
|
||||
and change sample.py accordingly.
|
||||
<p> OpenBSD users report that this problem has been fixed.
|
||||
<p>
|
||||
|
||||
<li> Q. How can I change the bounce message for an invalid recipient?
|
||||
@@ -143,8 +151,8 @@ everything up for you. For other systems:
|
||||
<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
|
||||
to use SRC (System Resource Controller).
|
||||
<li> Copy milter.cfg to the directory you run bms.py in, and edit it. The
|
||||
comments should explain the options.
|
||||
<li> Copy pymilter.cfg to the /etc/mail or the directory you run bms.py in,
|
||||
and edit it. The comments should explain the options.
|
||||
<li> Start bms.py in the background as arranged.
|
||||
<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
|
||||
|
||||
+13
-8
@@ -1,25 +1,29 @@
|
||||
[milter]
|
||||
# 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
|
||||
tempdir = /var/log/milter/save
|
||||
# how long to wait for a response from sendmail before giving up
|
||||
;timeout=600
|
||||
log_headers = 0
|
||||
# connection ips and hostnames are matched against this glob style list
|
||||
# to recognize internal senders
|
||||
# to recognize internal senders.
|
||||
;internal_connect = 192.168.*.*
|
||||
|
||||
# mail that is not an internal_connect and claims to be from an
|
||||
# internal domain is rejected. You should enable SPF instead if you can.
|
||||
# SPF is much more comprehensive and flexible.
|
||||
# internal domain is rejected. Furthermore, internal mail that
|
||||
# does not claim to be from an internal domain is rejected.
|
||||
# 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
|
||||
|
||||
# connections from a trusted relay can trust the first Received header
|
||||
# SPF checks are bypassed for internal connections and trusted relays.
|
||||
;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
|
||||
# will save some DNS lookups when rejecting certain viruses.
|
||||
;hello_blacklist = mycorp.com, 66.12.34.56
|
||||
@@ -46,7 +50,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,
|
||||
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,
|
||||
valium, rolex, sexual
|
||||
valium, rolex, sexual, fuck
|
||||
# reject mail with these case sensitive strings in the subject
|
||||
spam_words = $$$, !!!, XXX, FREE, HGH
|
||||
# attachments with these extensions will be replaced with a warning
|
||||
@@ -76,9 +80,10 @@ reject_spoofed = 0
|
||||
;reject_neutral = aol.com
|
||||
# use a default (v=spf1 a/24 mx/24 ptr) when no SPF records are published
|
||||
;best_guess = 0
|
||||
# reject senders that have neither PTR nor SPF records, or DSN if false
|
||||
# Reject senders that have neither PTR nor valid HELO nor SPF records, or send
|
||||
# DSN otherwise
|
||||
;reject_noptr = 0
|
||||
# always accept softfail from these domains, or DSN otherwise
|
||||
# always accept softfail from these domains, or send DSN otherwise
|
||||
;accept_softfail = bounces.amazon.com
|
||||
|
||||
# features intended to clean up outgoing mail
|
||||
|
||||
+18
-7
@@ -24,11 +24,13 @@ ALT="Viewable With Any Browser" BORDER="0"></A>
|
||||
Stuart D. Gathman</a><br>
|
||||
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>
|
||||
Last updated May 31, 2005</h4>
|
||||
Last updated Jun 09, 2005</h4>
|
||||
|
||||
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="#overview">Overview</a>
|
||||
<a href="#overview">Overview</a> |
|
||||
<a href="/python/dspam.html">pydspam</a> |
|
||||
<a href="/libdspam/dspam.html">libdspam</a>
|
||||
<p>
|
||||
<a href="//www.python.org">
|
||||
<img src="python55.gif" align=left alt="A Python"></a>
|
||||
@@ -39,17 +41,26 @@ provides a python interface to libmilter that exploits all its features.
|
||||
<p>
|
||||
Sendmail 8.12 officially releases libmilter.
|
||||
Version 8.12 seems to be more robust, and includes new privilege
|
||||
separation features to enhance security.
|
||||
I recommend upgrading.
|
||||
separation features to enhance security. Even better, sendmail 8.13
|
||||
supports socket maps, which makes <a href="pysrs.html">pysrs</a> much more
|
||||
efficient and secure. I recommend upgrading.
|
||||
|
||||
<h2> Recent Changes </h2>
|
||||
|
||||
Python milter is being moved to
|
||||
<a href="http://sourceforge.net/projects/pymilter/">Sourceforge</a> for
|
||||
development.
|
||||
<a href="http://sourceforge.net/projects/pymilter/">pymilter Sourceforge
|
||||
project</a> for 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>
|
||||
Release 0.7.2 tightens the authentication screws with a "3 strikes and
|
||||
your out" policy. A sender must have a valid PTR, HELO, or SPF record
|
||||
you're out" policy. A sender must have a valid PTR, HELO, or SPF record
|
||||
to send email. Specific senders can be whitelisted using the
|
||||
"delegate" option in the spf configuration section by adding a
|
||||
default SPF record for them. The PTR and HELO are required
|
||||
|
||||
+8
-2
@@ -1,6 +1,6 @@
|
||||
%define name milter
|
||||
%define version 0.8.0
|
||||
%define release 3.RH7
|
||||
%define version 0.8.1
|
||||
%define release 1.RH7
|
||||
# what version of RH are we building for?
|
||||
%define redhat9 0
|
||||
%define redhat7 1
|
||||
@@ -166,6 +166,12 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/usr/share/sendmail-cf/hack/rhsbl.m4
|
||||
|
||||
%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
|
||||
* 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
|
||||
- Include default softfail, strike3 templates
|
||||
* Wed May 25 2005 Stuart Gathman <stuart@bmsi.com> 0.8.0-1
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# $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
|
||||
# Update copyright notices after reading article on /.
|
||||
#
|
||||
@@ -87,6 +90,16 @@ from email import Errors
|
||||
|
||||
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):
|
||||
def _dispatch(self, msg):
|
||||
# Get the Content-Type: for the message, then try to dispatch to
|
||||
@@ -177,13 +190,10 @@ class MimeMessage(Message):
|
||||
names.append((attr,val))
|
||||
names += [("filename",self.get_filename())]
|
||||
if scan_zip:
|
||||
for key,name in names:
|
||||
for key,name in tuple(names): # copy by converting to tuple
|
||||
if name and name.lower().endswith('.zip'):
|
||||
txt = self.get_payload(decode=True)
|
||||
fp = StringIO.StringIO(txt)
|
||||
zipf = zipfile.ZipFile(fp,'r')
|
||||
for nm in zipf.namelist():
|
||||
names.append(('zipname',nm))
|
||||
names += zipnames(txt)
|
||||
return names
|
||||
|
||||
def ismodified(self):
|
||||
|
||||
@@ -12,7 +12,7 @@ if sys.version < '2.2.3':
|
||||
DistributionMetadata.classifiers = None
|
||||
DistributionMetadata.download_url = None
|
||||
|
||||
setup(name = "milter", version = "0.8.0",
|
||||
setup(name = "milter", version = "0.8.1",
|
||||
description="Python interface to sendmail milter API",
|
||||
long_description="""\
|
||||
This is a python extension module to enable python scripts to
|
||||
|
||||
@@ -46,6 +46,9 @@ For news, bugfixes, etc. visit the home page for this implementation at
|
||||
# Terrence is not responding to email.
|
||||
#
|
||||
# $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
|
||||
# Reject on PermErr
|
||||
#
|
||||
@@ -684,13 +687,12 @@ class query(object):
|
||||
p = CIDParser(q=self)
|
||||
try:
|
||||
return p.spf_txt(domain)
|
||||
except xml.sax._exceptions.SAXParseException,x:
|
||||
except xml.sax._exceptions.SAXParseException:
|
||||
raise PermError("Caller-ID parse error",domain)
|
||||
|
||||
if len(a) == 1:
|
||||
return a[0]
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
def dns_txt(self, domainname):
|
||||
"Get a list of TXT records for a domain name."
|
||||
@@ -974,12 +976,12 @@ def bin2addr(addr):
|
||||
def expand_one(expansion, str, joiner):
|
||||
if not str:
|
||||
return expansion
|
||||
len, reverse, delimiters = RE_ARGS.split(str)[1:4]
|
||||
ln, reverse, delimiters = RE_ARGS.split(str)[1:4]
|
||||
if not delimiters:
|
||||
delimiters = '.'
|
||||
expansion = split(expansion, delimiters, joiner)
|
||||
if reverse: expansion.reverse()
|
||||
if len: expansion = expansion[-int(len)*2+1:]
|
||||
if ln: expansion = expansion[-int(ln)*2+1:]
|
||||
return ''.join(expansion)
|
||||
|
||||
def split(str, delimiters, joiner=None):
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ SMTP (email) servers to prevent criminals from forging your
|
||||
domain. The simplest step is usually to publish an SPF record
|
||||
with your Sender Policy.
|
||||
|
||||
For more information, see: http://spfhelp.net
|
||||
For more information, see: http://spf.pobox.com
|
||||
|
||||
I hate to annoy you with a DSN (Delivery Status
|
||||
Notification) from a possibly forged email, but since you
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
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--
|
||||
|
||||
|
||||
+8
-1
@@ -1,4 +1,7 @@
|
||||
# $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
|
||||
# Development changes since 0.7.2
|
||||
#
|
||||
@@ -126,10 +129,12 @@ class MimeTestCase(unittest.TestCase):
|
||||
self.failUnless(name == "Jim&amp;Girlz.jpg","name=%s"%name)
|
||||
|
||||
def testZip(self,vname="zip1",fname='zip.zip'):
|
||||
self.testDefang('zip1',1,'zip.zip')
|
||||
self.testDefang(vname,1,'zip.zip')
|
||||
msg = mime.message_from_file(open('test/'+vname,"r"))
|
||||
mime.defang(msg,scan_zip=False)
|
||||
self.failIf(msg.ismodified())
|
||||
# test zip within zip
|
||||
self.testDefang('ziploop',1,'stuart@bmsi.com.zip')
|
||||
|
||||
def testHTML(self,fname=""):
|
||||
result = StringIO.StringIO()
|
||||
@@ -153,3 +158,5 @@ if __name__ == '__main__':
|
||||
for fname in sys.argv[1:]:
|
||||
fp = open(fname,'r')
|
||||
msg = mime.message_from_file(fp)
|
||||
mime.defang(msg,scan_zip=True)
|
||||
print msg.as_string()
|
||||
|
||||
Reference in New Issue
Block a user