[Pymilter] Emulating another MimeDefang function

Larry G. Wapnitsky LWapnitsky at ph.wrtdesign.com
Mon Nov 21 15:30:01 EST 2011


Same thing happened with a message from GMail

Larry G. Wapnitsky MBA, MCSE, MCP+I
IT SUPPORT & ADMINISTRATION COORDINATOR
WRT  |  Wallace Roberts & Todd, LLC
1700 Market Street, 28th Fl
Philadelphia, PA 19103
T  215.430.5068
C  215.713.8635
E  lwapnitsky at WRTdesign.com


-----Original Message-----
From: Larry G. Wapnitsky 
Sent: Monday, November 21, 2011 3:08 PM
To: Stuart D. Gathman
Subject: RE: [Pymilter] Emulating another MimeDefang function

OK...still puzzling through the defang stuff.  I'm trying to trace
through and still don't see what I'm looking for.

As for the part about misreporting the multiparts, I'm attaching a file
to a message in Thunderbird and sending it through my mail server.  I
have the output logged for diagnostics as follows:


2011Nov21 15:11:23 milter startup
2011Nov21 15:11:30 [1] connect from [10.102.50.66] at ('10.102.50.66',
51781)
2011Nov21 15:11:30 [1] False
2011Nov21 15:11:30 [1] This is a multi-part message in MIME format.
--------------090109040705000201000008
Content-Type: multipart/alternative;
 boundary="------------080609030809060906010707"


--------------080609030809060906010707
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

test message*2*

--------------080609030809060906010707
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>
  <head>

    <meta http-equiv="content-type" content="text/html;
charset=ISO-8859-1">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    test message<b>2</b><br>
  </body>
</html>

--------------080609030809060906010707--

--------------090109040705000201000008
Content-Type: text/x-perl;
 name="hashtest1.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="hashtest1.pl"

#/usr/bin/env perl
use Digest::SHA1;

$sha1 = Digest::SHA1->new;

open $fh, $ARGV[0] or die $!;
$sha1->addfile($fh);

$digest = $sha1->hexdigest;

print $digest, "    $ARGV[0]\n";

close FILE;

--------------090109040705000201000008--

2011Nov21 15:11:30 [1] text/plain
Removing /tmp/py_testmilter.sock
2011Nov21 15:11:35 bms milter shutdown


Below is my working code.  Please note, I've only been working in Python
for about 1 week:



#! /usr/bin/env python

import Milter
import StringIO
import email
import email.message
import mime
import rfc822
import sys
import tempfile
import time
import unittest

from email import Errors

## ==  IP Information
from socket import AF_INET, AF_INET6
## ==

## === Define multiprocessing == ##

if True:
    from multiprocessing import Process as Thread, Queue
else:
    from threading import Thread
    from Queue import Queue

logq = Queue(maxsize=4)


def background():
    while True:
        t = logq.get()
        if not t: break
        msg,id,ts = t
        print "%s [%d]" % (time.strftime('%Y%b%d
%H:%M:%S',time.localtime(ts)),id),
        # 2005Oct13 02:34:11 [1] msg1 msg2 msg3 ...
        for i in msg: print i,
        print

## === End Define Multiprocesing === ##

class mltr_SaveAttachments(Milter.Base):

    def __init__(self):
        self.id = Milter.uniqueID()

    def log(self,*msg):
        logq.put((msg,self.id,time.time()))
    
    def connect(self, IPname, family, hostaddr):
        self.IP = hostaddr[0]
        self.port = hostaddr[1]
        if family == AF_INET6:
            self.flow = hostaddr[2]
            self.scope = hostaddr[3]
        else:
            self.flow = None
            self.scope = None
        self.IPname = IPname # Name from a reverse IP lookup
        self.H = None
        self.fp = None
        self.receiver = self.getsymval('j')
        self.log("connect from %s at %s" % (IPname, hostaddr) )
        return Milter.CONTINUE

    

    def envfrom(self,mailfrom,*str):
        # self.F = mailfrom
        # self.R = []
        # self.fromparms = Milter.dictfromlist(str)
        # self.user = self.getsymval('{auth_authen}')
        # self.log("mail from:", mailfrom, *str)
        self.fp = StringIO.StringIO()
        # self.canon_from = '@'.join(parse_addr(mailfrom))
        # self.fp.write('From %s %s\n' % (self.canon_from,time,ctime()))
        return Milter.CONTINUE

    def body(self, chunk):
        self.fp.write(chunk)
        return Milter.CONTINUE
  
    def replacebody(self,chunk):
       if self._body:
            self._body.write(chunk)
            self.bodyreplaced = True
#            self.log("mail body chunk")
#            self.log(chunk)
            return Milter.CONTINUE
       else:
            raise IOError,"replacebody not called from eom()"
            return Milter.TEMPFAIL

    def attachment(self):
#       parts = self._msg.get_payload()
#       self.log(len(parts))
#       self.log(parts)
#       for p in parts:
#           self.log("part")
        self.log(self._msg.ismultipart())
        parts = self._msg.get_payload()
        self.log(parts)
        t = self._msg.get_content_type().lower()
        self.log(t)
        


    def eom(self):
        self.fp.seek(0)
        #msg = email.message_from_file(self.fp)
        msg = mime.message_from_file(self.fp)
        self._msg = msg;
        self.attachment()

        self._body = StringIO.StringIO()


        self.tempname = fname = tempfile.mktemp(".tmp")
#        self.log(self.tempname)
        
        out = tempfile.TemporaryFile()
        
        try:
            msg.dump(out)
            out.seek(0)
            msg = rfc822.Message(out)
        
            msg.rewindbody()
            while 1:
                buf = out.read(8192)
                if len(buf) == 0: break
                self.replacebody(buf)
#            return Milter.ACCEPT
            return Milter.TEMPFAIL
        finally:
            out.close()
        return Milter.TEMPFAIL
        

## ===

def main():
    bt = Thread(target=background)
    bt.start()
    socketname = "/tmp/py_testmilter.sock"
    timeout = 600
    Milter.factory = mltr_SaveAttachments
    flags = Milter.CHGBODY + Milter.CHGHDRS + Milter.ADDHDRS
    flags += Milter.ADDRCPT
    flags += Milter.DELRCPT
    Milter.set_flags(flags)     # tell Sendmail/Postfix which features
we use
    print "%s milter startup" % time.strftime('%Y%b%d %H:%M:%S')
    sys.stdout.flush()
    Milter.runmilter("py_testmilter",socketname,timeout)
    logq.put(None)
    bt.join()
    print "%s bms milter shutdown" % time.strftime('%Y%b%d %H:%M:%S')

if __name__ == "__main__":
    main()



-----Original Message-----
From: Stuart D. Gathman [mailto:stuart at bmsi.com]
Sent: Mon 2011-11-21 15:03
To: Larry G. Wapnitsky
Subject: RE: [Pymilter] Emulating another MimeDefang function
 
On Mon, 21 Nov 2011, Larry G. Wapnitsky wrote:

> I still don't see how this is getting me the filenames I need.  Also,

The check= argument to defang is a function that is passed the filename.

> check_attachment seems to be recursive and references all the defang 
> functions, hence increasing my confusion.

MIME is a recursive structure, hence any attachment and/or filename
enumeration must be recursive.

> Additionally, when I send a multipart MIME message to my through my 
> server, ismultipart() reports false, but output of the message parts 
> says my message is mime multipart.

You will have to provide a specific example.

--
 	      Stuart D. Gathman <stuart at bmsi.com>
     Business Management Systems Inc.  Phone: 703 591-0911 Fax: 703
591-6154 "Confutatis maledictis, flammis acribus addictis" - background
song for a Microsoft sponsored "Where do you want to go from here?"
commercial.





----wrtmail--%3423wrt%----



More information about the Pymilter mailing list