From 8b08a3eeefe733a1367f27afcbfc40733486334a Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sat, 25 Feb 2012 15:51:53 +0100 Subject: Rename spamclassify.py --- maildirlearn.py | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ spamclassify.py | 128 -------------------------------------------------------- 2 files changed, 128 insertions(+), 128 deletions(-) create mode 100755 maildirlearn.py delete mode 100755 spamclassify.py diff --git a/maildirlearn.py b/maildirlearn.py new file mode 100755 index 0000000..7c40c27 --- /dev/null +++ b/maildirlearn.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 +# Lars-Dominik Braun +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os, re, sys, subprocess, pyinotify + +class Classifier (object): + # files in junk are spam + SPAMDIR = re.compile (r'mail/\.Junk/(new|cur)') + # exclude: Unsure messages, temporary directory, trashed messages (see + # http://cr.yp.to/proto/maildir.html), dovecot files + EXCLUDE = re.compile (r'mail/(\.Unsure/(new|cur)|[^/]+/(tmp|.*:2,[A-S]*T[U-Z]*$)|.*dovecot)') + + SPAM = 1 + HAM = 2 + UNSURE = 3 + + def statusFromFile (self, path): + """ + filter mail through bogofilter and return spam status + """ + + ret = subprocess.call (['bogofilter', '-I', path]) + if ret == 2: + return self.UNSURE + elif ret == 1: + return self.HAM + elif ret == 0: + return self.SPAM + elif ret == 3: + raise Exception ('bogofilter returned error') + + def statusFromPath (self, path): + """ + get spam status from file path + """ + + if self.SPAMDIR.search (path): + return self.SPAM + else: + return self.HAM + + def isExcluded (self, path): + """ + is path excluded? + """ + + return self.EXCLUDE.search (path) + + def setStatus (self, curStatus, newStatus, path): + """ + tell bogofilter to set new spam status for message + """ + if curStatus != newStatus: + bogoopts = None + if curStatus == self.UNSURE: + if newStatus == self.HAM: + bogoopts = '-n' + elif newStatus == self.SPAM: + bogoopts = '-s' + elif curStatus == self.SPAM and newStatus == self.HAM: + bogoopts = '-Sn' + elif curStatus == self.HAM and newStatus == self.SPAM: + bogoopts = '-Ns' + print 'bogoopts %s' % bogoopts + ret = subprocess.call (['bogofilter', bogoopts, '-I', path]) + print 'bogofilter returned %i' % ret + return True + else: + return False + + + def updateStatus (self, path): + """ + does all the magic + """ + if self.isExcluded (path): + return False + curStatus = self.statusFromFile (path) + newStatus = self.statusFromPath (path) + return self.setStatus (curStatus, newStatus, path) + +class EventHandler(pyinotify.ProcessEvent): + def __init__ (self, wm, mask, classifier): + pyinotify.ProcessEvent.__init__ (self) + + self.wm = wm + self.mask = mask + self.classifier = classifier + + def process_IN_MOVED_TO (self, event): + self.classifier.updateStatus (event.pathname) + + def process_IN_CREATE (self, event): + # make sure new directories are watched as well + if event.mask & pyinotify.IN_ISDIR: + wdd = self.wm.add_watch(event.pathname, self.mask, rec=True) + else: + self.classifier.updateStatus (event.pathname) + +if __name__ == '__main__': + c = Classifier () + wm = pyinotify.WatchManager() + mask = pyinotify.IN_MOVED_TO | pyinotify.IN_CREATE + handler = EventHandler(wm, mask, c) + notifier = pyinotify.Notifier(wm, handler) + wdd = wm.add_watch(os.path.expanduser ('mail/'), mask, rec=True) + notifier.loop() + diff --git a/spamclassify.py b/spamclassify.py deleted file mode 100755 index 7c40c27..0000000 --- a/spamclassify.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 -# Lars-Dominik Braun -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -import os, re, sys, subprocess, pyinotify - -class Classifier (object): - # files in junk are spam - SPAMDIR = re.compile (r'mail/\.Junk/(new|cur)') - # exclude: Unsure messages, temporary directory, trashed messages (see - # http://cr.yp.to/proto/maildir.html), dovecot files - EXCLUDE = re.compile (r'mail/(\.Unsure/(new|cur)|[^/]+/(tmp|.*:2,[A-S]*T[U-Z]*$)|.*dovecot)') - - SPAM = 1 - HAM = 2 - UNSURE = 3 - - def statusFromFile (self, path): - """ - filter mail through bogofilter and return spam status - """ - - ret = subprocess.call (['bogofilter', '-I', path]) - if ret == 2: - return self.UNSURE - elif ret == 1: - return self.HAM - elif ret == 0: - return self.SPAM - elif ret == 3: - raise Exception ('bogofilter returned error') - - def statusFromPath (self, path): - """ - get spam status from file path - """ - - if self.SPAMDIR.search (path): - return self.SPAM - else: - return self.HAM - - def isExcluded (self, path): - """ - is path excluded? - """ - - return self.EXCLUDE.search (path) - - def setStatus (self, curStatus, newStatus, path): - """ - tell bogofilter to set new spam status for message - """ - if curStatus != newStatus: - bogoopts = None - if curStatus == self.UNSURE: - if newStatus == self.HAM: - bogoopts = '-n' - elif newStatus == self.SPAM: - bogoopts = '-s' - elif curStatus == self.SPAM and newStatus == self.HAM: - bogoopts = '-Sn' - elif curStatus == self.HAM and newStatus == self.SPAM: - bogoopts = '-Ns' - print 'bogoopts %s' % bogoopts - ret = subprocess.call (['bogofilter', bogoopts, '-I', path]) - print 'bogofilter returned %i' % ret - return True - else: - return False - - - def updateStatus (self, path): - """ - does all the magic - """ - if self.isExcluded (path): - return False - curStatus = self.statusFromFile (path) - newStatus = self.statusFromPath (path) - return self.setStatus (curStatus, newStatus, path) - -class EventHandler(pyinotify.ProcessEvent): - def __init__ (self, wm, mask, classifier): - pyinotify.ProcessEvent.__init__ (self) - - self.wm = wm - self.mask = mask - self.classifier = classifier - - def process_IN_MOVED_TO (self, event): - self.classifier.updateStatus (event.pathname) - - def process_IN_CREATE (self, event): - # make sure new directories are watched as well - if event.mask & pyinotify.IN_ISDIR: - wdd = self.wm.add_watch(event.pathname, self.mask, rec=True) - else: - self.classifier.updateStatus (event.pathname) - -if __name__ == '__main__': - c = Classifier () - wm = pyinotify.WatchManager() - mask = pyinotify.IN_MOVED_TO | pyinotify.IN_CREATE - handler = EventHandler(wm, mask, c) - notifier = pyinotify.Notifier(wm, handler) - wdd = wm.add_watch(os.path.expanduser ('mail/'), mask, rec=True) - notifier.loop() - -- cgit v1.2.3