-paul
#!/usr/bin/python
print_signature = 1
filter_viruses = 1
# Usage:
# exim-filter-mime.py <mime-type> ...
#
# Example:
# exim-filter-mime.py audio image/jpg video
#
# This script reads from stdin and writes to stdout.
# It strips all the mime attachments from a mail message
# that are one of the mime types listed on the command line
#
# Exim can use it in its configuration file, for example, as follows:
#
# remote_smtp:
# driver = smtp
# .
# .
# .
# transport_filter = /etc/exim-filter-mime.py audio video image
#
#
# Note that the files /etc/exim-signature.html and /etc/exim-signature
# must exist and be world readable.
have_written_signature = 0
have_written_html_signature = 0
attachment_count = 0
# The attachment is replaced with the following:
def cheeky_response (part):
print "[File `%s' of type `%s' is meant to go here]" % (part.getheader('Content-Description'), string.lower (part.gettype ()))
print
print "This host is restricted from transmitting %s files and" % (string.lower (part.getmaintype ()),)
print "hence this attachment was stripped from the mail message."
print
def cheeky_viruswarning (part):
print "[File `%s' is meant to go here]" % (part.getheader('Content-Description'))
print
print "This host is restricted from transmitting .vbs, .exe, .bat and other files"
print "due to potential virus hazards, and hence this attachment was stripped from"
print "the mail message."
print
def write_signature():
sys.stdout.write (open ("/etc/exim-signature").read())
sys.stdout.write ("\n");
def write_html_signature():
sys.stdout.write (open ("/etc/exim-signature.html").read())
sys.stdout.write ("\n");
def write_header(s):
if len (s) > 256:
s = s[:255] + "\n"
sys.stdout.write (s)
def process_part (part, boundaries, keepheader):
global attachment_count
global have_written_signature
global have_written_html_signature
l = None
not_allowable_mimetype = 0
not_allowable_filetype = 0
if string.lower (part.getmaintype ()) in sys.argv[1:] or string.lower (part.gettype ()) in sys.argv[1:]:
not_allowable_mimetype = 1
if filter_viruses:
# perlre(1) says that `(?>pattern)' is the same as `(?=(pattern))\1'
# Otherwise, these are taken from the regular expressions in http://www.exim.org/system_filter.exim
if re.search ( \
'name=("[^"]+\\.(?:vb[se]|ws[fh]|jse?|exe|com|shs|bat)"|[\\w.-]+\\.(?:vb[se]|ws[fh]|jse?|exe|com|shs|bat))' \
, string.join (part.getplist ())):
not_allowable_filetype = 1
if re.search ( \
'(?:Content-(?:Type:(?=(\\s*))\\1[\\w-]+/[\\w-]+|Disposition:(?=(\\s*))\\1attachment);(?=(\\s*))\\1(?:file)?name=|begin(?=(\\s+))\\1[0-7]{3,4}(?=(\\s+))\\1)("[^"]+\\.(?:vb[se]|ws[fh]|jse?|exe|com|shs|bat)"|[\\w.-]+\\.(?:vb[se]|ws[fh]|jse?|exe|com|shs|bat))[\\s;]' \
, string.join (part.headers)):
not_allowable_filetype = 1
if not_allowable_filetype or not_allowable_mimetype:
# Generate a new header
if keepheader:
for l in message.headers:
if not re.match ("^Content-[^:]*: ", l):
write_header (l)
print "Content-Type: TEXT/plain; charset=us-ascii"
print
# Then give a cheeky message of our own:
if not_allowable_mimetype:
cheeky_response (part)
else:
cheeky_viruswarning (part)
# Skip through the actually message body:
l = " "
while not l in boundaries:
l = part.fp.readline ()
# write the boundary:
sys.stdout.write (l)
else:
# if it is anything else (like text/plain, application/octet-stream etc.
# then write the header...
p = ""
for p in part.headers:
write_header (p)
print
# ... and then write the body
l = " "
attachment_count = attachment_count + 1
while not l in boundaries:
l = part.fp.readline ()
# now add a signature onto the first html or plain text part of the mail...
if print_signature:
if l in boundaries:
if not have_written_signature:
if string.lower (part.gettype ()) == "text/plain":
have_written_signature = 1
write_signature ();
if not have_written_html_signature:
if string.lower (part.gettype ()) == "text/html":
have_written_html_signature = 1
write_html_signature ();
if l:
sys.stdout.write (l)
#...but not after first two attachments.
if attachment_count >= 2:
have_written_html_signature = 1
have_written_signature = 1
return l
import sys, mimetools, re, string
message = mimetools.Message (sys.stdin, 0)
# Not a multipart message, so just dump the whole thing:
if message.getmaintype () != "multipart":
process_part (message, [None, ""], 1)
if print_signature:
write_signature ()
sys.exit (0)
# Print out the header:
for l in message.headers:
write_header (l)
print
# Mime boundaries:
boundaries = [None, "", "--" + message.getparam ("boundary") + "\n", "--" + message.getparam ("boundary") + "--\n"]
# Read and write the initial part of the message up to the
# first boundary. This will usually explain that this is a
# MIME message:
l = " "
while not l in boundaries:
l = message.fp.readline ()
sys.stdout.write (l)
while l and l != boundaries[-1]:
part = mimetools.Message (message.fp, 0)
l = process_part (part, boundaries, 0)
# write any trailing stuff
sys.stdout.write (message.fp.read())