# -*- mode: python; indent-tabs-mode: t -*- import os import os.path import subprocess import datetime import re # # Mail attribute utilities def mailman_domain(mail, domain): """ Return a string that is the list-name for a mailman domain """ m = mail["List-Id"].matches("^(.*<|)([^<]*)\."+re.escape(domain)) if m: return m.group(2) for hdr in [ 'To', 'Cc', 'From' ]: m = mail[hdr].matches("((\w|-)*)@"+re.escape(domain)) if m: if mail["Subject"].contains("["+m.group(1)+"]"): return m.group(1) return None def ezmlm_domain(mail, domain): """ Return a string that is the list-name for a ezmlm domain """ m = mail["Mailing-List"].matches("^(.* )?(\w+)(-\S*)?@"+re.escape(domain)+"(;.*)?$") if m: return m.group(2) for hdr in [ 'To', 'Cc', 'From' ]: m = mail[hdr].matches("(\w)@"+re.escape(domain)) if m: return m.group(1) return None def majordomo_domain(mail, domain): """ Return a string that is the list-name for a majordomo domain """ m = mail["List-Id"].matches("^(.*<|)([^<]*)\."+re.escape(domain)) if m: return m.group(2) for hdr in [ 'To', 'Cc', 'From' ]: m = mail[hdr].matches("((\w|-)*)@"+re.escape(domain)) if m: return m.group(1) def is_to_or_from(mail, address): """ Return true if [mail] is to or from an address that contains [address]. """ return ( False or mail["From"].contains(address) or mail["Reply-To"].contains(address) or mail.target.contains(address)) def is_to_or_from_re(mail, address): """ Return true if [mail] is to or from an address that matches the regex [address]. """ return ( mail["From"].matches(address) or mail.target.matches(address)) # # bogofilter utilites def bogofilter_auto(mail): p = subprocess.Popen( ["bogofilter", "-u", "-v", "-I", mail.path], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) (output, _) = p.communicate() processor.log("*** Bogofilter result: {0!r}".format(output.rstrip())) if p.returncode not in [0, 1, 2]: processor.log_error( "Error running bogofilter: Return code = {0!r}".format( p.returncode)) return p.returncode def bogofilter_ham(mail): subprocess.call(["bogofilter", "-S", "-n", "-I", mail.path]) def bogofilter_spam(mail): subprocess.call(["bogofilter", "-N", "-s", "-I", mail.path]) # # The core of my filters def move_ham(mail, folder): y = datetime.datetime.now().year folder = "FOLDERS.Ham."+str(y)+folder dir = processor.maildir_base+"/"+folder if not os.path.isfile(dir+"/maildirfolder"): os.makedirs(dir+"/tmp", 0o777, True) os.makedirs(dir+"/new", 0o777, True) os.makedirs(dir+"/cur", 0o777, True) open(dir+"/maildirfolder", 'a').close() mail.move(folder) def my_whitelist(mail): return ( False or is_to_or_from(mail, "@opengroup.org") or is_to_or_from(mail, "@purestorage.com") or is_to_or_from(mail, "@vger.kernel.org") or is_to_or_from(mail, "Bryan@ChankTunUnGi.onmicrosoft.com") or is_to_or_from(mail, "cacnedcomms@gmail.com") or is_to_or_from(mail, "fsf.org") or is_to_or_from(mail, "gnu.org") or is_to_or_from(mail, "parabola.nu") or is_to_or_from(mail, "parabolagnulinux.org") or mail["From"] == "3174451635@mms.att.net" or mail["From"] == "MAILER-DAEMON@yahoo.com" or mail["From"].contains("@careereco.com") or mail["From"].contains("@ciholas.com") or mail["From"].contains("@e.oldnational.com>") or mail["From"].contains("@facebookmail.com>") or mail["From"].contains("@gandi.net") or mail["From"].contains("@github.com>") or mail["From"].contains("@goodwillindy.org>") or mail["From"].contains("@kickstarter.com>") or mail["From"].contains("@list.cr.yp.to") or mail["From"].contains("@lpi.org>") or mail["From"].contains("@lulzbot.com>") or mail["From"].contains("@mail.scribd.com>") or mail["From"].contains("@massdrop.com>") or mail["From"].contains("@msdlt.k12.in.us>") or mail["From"].contains("@parabola.nu") or mail["From"].contains("@post.oreilly.com>") or mail["From"].contains("@scouting.org>") or mail["From"].contains("@solutionsinplastic.com>") or mail["From"].contains("@startcom.org>") or mail["From"].contains("@usfirst.org>") or mail["From"].contains("@vectren.com") or mail["From"].contains("@vectrenemail.com") or mail["From"].contains("@wolframalpha.com>") or mail["From"].contains("Promo@email.newegg.com") or mail["From"].contains("info@email2.mysimplemobile.com") or mail["From"].contains("margieshu@sbcglobal.net") or mail["From"].contains("parabolagnulinux.org") or mail["From"].matches("@[a-z]+\.gandi\.net") or mail["List-Id"].matches(".*\.(gnu|gnome|archlinux|parabolagnulinuxlibre|fedorahosted)\.org") or mail["List-Id"].matches(".*\.parabola\.nu") or mail["Subject"].contains("[Dev]") or mail["Subject"].contains("[Maintenance]") or mail["Subject"].contains("[PATCH") or mail["Subject"].contains("[systemd-devel]") ) def my_filters(mail): # .software.* (GNU Mailman) for pair in [ [ 'gnu.org', 'gnu' ], # https://lists.gnu.org/mailman/options/bug-librejs/lukeshu@sbcglobal.net [ 'nongnu.org', 'nongnu' ], # https://lists.nongnu.org/mailman/options/libreboot/lukeshu@sbcglobal.net [ 'gnome.org', 'gnome' ], # https://mail.gnome.org/mailman/options/networkmanager-list/lukeshu@sbcglobal.net [ 'archlinux.org', 'archlinux' ], [ 'lists.freedesktop.org', 'freedesktop' ], [ 'lists.fedorahosted.org', 'fedorahosted' ], [ 'lists.arthurdejong.org', 'arthurdejong' ], [ 'lists.stanford.edu', 'stanford' ], [ 'mailman.stanford.edu', 'stanford' ], [ 'lists.parabola.nu', 'parabola' ], [ 'parabola.nu', 'parabola' ] ]: list = mailman_domain(mail, pair[0]) if list: move_ham(mail, ".software."+pair[1]+"."+list) return # .software.* (EZMLM) for pair in [ [ 'list.cr.yp.to', 'djb' ] ]: list = ezmlm_domain(mail, pair[0]) if list: move_ham(mail, ".software."+pair[1]+"."+list) return # .software.* (Majordomo) for pair in [ [ 'vger.kernel.org', 'kernel' ] ]: list = majordomo_domain(mail, pair[0]) if list: move_ham(mail, ".software."+pair[1]+"."+list) return # .software.parabola if ( False or is_to_or_from(mail, "parabolagnulinux.org") or is_to_or_from(mail, "parabola.nu") or is_to_or_from(mail, "kiwwwi.com.ar") ): move_ham(mail, ".software.parabola") return # .software.POSIX if is_to_or_from(mail, "austin-group-l@opengroup.org"): move_ham(mail, ".software.POSIX") return # .software.TravisCI if mail["From"].contains("builds@travis-ci.org"): move_ham(mail, ".software.TravisCI") return # .software for address in [ "@archlinux.org", "@canonical.org", "@cnuk.org", "@core3.amsl.com", "@defectivebydesign.org", "@eff.org", "@fedorahosted.org", "@foocorp.net", "@fsf.org", "@github.com", "@gitorious.org", "@gnome.org", "@gnu.org", "@ietf.org", "@kde.org", "@lists.fedorahosted.org", "@mozilla.org", "@nongnu.org", "@sourceforge.com", "@thyrsus.com", ]: if is_to_or_from(mail, address): move_ham(mail, ".software") return # .servers if ( False or mail["From"].contains("@gandi.net") or mail["From"].contains("@ramhost.us") or mail["From"].contains("@startcom.org") or mail["From"].contains("@startssl.com") or mail["From"].contains("@vultr.com") or (mail["From"].contains("@2co.com") and mail["Subject"].contains("RAM Host")) ): move_ham(mail, ".servers") return # .Social.* if mail["From"].matches("facebook(|mail)\.com"): move_ham(mail, ".Social.Facebook") return if mail["From"].matches("identi\.ca|statusnet"): move_ham(mail, ".Social.Identica") return if mail["From"].matches("twitter\.com"): move_ham(mail, ".Social.Twitter") return if mail["From"].matches("@xkcd\.com"): move_ham(mail, ".Social.xkcd") return if is_to_or_from(mail, "linkedin.com"): move_ham(mail, ".Social.LinkedIn") return # .BSA if ( False or mail["List-Id"].contains("troopmailinglist.troop276.net") or mail["Subject"].matches("troop") or mail["Subject"].matches("merit\s*badge") or is_to_or_from(mail, "t276_announcements@att.net") or is_to_or_from(mail, "Bryan@ChankTunUnGi.onmicrosoft.com") or is_to_or_from(mail, "basu@maharjan.org") or is_to_or_from(mail, "cacnedcomms@gmail.com") or is_to_or_from(mail, "crossroadsbsa.org") or is_to_or_from(mail, "dhoyt@yourhomecompany.com") or is_to_or_from(mail, "dllargent@comcast.net") or is_to_or_from(mail, "eldredmac@comcast.net")# MacDonell or is_to_or_from(mail, "jsting@sbcglobal.net") or is_to_or_from(mail, "mitchprather@sbcglobal.net") or is_to_or_from(mail, "muellerindy@yahoo.com") or is_to_or_from(mail, "mytroop.us") or is_to_or_from(mail, "oa_wap@yahoo.com") or is_to_or_from(mail, "salupo_vincent_p@lilly.com") or is_to_or_from(mail, "scouting.org") or is_to_or_from(mail, "solorzano.luis@rocketmail.com") or is_to_or_from(mail, "trdindy@comcast.net") or is_to_or_from(mail, "wjensen111@aol.com") ): move_ham(mail, ".BSA") return # .FRC for address in [ "@ni.com", "@usfirst.org", "@firstinspires.org" ]: if is_to_or_from(mail, address): move_ham(mail, ".FRC") return # .FRC.829 if ( False or mail["Subject"].matches("\b829\b") or is_to_or_from(mail, "wcxctrack829@aim.com") # Pat or is_to_or_from(mail, "william.walk@gmail.com") ): move_ham(mail, ".FRC.829") return # .FRC.1024 if ( False or mail["Subject"].matches("\b1024\b") or mail["Subject"].matches("kil-?a-?bytes") or is_to_or_from(mail, "BBonahoom@stanleyworks.com") or is_to_or_from(mail, "bryanbonahoom@gmail.com") or is_to_or_from(mail, "allison.m.babcock@gmail.com") or is_to_or_from(mail, "cdewalt3@yahoo.com") or is_to_or_from(mail, "dave.nelson@ecolab.com") or is_to_or_from(mail, "dickaustin190@yahoo.com") or is_to_or_from(mail, "djnels1@comcast.net") # Dave and Julie Nelson or is_to_or_from(mail, "gamefreak207@gmail.com") # Brett Leedy or is_to_or_from(mail, "jason.zielke@gmail.com") or is_to_or_from(mail, "jeffreysmith@msdlt.k12.in.us") or is_to_or_from(mail, "sarahlittell@comcast.net") or is_to_or_from(mail, "silioso@gmail.com") or is_to_or_from(mail, "skiplittell@comcast.net") or is_to_or_from(mail, "tswilson4801@att.net") ): move_ham(mail, ".FRC.1024") return # .FRC.4272 if ( False or mail["Subject"].matches("\b4272\b") or mail["Subject"].contains("[ME297]") or is_to_or_from(mail, "firstteam4272@gmail.com") or is_to_or_from(mail, "@tscstudents.net") or is_to_or_from(mail, "abenyeho@purdue.edu") or is_to_or_from(mail, "Henry65@purdue.edu") or is_to_or_from(mail, "chang282@purdue.edu") ): move_ham(mail, ".FRC.4272") return # .Purdue.* if ( False or mail["Subject"].contains("[PASE]") or is_to_or_from(mail, "Purduealumni@purdue.edu") or is_to_or_from(mail, "pase@purdue.edu") ): move_ham(mail, ".Purdue.PASE") return if mail["Subject"].contains("[PLUG]"): move_ham(mail, ".Purdue.PLUG") return if is_to_or_from(mail, "@cerias.purdue.edu"): move_ham(mail, ".Purdue.CERIAS") return if ( False or is_to_or_from(mail, "purduehackers@gmail.com") or is_to_or_from(mail, "royfu@purdue.edu") or is_to_or_from(mail, "usmannkhan@purdue.edu") ): move_ham(mail, ".Purdue.Hackers") return if ( False or mail["Subject"].contains("[CS Opportunity Update]") or mail["Subject"].contains("[CS Majors]") ): move_ham(mail, ".Purdue.CS") return if ( False or is_to_or_from(mail, "askcco@purdue.edu") or is_to_or_from_re(mail, "pmx-auto-approve\+.*@purdue\.edu") or is_to_or_from(mail, "evertrue@purdue.edu") or is_to_or_from(mail, "college.response@purdue.edu") or is_to_or_from(mail, "purduepresident@purdue.edu") or is_to_or_from(mail, "@prf.org") ): move_ham(mail, ".Purdue.misc") return # .misc.* if mail["From"].matches("schwab\.com"): move_ham(mail, ".misc.schwab") return if mail["From"].matches("@ebay\.com"): move_ham(mail, ".misc.ebay") return if ( False or is_to_or_from(mail, "margieshu@sbcglobal.net") or is_to_or_from(mail, "3174451635@mms.att.net") ): move_ham(mail, ".misc.Mom") return for address in [ "@lpi.org", "@pearson.com", "ciscotraining-notify@cisco.com", "CompTIA", ]: if mail["From"].contains(address): move_ham(mail, ".misc.CompTIA") return if ( False or mail["From"].contains("newsletter") or mail["From"].contains("announcements") or mail["Subject"].contains("newsletter") or mail["Message-Id"].contains("@sailthru.com") or False or (mail["From"].contains("@sparkfun.com") and mail["Message-Id"].contains("rsgsv.net")) or (mail["From"].contains("no-reply@kickstarter.com") and mail["Message-Id"].contains(".sendgrid.net")) or (mail["From"].contains("no-reply@kickstarter.com") and ( False or mail["Subject"].contains("Projects We Love:") or mail["Subject"].contains("Project Update"))) or mail["From"].contains("Info@mailing.jamendo.com") or mail["From"].contains("Promo@email.newegg.com") or mail["From"].contains("auto@comicsbyemail.com") or mail["From"].contains("info@demandprogress.org") or mail["From"].contains("info@email2.mysimplemobile.com") or mail["From"].contains("info@massdrop.com") or mail["From"].contains("info@lulzbot.com") or mail["From"].contains("oreilly.com") or mail["From"].contains("reply-to@e.digikey.com") or mail["From"].contains("communication@communications.bmv.in.gov") or mail["From"].contains("sales@solutionsinplastic.com") or mail["From"].contains("social@goodwillindy.org") or mail["From"].contains("support@support.digitalocean.com") or mail["From"].contains("@pardonsnowden.org") ): move_ham(mail, ".misc.Newsletters") return if ( False or mail["From"].matches("@localhost") or mail["From"].matches("@[^,>]*\.local") or mail["From"].matches("@[^,>]*\.lan") or mail["To"].matches("luke@") ): move_ham(mail, ".misc.LocalSystems") return if ( False or mail["Subject"].contains("password") or mail["Subject"].contains("account") or mail["From"].contains("accounts") ): move_ham(mail, ".misc.accounts") return move_ham(mail, "") # # call the above def handle_incoming_ham_training(mail): bogofilter_ham(mail) handle_incoming_ham(mail) def handle_incoming_spam_training(mail): bogofilter_spam(mail) mail.move("FOLDERS.Spam") def handle_incoming_ham(mail): my_filters(mail) def handle_incoming_spam(mail): mail.move("FOLDERS.Spam") def handle_incoming_unknown(mail): # Whitelist if my_whitelist(mail): handle_incoming_ham_training(mail) return spam = bogofilter_auto(mail) if spam == 0: handle_incoming_spam(mail) return elif spam == 1: handle_incoming_ham(mail) return elif spam == 2: mail.move("FOLDERS.MysteryMeat") return else: mail.move("FOLDERS.BogoFail") return # hook the above functions into the maildirproc processor processor.maildir_base = "~/Maildir" processor.auto_reload_rcfile = True handle_mapping = { "Inbox": handle_incoming_unknown, "Bulk Mail": handle_incoming_unknown, # fucking Yahoo! "FOLDERS.Spam.training": handle_incoming_spam_training, "FOLDERS.Ham.training": handle_incoming_ham_training, } processor.maildirs = handle_mapping.keys() for mail in processor: handle_mapping[mail.maildir](mail)