diff --git a/Milter/__init__.py b/Milter/__init__.py index 99baf9d..d130575 100755 --- a/Milter/__init__.py +++ b/Milter/__init__.py @@ -358,9 +358,9 @@ class Base(object): if e == 'bytes': #self.envfrom_bytes = self.envfrom return self.envfrom(*b) - s = (v.decode(encoding='utf-8',errors=e) for v in b) + s = [v.decode(encoding='utf-8',errors=e) for v in b] except UnicodeDecodeError: s = b - return self.envfrom(fld,*s) + return self.envfrom(s[0],*s[1:]) ## Called when the SMTP client says MAIL FROM. Called by the # # xxfi_envfrom callback. @@ -383,9 +383,9 @@ class Base(object): if e == 'bytes': #self.envrcpt_bytes = self.envrcpt return self.envrcpt(*b) - s = (v.decode(encoding='utf-8',errors=e) for v in b) + s = [v.decode(encoding='utf-8',errors=e) for v in b] except UnicodeDecodeError: s = b - return self.envrcpt(fld,*s) + return self.envrcpt(s[0],*s[1:]) ## Called when the SMTP client says RCPT TO. Called by the # # xxfi_envrcpt callback. diff --git a/Milter/policy.py b/Milter/policy.py index 25ed5db..a533ba3 100644 --- a/Milter/policy.py +++ b/Milter/policy.py @@ -16,6 +16,7 @@ try: f = DB() f.open(fname,mode) return f +except ModuleNotFoundError: raise except: import anydbm as dbm dbmopen = dbm.open diff --git a/mime.py b/mime.py index 2b1f6cc..b6df136 100644 --- a/mime.py +++ b/mime.py @@ -125,7 +125,7 @@ class MimeMessage(Message): """Return a list of (attr,name) pairs of attributes that IE might interpret as a name - and hence decide to execute this message.""" names = [] - for attr,val in self._get_params_preserve([],'content-type'): + for attr,val in self.get_params([],'content-type',False): if isinstance(val, tuple): # It's an RFC 2231 encoded parameter newvalue = _unquotevalue(val) @@ -195,6 +195,11 @@ class MimeMessage(Message): def get_payload(self,i=None,decode=False): msg = self.submsg + if msg is None: + t = self.get_content_type().lower() + if t == 'message/rfc822' or t.startswith('multipart/'): + msg = super().get_payload() + self.submsg = msg if isinstance(msg,Message) and msg.ismodified(): self.set_payload([msg]) return Message.get_payload(self,i,decode) @@ -213,7 +218,11 @@ class MimeMessage(Message): if t == 'message/rfc822' or t.startswith('multipart/'): if not self.submsg: txt = self.get_payload() - if type(txt) == str: + if type(txt) is bytes: + self.submsg = email.message_from_bytes(txt,MimeMessage) + for part in self.submsg.walk(): + part.modified = False + elif type(txt) is str: txt = self.get_payload(decode=True) self.submsg = email.message_from_string(txt,MimeMessage) for part in self.submsg.walk(): @@ -274,17 +283,24 @@ def check_name(msg,savname=None,ckname=check_ext,scan_zip=False): msg["Content-Type"] = "text/plain; name="+name return Milter.CONTINUE -def check_attachments(msg,check): +def check_attachments(msg,check,lev=None): """Scan attachments. msg MimeMessage check function(MimeMessage): int Return CONTINUE, REJECT, ACCEPT """ if msg.is_multipart(): + if not lev: lev = [] + lev.append(1) + if msg.get_content_type().endswith('/rfc822'): + foo = 1 for i in msg.get_payload(): - rc = check_attachments(i,check) + print('chkm',lev,msg.get_content_type()) + rc = check_attachments(i,check,lev=lev) if rc != Milter.CONTINUE: return rc + lev[-1] += 1 return Milter.CONTINUE + print('chk',lev,msg.get_content_type()) return check(msg) # save call context for Python without nested_scopes diff --git a/testmime.py b/testmime.py index 3b1f236..18a9276 100644 --- a/testmime.py +++ b/testmime.py @@ -192,6 +192,33 @@ class MimeTestCase(unittest.TestCase): self.assertEqual(self.filename,"7501'S FOR TWO GOLDEN SOURCES SHIPMENTS FOR TAX & DUTY PURPOSES ONLY.PDF") self.assertEqual(rc,Milter.CONTINUE) + def test_getnames(self): + names = [] + self.sawpif = False + def do_part(m): + n = m.getnames() + a = names + a += n + return Milter.CONTINUE + def chk_part(m): + for k,n in m.getnames(): + if n and n.lower().endswith('.pif'): + self.sawpif = True + s = m.get_submsg() + print(m.get_content_type(),type(s),'modified:',m.ismodified()) + if isinstance(s,email.message.Message): + return mime.check_attachments(s,chk_part) + return Milter.CONTINUE + + with self.zf.open('virus7','r') as fp: + msg = mime.message_from_file(fp) + self.assertTrue(msg.ismultipart()) + mime.check_attachments(msg,do_part) + self.assertTrue(('filename','application.pif') in names) + self.assertFalse(self.sawpif) + mime.check_attachments(msg,chk_part) + self.assertTrue(self.sawpif) + def testHTML(self,fname=""): result = StringIO() filter = mime.HTMLScriptFilter(result)