Fix lots of py3isms. Email package is borked in py3, however.
This commit is contained in:
+3
-3
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import time
|
import time
|
||||||
from plock import PLock
|
from Milter.plock import PLock
|
||||||
|
|
||||||
class AddrCache(object):
|
class AddrCache(object):
|
||||||
time_format = '%Y%b%d %H:%M:%S %Z'
|
time_format = '%Y%b%d %H:%M:%S %Z'
|
||||||
@@ -132,8 +132,8 @@ class AddrCache(object):
|
|||||||
if not ts or ts > too_old:
|
if not ts or ts > too_old:
|
||||||
return res
|
return res
|
||||||
del self.cache[lsender]
|
del self.cache[lsender]
|
||||||
raise KeyError, sender
|
raise KeyError(sender)
|
||||||
except KeyError,x:
|
except KeyError as x:
|
||||||
try:
|
try:
|
||||||
user,host = sender.split('@',1)
|
user,host = sender.split('@',1)
|
||||||
return self.__getitem__(host)
|
return self.__getitem__(host)
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ import time
|
|||||||
import logging
|
import logging
|
||||||
import urllib
|
import urllib
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
try:
|
||||||
import thread
|
import thread
|
||||||
|
except:
|
||||||
|
import _thread as thread
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
log = logging.getLogger('milter.greylist')
|
log = logging.getLogger('milter.greylist')
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@ class PLock(object):
|
|||||||
self.basename = basename
|
self.basename = basename
|
||||||
self.fp = None
|
self.fp = None
|
||||||
|
|
||||||
def lock(self,lockname=None,mode=0660,strict_perms=False):
|
def lock(self,lockname=None,mode=0o660,strict_perms=False):
|
||||||
"Start an update transaction. Return FILE to write new version."
|
"Start an update transaction. Return FILE to write new version."
|
||||||
self.unlock()
|
self.unlock()
|
||||||
if not lockname:
|
if not lockname:
|
||||||
@@ -21,7 +21,7 @@ class PLock(object):
|
|||||||
st = os.stat(self.basename)
|
st = os.stat(self.basename)
|
||||||
mode |= st.st_mode
|
mode |= st.st_mode
|
||||||
except OSError: pass
|
except OSError: pass
|
||||||
u = os.umask(0002)
|
u = os.umask(0o2)
|
||||||
try:
|
try:
|
||||||
fd = os.open(lockname,os.O_WRONLY+os.O_CREAT+os.O_EXCL,mode)
|
fd = os.open(lockname,os.O_WRONLY+os.O_CREAT+os.O_EXCL,mode)
|
||||||
finally:
|
finally:
|
||||||
@@ -46,7 +46,7 @@ class PLock(object):
|
|||||||
def commit(self,backname=None):
|
def commit(self,backname=None):
|
||||||
"Commit update transaction with optional backup file."
|
"Commit update transaction with optional backup file."
|
||||||
if not self.fp:
|
if not self.fp:
|
||||||
raise IOError,"File not locked"
|
raise IOError("File not locked")
|
||||||
self.fp.close()
|
self.fp.close()
|
||||||
self.fp = None
|
self.fp = None
|
||||||
if backname:
|
if backname:
|
||||||
|
|||||||
+1
-1
@@ -85,7 +85,7 @@ def inet_pton(p):
|
|||||||
::1.2.3.4.5
|
::1.2.3.4.5
|
||||||
"""
|
"""
|
||||||
if p == '::':
|
if p == '::':
|
||||||
return '\0'*16
|
return b'\0'*16
|
||||||
s = p
|
s = p
|
||||||
m = RE_IP4.search(s)
|
m = RE_IP4.search(s)
|
||||||
try:
|
try:
|
||||||
|
|||||||
+15
-31
@@ -2,7 +2,7 @@
|
|||||||
# A test framework for milters
|
# A test framework for milters
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import rfc822
|
import mime
|
||||||
try:
|
try:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
except:
|
except:
|
||||||
@@ -62,11 +62,11 @@ class TestBase(object):
|
|||||||
self._body.write(chunk)
|
self._body.write(chunk)
|
||||||
self._bodyreplaced = True
|
self._bodyreplaced = True
|
||||||
else:
|
else:
|
||||||
raise IOError,"replacebody not called from eom()"
|
raise IOError("replacebody not called from eom()")
|
||||||
|
|
||||||
def chgfrom(self,sender,params=None):
|
def chgfrom(self,sender,params=None):
|
||||||
if not self._body:
|
if not self._body:
|
||||||
raise IOError,"chgfrom not called from eom()"
|
raise IOError("chgfrom not called from eom()")
|
||||||
self.log('chgfrom: sender=%s' % (sender))
|
self.log('chgfrom: sender=%s' % (sender))
|
||||||
self._envfromchanged = True
|
self._envfromchanged = True
|
||||||
self._sender = sender
|
self._sender = sender
|
||||||
@@ -83,7 +83,7 @@ class TestBase(object):
|
|||||||
# work for a %milter
|
# work for a %milter
|
||||||
def chgheader(self,field,idx,value):
|
def chgheader(self,field,idx,value):
|
||||||
if not self._body:
|
if not self._body:
|
||||||
raise IOError,"chgheader not called from eom()"
|
raise IOError("chgheader not called from eom()")
|
||||||
self.log('chgheader: %s[%d]=%s' % (field,idx,value))
|
self.log('chgheader: %s[%d]=%s' % (field,idx,value))
|
||||||
if value == '':
|
if value == '':
|
||||||
del self._msg[field]
|
del self._msg[field]
|
||||||
@@ -93,19 +93,19 @@ class TestBase(object):
|
|||||||
|
|
||||||
def addheader(self,field,value,idx=-1):
|
def addheader(self,field,value,idx=-1):
|
||||||
if not self._body:
|
if not self._body:
|
||||||
raise IOError,"addheader not called from eom()"
|
raise IOError("addheader not called from eom()")
|
||||||
self.log('addheader: %s=%s' % (field,value))
|
self.log('addheader: %s=%s' % (field,value))
|
||||||
self._msg[field] = value
|
self._msg[field] = value
|
||||||
self._headerschanged = True
|
self._headerschanged = True
|
||||||
|
|
||||||
def delrcpt(self,rcpt):
|
def delrcpt(self,rcpt):
|
||||||
if not self._body:
|
if not self._body:
|
||||||
raise IOError,"delrcpt not called from eom()"
|
raise IOError("delrcpt not called from eom()")
|
||||||
self._delrcpt.append(rcpt)
|
self._delrcpt.append(rcpt)
|
||||||
|
|
||||||
def addrcpt(self,rcpt):
|
def addrcpt(self,rcpt):
|
||||||
if not self._body:
|
if not self._body:
|
||||||
raise IOError,"addrcpt not called from eom()"
|
raise IOError("addrcpt not called from eom()")
|
||||||
self._addrcpt.append(rcpt)
|
self._addrcpt.append(rcpt)
|
||||||
|
|
||||||
## Save the reply codes and messages in self._reply.
|
## Save the reply codes and messages in self._reply.
|
||||||
@@ -143,34 +143,21 @@ class TestBase(object):
|
|||||||
self._headerschanged = False
|
self._headerschanged = False
|
||||||
self._reply = None
|
self._reply = None
|
||||||
self._sender = '<%s>'%sender
|
self._sender = '<%s>'%sender
|
||||||
msg = rfc822.Message(fp)
|
msg = mime.message_from_file(fp)
|
||||||
rc = self.envfrom(self._sender)
|
rc = self.envfrom(self._sender)
|
||||||
if rc != Milter.CONTINUE: return rc
|
if rc != Milter.CONTINUE: return rc
|
||||||
for rcpt in (rcpt,) + rcpts:
|
for rcpt in (rcpt,) + rcpts:
|
||||||
rc = self.envrcpt('<%s>'%rcpt)
|
rc = self.envrcpt('<%s>'%rcpt)
|
||||||
if rc != Milter.CONTINUE: return rc
|
if rc != Milter.CONTINUE: return rc
|
||||||
line = None
|
for h,val in msg.items():
|
||||||
for h in msg.headers:
|
rc = self.header(h,val)
|
||||||
if h[:1].isspace():
|
|
||||||
line = line + h
|
|
||||||
continue
|
|
||||||
if not line:
|
|
||||||
line = h
|
|
||||||
continue
|
|
||||||
s = line.split(': ',1)
|
|
||||||
if len(s) > 1: val = s[1].strip()
|
|
||||||
else: val = ''
|
|
||||||
rc = self.header(s[0],val)
|
|
||||||
if rc != Milter.CONTINUE: return rc
|
|
||||||
line = h
|
|
||||||
if line:
|
|
||||||
s = line.split(': ',1)
|
|
||||||
rc = self.header(s[0],s[1])
|
|
||||||
if rc != Milter.CONTINUE: return rc
|
if rc != Milter.CONTINUE: return rc
|
||||||
rc = self.eoh()
|
rc = self.eoh()
|
||||||
if rc != Milter.CONTINUE: return rc
|
if rc != Milter.CONTINUE: return rc
|
||||||
|
header,body = msg.as_bytes().split(b'\n\n',1)
|
||||||
|
bfp = StringIO(body)
|
||||||
while 1:
|
while 1:
|
||||||
buf = fp.read(8192)
|
buf = bfp.read(8192)
|
||||||
if len(buf) == 0: break
|
if len(buf) == 0: break
|
||||||
rc = self.body(buf)
|
rc = self.body(buf)
|
||||||
if rc != Milter.CONTINUE: return rc
|
if rc != Milter.CONTINUE: return rc
|
||||||
@@ -179,12 +166,9 @@ class TestBase(object):
|
|||||||
rc = self.eom()
|
rc = self.eom()
|
||||||
if self._bodyreplaced:
|
if self._bodyreplaced:
|
||||||
body = self._body.getvalue()
|
body = self._body.getvalue()
|
||||||
else:
|
|
||||||
msg.rewindbody()
|
|
||||||
body = msg.fp.read()
|
|
||||||
self._body = StringIO()
|
self._body = StringIO()
|
||||||
self._body.writelines(msg.headers)
|
self._body.write(header)
|
||||||
self._body.write('\n')
|
self._body.write('\n\n')
|
||||||
self._body.write(body)
|
self._body.write(body)
|
||||||
return rc
|
return rc
|
||||||
|
|
||||||
|
|||||||
+10
-12
@@ -5,13 +5,11 @@
|
|||||||
import re
|
import re
|
||||||
import struct
|
import struct
|
||||||
import socket
|
import socket
|
||||||
import email.Errors
|
import email.errors
|
||||||
|
from email.header import decode_header
|
||||||
import email.base64mime
|
import email.base64mime
|
||||||
from fnmatch import fnmatchcase
|
from fnmatch import fnmatchcase
|
||||||
from email.Header import decode_header
|
|
||||||
from binascii import a2b_base64
|
from binascii import a2b_base64
|
||||||
#import email.Utils
|
|
||||||
import rfc822
|
|
||||||
|
|
||||||
dnsre = re.compile(r'^[a-z][-a-z\d.]+$', re.IGNORECASE)
|
dnsre = re.compile(r'^[a-z][-a-z\d.]+$', re.IGNORECASE)
|
||||||
PAT_IP4 = r'\.'.join([r'(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])']*4)
|
PAT_IP4 = r'\.'.join([r'(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])']*4)
|
||||||
@@ -56,8 +54,8 @@ if hasattr(socket,'has_ipv6') and socket.has_ipv6:
|
|||||||
else:
|
else:
|
||||||
from pyip6 import inet_ntop, inet_pton
|
from pyip6 import inet_ntop, inet_pton
|
||||||
|
|
||||||
MASK = 0xFFFFFFFFL
|
MASK = 0xFFFFFFFF
|
||||||
MASK6 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFL
|
MASK6 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||||
|
|
||||||
def cidr(i,n,mask=MASK):
|
def cidr(i,n,mask=MASK):
|
||||||
return ~(mask >> n) & mask & i
|
return ~(mask >> n) & mask & i
|
||||||
@@ -119,7 +117,7 @@ def iniplist(ipaddr,iplist):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
## Split email into Fullname and address.
|
## Split email into Fullname and address.
|
||||||
# This replaces <code>email.Utils.parseaddr</code> but fixes
|
# This replaces <code>email.utils.parseaddr</code> but fixes
|
||||||
# some <a href="http://bugs.python.org/issue1025395">tricky test cases</a>.
|
# some <a href="http://bugs.python.org/issue1025395">tricky test cases</a>.
|
||||||
# Additional tricky cases are still broken. Patches welcome.
|
# Additional tricky cases are still broken. Patches welcome.
|
||||||
#
|
#
|
||||||
@@ -139,8 +137,8 @@ def parseaddr(t):
|
|||||||
>>> parseaddr('a(WRONG)@b')
|
>>> parseaddr('a(WRONG)@b')
|
||||||
('WRONG', 'a@b')
|
('WRONG', 'a@b')
|
||||||
"""
|
"""
|
||||||
#return email.Utils.parseaddr(t)
|
#return email.utils.parseaddr(t)
|
||||||
res = rfc822.parseaddr(t)
|
res = email.utils.parseaddr(t)
|
||||||
# dirty fix for some broken cases
|
# dirty fix for some broken cases
|
||||||
if not res[0]:
|
if not res[0]:
|
||||||
pos = t.find('<')
|
pos = t.find('<')
|
||||||
@@ -149,7 +147,7 @@ def parseaddr(t):
|
|||||||
pos1 = addrspec.rfind(':')
|
pos1 = addrspec.rfind(':')
|
||||||
if pos1 > 0:
|
if pos1 > 0:
|
||||||
addrspec = addrspec[pos1+1:]
|
addrspec = addrspec[pos1+1:]
|
||||||
return rfc822.parseaddr('"%s" <%s>' % (t[:pos].strip(),addrspec))
|
return email.utils.parseaddr('"%s" <%s>' % (t[:pos].strip(),addrspec))
|
||||||
if not res[1]:
|
if not res[1]:
|
||||||
pos = t.find('<')
|
pos = t.find('<')
|
||||||
if pos > 0 and t[-1] == '>':
|
if pos > 0 and t[-1] == '>':
|
||||||
@@ -157,7 +155,7 @@ def parseaddr(t):
|
|||||||
pos1 = addrspec.rfind(':')
|
pos1 = addrspec.rfind(':')
|
||||||
if pos1 > 0:
|
if pos1 > 0:
|
||||||
addrspec = addrspec[pos1+1:]
|
addrspec = addrspec[pos1+1:]
|
||||||
return rfc822.parseaddr('%s<%s>' % (t[:pos].strip(),addrspec))
|
return email.utils.parseaddr('%s<%s>' % (t[:pos].strip(),addrspec))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
## Fix email.base64mime.decode to add any missing padding
|
## Fix email.base64mime.decode to add any missing padding
|
||||||
@@ -227,5 +225,5 @@ def parse_header(val):
|
|||||||
except UnicodeDecodeError: pass
|
except UnicodeDecodeError: pass
|
||||||
except LookupError: pass
|
except LookupError: pass
|
||||||
except ValueError: pass
|
except ValueError: pass
|
||||||
except email.Errors.HeaderParseError: pass
|
except email.errors.HeaderParseError: pass
|
||||||
return val
|
return val
|
||||||
|
|||||||
@@ -103,15 +103,12 @@ import Milter
|
|||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
import email
|
import email
|
||||||
import email.Message
|
from email.message import Message
|
||||||
from email.Message import Message
|
from email.generator import Generator
|
||||||
from email.Generator import Generator
|
from email.utils import quote
|
||||||
from email.Utils import quote
|
|
||||||
from email import Utils
|
|
||||||
from email.Parser import Parser
|
|
||||||
from email import Errors
|
|
||||||
|
|
||||||
from types import ListType,StringType
|
if not getattr(Message,'as_bytes',None):
|
||||||
|
Message.as_bytes = Message.as_string
|
||||||
|
|
||||||
## Return a list of filenames in a zip file.
|
## Return a list of filenames in a zip file.
|
||||||
# Embedded zip files are recursively expanded.
|
# Embedded zip files are recursively expanded.
|
||||||
@@ -154,19 +151,17 @@ def unquote(s):
|
|||||||
return s[1:-1]
|
return s[1:-1]
|
||||||
return s
|
return s
|
||||||
|
|
||||||
from types import TupleType
|
|
||||||
|
|
||||||
def _unquotevalue(value):
|
def _unquotevalue(value):
|
||||||
if isinstance(value, TupleType):
|
if isinstance(value, tuple):
|
||||||
return value[0], value[1], unquote(value[2])
|
return value[0], value[1], unquote(value[2])
|
||||||
else:
|
else:
|
||||||
return unquote(value)
|
return unquote(value)
|
||||||
|
|
||||||
#email.Message._unquotevalue = _unquotevalue
|
#email.Message._unquotevalue = _unquotevalue
|
||||||
|
|
||||||
from email.Message import _parseparam
|
from email.message import _parseparam
|
||||||
|
|
||||||
## Enhance email.Message
|
## Enhance email.message.Message
|
||||||
#
|
#
|
||||||
# Tracks modifications to headers of body or any part independently.
|
# Tracks modifications to headers of body or any part independently.
|
||||||
|
|
||||||
@@ -207,7 +202,7 @@ class MimeMessage(Message):
|
|||||||
interpret as a name - and hence decide to execute this message."""
|
interpret as a name - and hence decide to execute this message."""
|
||||||
names = []
|
names = []
|
||||||
for attr,val in self._get_params_preserve([],'content-type'):
|
for attr,val in self._get_params_preserve([],'content-type'):
|
||||||
if isinstance(val, TupleType):
|
if isinstance(val, tuple):
|
||||||
# It's an RFC 2231 encoded parameter
|
# It's an RFC 2231 encoded parameter
|
||||||
newvalue = _unquotevalue(val)
|
newvalue = _unquotevalue(val)
|
||||||
if val[0]:
|
if val[0]:
|
||||||
@@ -355,8 +350,6 @@ def check_name(msg,savname=None,ckname=check_ext,scan_zip=False):
|
|||||||
msg["Content-Type"] = "text/plain; name="+name
|
msg["Content-Type"] = "text/plain; name="+name
|
||||||
return Milter.CONTINUE
|
return Milter.CONTINUE
|
||||||
|
|
||||||
import email.Iterators
|
|
||||||
|
|
||||||
def check_attachments(msg,check):
|
def check_attachments(msg,check):
|
||||||
"""Scan attachments.
|
"""Scan attachments.
|
||||||
msg MimeMessage
|
msg MimeMessage
|
||||||
@@ -402,18 +395,21 @@ class _defang:
|
|||||||
# emulate old defang function
|
# emulate old defang function
|
||||||
defang = _defang()
|
defang = _defang()
|
||||||
|
|
||||||
import sgmllib
|
try:
|
||||||
|
from html.parser import HTMLParser
|
||||||
|
except:
|
||||||
|
from sgmllib import SGMLParser as HTMLParser
|
||||||
|
|
||||||
import re
|
import re
|
||||||
declname = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*')
|
declname = re.compile(r'[a-zA-Z][-_.a-zA-Z0-9]*\s*')
|
||||||
declstringlit = re.compile(r'(\'[^\']*\'|"[^"]*")\s*')
|
declstringlit = re.compile(r'(\'[^\']*\'|"[^"]*")\s*')
|
||||||
|
|
||||||
class SGMLFilter(sgmllib.SGMLParser):
|
class SGMLFilter(HTMLParser):
|
||||||
"""Parse HTML and pass through all constructs unchanged. It is intended for
|
"""Parse HTML and pass through all constructs unchanged. It is intended for
|
||||||
derived classes to implement exceptional processing for selected cases.
|
derived classes to implement exceptional processing for selected cases.
|
||||||
"""
|
"""
|
||||||
def __init__(self,out):
|
def __init__(self,out):
|
||||||
sgmllib.SGMLParser.__init__(self)
|
HTMLParser.__init__(self)
|
||||||
self.out = out
|
self.out = out
|
||||||
|
|
||||||
def handle_comment(self,comment):
|
def handle_comment(self,comment):
|
||||||
@@ -444,7 +440,7 @@ class SGMLFilter(sgmllib.SGMLParser):
|
|||||||
self.out.write("<!%s>" % data)
|
self.out.write("<!%s>" % data)
|
||||||
|
|
||||||
def write(self,buf):
|
def write(self,buf):
|
||||||
"Act like a writer. Why doesn't SGMLParser do this by default?"
|
"Act like a writer. Why doesn't HTMLParser do this by default?"
|
||||||
self.feed(buf)
|
self.feed(buf)
|
||||||
|
|
||||||
# Python-2.1 sgmllib rejects illegal declarations. Since various Microsoft
|
# Python-2.1 sgmllib rejects illegal declarations. Since various Microsoft
|
||||||
@@ -545,5 +541,5 @@ if __name__ == '__main__':
|
|||||||
for fname in sys.argv[1:]:
|
for fname in sys.argv[1:]:
|
||||||
fp = open(fname)
|
fp = open(fname)
|
||||||
msg = message_from_file(fp)
|
msg = message_from_file(fp)
|
||||||
email.Iterators._structure(msg)
|
email.iterators._structure(msg)
|
||||||
check_attachments(msg,_list_attach)
|
check_attachments(msg,_list_attach)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ try:
|
|||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
except:
|
except:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import rfc822
|
|
||||||
import mime
|
import mime
|
||||||
import Milter
|
import Milter
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -141,19 +140,16 @@ class sampleMilter(Milter.Milter):
|
|||||||
self.log("Temp file:",self.tempname)
|
self.log("Temp file:",self.tempname)
|
||||||
self.tempname = None # prevent removal of original message copy
|
self.tempname = None # prevent removal of original message copy
|
||||||
# copy defanged message to a temp file
|
# copy defanged message to a temp file
|
||||||
out = tempfile.TemporaryFile()
|
with tempfile.TemporaryFile() as out:
|
||||||
try:
|
|
||||||
msg.dump(out)
|
msg.dump(out)
|
||||||
out.seek(0)
|
out.seek(0)
|
||||||
msg = rfc822.Message(out)
|
msg = mime.message_from_file(out)
|
||||||
msg.rewindbody()
|
fp = StringIO(msg.as_bytes().split(b'\n\n',1)[1])
|
||||||
while 1:
|
while 1:
|
||||||
buf = out.read(8192)
|
buf = fp.read(8192)
|
||||||
if len(buf) == 0: break
|
if len(buf) == 0: break
|
||||||
self.replacebody(buf) # feed modified message to sendmail
|
self.replacebody(buf) # feed modified message to sendmail
|
||||||
return Milter.ACCEPT # ACCEPT modified message
|
return Milter.ACCEPT # ACCEPT modified message
|
||||||
finally:
|
|
||||||
out.close()
|
|
||||||
return Milter.TEMPFAIL
|
return Milter.TEMPFAIL
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
|||||||
+5
-2
@@ -37,7 +37,10 @@ except:
|
|||||||
import email
|
import email
|
||||||
import sys
|
import sys
|
||||||
import Milter
|
import Milter
|
||||||
from email import Errors
|
try:
|
||||||
|
from email import Errors as errors
|
||||||
|
except:
|
||||||
|
from email import errors
|
||||||
|
|
||||||
samp1_txt1 = """Dear Agent 1
|
samp1_txt1 = """Dear Agent 1
|
||||||
I hope you can read this. Whenever you write label it P.B.S kids.
|
I hope you can read this. Whenever you write label it P.B.S kids.
|
||||||
@@ -77,7 +80,7 @@ class MimeTestCase(unittest.TestCase):
|
|||||||
# if message is modified, output is readable by mail clients
|
# if message is modified, output is readable by mail clients
|
||||||
if sys.hexversion < 0x02040000:
|
if sys.hexversion < 0x02040000:
|
||||||
self.fail('should get boundary error parsing bad rfc822 attachment')
|
self.fail('should get boundary error parsing bad rfc822 attachment')
|
||||||
except Errors.BoundaryError:
|
except errors.BoundaryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def testDefang(self,vname='virus1',part=1,
|
def testDefang(self,vname='virus1',part=1,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import unittest
|
|||||||
import Milter
|
import Milter
|
||||||
import sample
|
import sample
|
||||||
import mime
|
import mime
|
||||||
import rfc822
|
|
||||||
from Milter.test import TestBase
|
from Milter.test import TestBase
|
||||||
|
|
||||||
class TestMilter(TestBase,sample.sampleMilter):
|
class TestMilter(TestBase,sample.sampleMilter):
|
||||||
|
|||||||
Reference in New Issue
Block a user