[Pymilter] Emulating another MimeDefang function

Larry G. Wapnitsky LWapnitsky at ph.wrtdesign.com
Wed Nov 23 10:38:22 EST 2011


So, I was able to remove the attachments in a function I've written, but
when the message gets sent, the attachments are still there rather than
my modified message.  Not sure what I'm missing.

Code below:


#! /usr/bin/env python

import Milter
import StringIO
import email
import email.Message
import hashlib
import mime
import os
import sys
import tempfile
import time
import rfc822


from email import Errors
from email.Message import Message

## ==  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

    @Milter.noreply
    def header(self, name, hval):
        self.fp.write("%s: %s\n" % (name,hval)) # add header to buffer
        return Milter.CONTINUE

    @Milter.noreply
    def eoh(self):
        self.fp.write("\n")                             # terminate
headers
        return Milter.CONTINUE



    def envfrom(self,mailfrom,*str):
#        self.log("envfrom")
        # 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 attachment(self):
        msg = self._msg
        attachDir = attach_dir(msg)
        removedParts = []

        for part in msg.walk():
            fname = ""

            if part.is_multipart():
                continue

            dtypes = part.get_params(None, 'Content-Disposition')

            if not dtypes:
                if part.get_content_type() == 'text/plain':
                    continue
                ctypes = part.getparams()
                if not ctypes:
                    continue
                for key,val in ctypes:
                    if key.lower() == 'name':
                        fname = val
            else:
                for key,val in dtypes:
                    if key.lower() == 'filename':
                        fname = val

            if fname:
                removedParts.append(fname)
                data = part.get_payload(decode=1)
                extract_attachment(data, attachDir, fname)
                part = delete_attachments(part)

        self.log(removedParts)
#        return Milter.CONTINUE
        return msg


    def eom(self):
        self.fp.seek(0)
        self._msg = mime.message_from_file(self.fp)
        self._msg = self.attachment()

        self.log(self._msg)
        return Milter.ACCEPT
#        return Milter.TEMPFAIL
## ===


def delete_attachments(part):
    for key,value in part.get_params():
        part.del_param(key)

    part.set_payload('[DELETED]\n')
    part.set_type('text/plain')
    del part['Content-Disposition']

    return part



def attach_dir(msg):
    tempname = fname = tempfile.mktemp(".tmp")
    out = tempfile.TemporaryFile()
    msg.dump(out)
    out.seek(0)
    buf = out.read()
    hashDir = hashit(buf)
    attachDir = dropDir + hashDir

    if not os.path.isdir(hashDir):
        os.mkdir(attachDir)

    return attachDir


def extract_attachment(data, attachDir, fname):
    exdir_file = attachDir + "/" + fname
    extracted = open(exdir_file, "wb")
    extracted.write(data)
    extracted.close()



def hashit(data):
    sha1 = hashlib.sha1()
    # f = open(filepath, 'rb')
    # try:
    #     sha1.update(f.read())
    # finally:
    #     f.close()
    sha1.update(data)

    return sha1.hexdigest()

dropDir = "/dropdir/"

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: Monday, November 21, 2011 3:43 PM
To: Larry G. Wapnitsky
Cc: pymilter at bmsi.com
Subject: RE: [Pymilter] Emulating another MimeDefang function

On Mon, 21 Nov 2011, Larry G. Wapnitsky wrote:

> Will try this.

If you were curious about the standard place for filenames (as opposed
the many places LookOut checks), look at the get_filename() method in
email.Message (python comes with source).  It looks first in the
Content-Disposition header field for the filename attribute (the
"correct"
place), and secondly in the name attribute of Content-Type.

--
 	      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%----

<!DSPAM:133D113DA422445417198307>




More information about the Pymilter mailing list