[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