[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: SA-learn on remote host



On Fri, Sep 14, 2007 at 09:23:16PM +0100, John K Masters <johnmasters@oxtedonline.net> was heard to say:
> I am gradually implementing a mail system where I have a mail-server on
> host1 running Postfix/Courier/Procmail/spamc which passes all except
> whitelisted mail to spamd on another server - host2. host2 simply runs
> the mail through SA and passes it back to host1 from which I read on my
> local box via Mutt. 
> 
> Most spam gets filtered into the .Spam folder and I have bound keys in
> Mutt to move missed spam to this folder and to copy good messages to a
> .Ham folder.
> 
> What I would like to do now is have a cronjob run the contents of these
> two folders through SA-learn and then delete them. ATM I am stumped as
> to how to go about this. Any pointers very welcome.

  I use IMAP to synchronize my mail across systems (sounds like you do
too?), and just run the attached script over folders holding spam and
ham to learn.  (warning: it's quick and dirty, won't work for anyone
else without tweaks!)

  Daniel
#!/usr/bin/python
#
#  Process spam in the maildir ~/Mail/spam-to-learn and ham in the
#  maildir ~/Mail/ham-to-learn, clearing both maildirs as we work.
#  This is meant to be run as a cronjob and will lock other instances
#  of itself out.  Note: the locking mechanism assumes that flock()
#  behaves sanely; you may not want to use this if you have a
#  networked $HOME.  (it has the benefit that the lock is
#  automatically dropped if the process dies unexpectedly)

import fcntl
import os
import sys

home = os.environ['HOME']
lockfile = '%s/.learnspam-lock' % home

f = file(lockfile, 'w')

try:
    fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
except IOError:
    print 'learnspamjob already running'
    sys.exit(0)

quiet = not os.isatty(1)



def dolistdir(dirname):
    return ['%s/%s'%(dirname, x) for x in os.listdir(dirname)]

# Process and delete each message in the maildir with the given
# command template.
def process_maildir(dname, cmd):
    files = dolistdir('%s/cur'%dname) + dolistdir('%s/new'%dname)

    for f in files:
        rval = os.system(cmd % f)

        if not os.WIFEXITED(rval):
            if os.WIFSIGNALED(rval):
                msg = '"%s" terminated with signal %d' % (cmd % f, os.WTERMSIG(rval))
            elif os.WIFSTOPPED(rval):
                msg = '"%s" unexpectedly stopped' % (cmd % f)
            elif os.WIFCONTINUED(rval):
                msg = '"%s" unexpectedly continued' % (cmd % f)

            if os.WCOREDUMP(rval):
                msg += ' (core dumped)'

            sys.stderr.write('ERROR processing %s: %s\n'%(f, msg))
        elif os.WEXITSTATUS(rval) <> 0:
            sys.stderr.write('ERROR processing %s: "%s" exited with status %d'%(f, cmd % f, os.WEXITSTATUS(rval)))
        else:
            try:
                os.unlink(f)
            except OSError, e:
                sys.stderr.write('Unable to unlink %s: %s\n'%(f, e.strerror))


process_maildir('%s/Mail/spam-to-learn' % home, 'spamassassin -r %s > /dev/null')
process_maildir('%s/Mail/ham-to-learn' % home, 'sa-learn --ham %s > /dev/null')

Reply to: