#!/usr/local/bin/python # # scanmailboxes.py - Scan mailboxes can can as spam based on user settings # Copyright 2007 Eric Shane Radman # # This is free software; you may redistribute, modify, and use it under the # terms of the Modified BSD License. import psycopg import os import sys from time import gmtime, strftime from flock import flock def main(): lock = flock('scanmailboxes.lock', True).acquire() if lock: print 'doing stuff' scan() else: print 'waiting for previous process to finish' def scan(): # Database Connectivity PGCONN = "dbname=system user=abc password=123" # External spam filter command cmdCHECK = "/usr/pkg/bin/spamc -u mail -c" # Vmail path and ownership VMAILPATH = "/var/mail" # the program ID this script PID = "/var/run/scanmailboxes.pid" # Only users who receive mail are filtered sqlMAILBOXES = "SELECT email,spamlimit \ FROM users \ WHERE mail='y' AND spamlimit < 7 \ ORDER BY email;" # Some default values uid = 4000 gid = 4000 db = psycopg.connect(PGCONN) cursor = db.cursor() cursor.execute(sqlMAILBOXES ) rows = cursor.fetchall() cursor.close() db.close() #Iterate through mailboxes for row in rows: if row[0] == None: continue emailparts = row[0].split("@") spamlimit = row[1] # If it's not a valid e-mail address, don't try to parse it! if len(emailparts) <> 2: continue; queuefolder = "%s/%s/%s/.Queue" % (VMAILPATH, emailparts[1], emailparts[0]) mailfolder = "%s/%s/%s" % (VMAILPATH, emailparts[1], emailparts[0]) junkfolder = "%s/%s/%s/.Junk" % (VMAILPATH, emailparts[1], emailparts[0]) # List messes in each folder if os.path.isdir(mailfolder): print mailfolder if not os.path.isdir("%s/new" % queuefolder): continue; folders = os.listdir("%s/new" % queuefolder) for files in folders: print files # Find the spam rating of each file and move them to the # appropriate folders This assumes that SpamAssassin is # being used to output a spam level result = os.popen("cat %s/new/%s | %s" % (queuefolder, files, cmdCHECK)) score = result.read().split("/") # Test to see if it's spam. The spamlimit for each # individual is pulled from the database. if float(score[0]) >= float(spamlimit): # If junkfolder exists, it is assumed that the other # folders exist as well if not os.path.isdir(junkfolder): try: os.mkdir("%s" % junkfolder, 0700) os.mkdir("%s/new" % junkfolder, 0700) os.mkdir("%s/cur" % junkfolder, 0700) os.mkdir("%s/tmp" % junkfolder, 0700) # maildir++ requires a blank file in # indicated that is a subfolder file = open("%s/maildirfolder" % junkfolder, 'w') file.close() except IOError, message: "Error %d:\n%s" % (message[ 0 ], message[ 1 ]) try: os.chown("%s" % junkfolder, uid, gid) os.chown("%s/new" % junkfolder, uid, gid) os.chown("%s/cur" % junkfolder, uid, gid) os.chown("%s/tmp" % junkfolder, uid, gid) os.chown("%s/maildirfolder" % junkfolder, uid, gid) except IOError, message: print "Error %d:\n%s" % (message[0], message[1]) # Move the e-mail to the trash print "%s > %s Junk" % (score[0], spamlimit) try: os.rename("%s/new/%s" % (queuefolder, files), "%s/cur/%s" % (junkfolder, files)) except OSError, message: print "Error %d:\n%s" % (message[0], message[1]) else: # Keep the e-mail print "%s < %s Pass" % (score[0], spamlimit) try: os.rename("%s/new/%s" % (queuefolder, files), "%s/new/%s" % (mailfolder, files)) except OSError, message: print "Error %d:\n%s" % (message[0], message[1]) if __name__ == "__main__": main()