On Wed, Sep 30, 2020 at 12:03:41PM +0100, Sam Kuper wrote: > On Tue, Sep 29, 2020 at 08:13:14AM +0100, Chris Green wrote: > > On Mon, Sep 28, 2020 at 05:48:38PM -0500, Derek Martin wrote: > >> I confess to some curiosity here... What are you doing in your > >> home-grown MDA, that you could not already do with procmail, which > >> (if you're on a Linux system at least) your mail system is most > >> likely already using to deliver your mail? > > > > It's all driven from one text file so that when I subscribe to a new > > mailing list all I have to do is add an entry to that file. No > > changing of procmail rules, no additions to muttrc. I have attached > > the filter file to this message, the comments explain it at least as > > well as I can here. [..] > > > > # Mail filterfile, used to generate Mutt aliases and for filtering > > # mail into mailboxes, it's used by:- > > # getAliases.py - generates mutt aliases for the mailing lists > > # getLists.py - generates list names for mutt 'subscribe' and > > # 'lists' commands > > # filter.py - called by .forward, delivers mail to appropriate > > # mail box > > Nice! If you would be willing to publish/share the Python files (under > a Free Software license), that would be great :) > Absolutely no problem, is there a place to put them on mutt.org? I've attached them here anyway. I've recently upgraded them to Python 3 and, of course, to maildir. If anyone wants the mbox versions I could probably provide them as I keep the code in mercurial.
-- Chris Green
#!/usr/bin/python3 # # # Mail filtering script # import mailbox import os import sys import time import mailLib import shlex # # # Redirect any exceptions to a file # sys.stderr = open("/home/chris/tmp/mail.err", 'a') # # # Some constants (i.e. configuration) # home = "/home/chris" logfile = home + "/tmp/mail.log" filtfile = home + "/.mutt/filter" mldir = home + "/mail/" indir = mldir + "In/" judir = mldir + "Ju/" # # # Set to log to mail.log in ~/tmp with name 'filter' and the envelope/from # log = mailLib.initLog("filter") # # # Initialise destination mailbox name to empty # dest = "" # # # Read the message from standard input and make a message object from it # msg = mailbox.MaildirMessage(sys.stdin.buffer.read()) # # # Extract the To:, Cc: and Subject: headers and the envelope/from # msgcc = msg.get("Cc", "unknown").lower() msgto = msg.get("To", "unknown").lower() msgsb = msg.get("Subject", "unknown") msgfm = msg.get("From", "unknown").lower() # # # See if it's in our filter file # f = open(filtfile, 'r') for ln in f: # for each line in filter if ln[0] == '#': # ignore comments continue # # # split the line into fields, shlex.split() does quoted strings, add a field # to create a dummy fourth field if there isn't one in the filter file # fld = shlex.split(ln) fld.append("XXXXYYYYZZZZ") # # # copy the fields into better named variables # nm = fld[0] # name/alias dd = fld[1] + "/" # destination directory tocc = fld[2].lower() # list address sbstrip = '[' + fld[3] + ']' # string to match in and/or strip out of subject # # # see if the filter To/CC column matches the message To: or Cc: or if sbstrip is in Subject: # if (tocc in msgcc or tocc in msgto or sbstrip in msgsb): # # # set the destination directory # dest = mldir + dd + nm # # # Strip out list name (4th field) from subject if it's there # if sbstrip in msgsb: msg.replace_header("Subject", msgsb.replace(sbstrip, '')) # # # we've found a match so assume we won't get another # break # # # if destination mb name hasn't been set yet then set to In/default # (mail with 'chris' in destination will get to 'inbox') # if dest == "": dest = indir + "default" mailLib.deliverMdMsg(dest, msg, log)
#!/usr/bin/python import sys # # # # home = "/home/chris" filtfile = home + "/.mutt/filter" # # # Get mailing lists from filter file # f = open(filtfile, 'r') for ln in f: if ln[0] == '#': # ignore comments continue # # # split the line into fields # fld = ln.split() tocc = fld[2] if (":x" in fld[1]): continue sys.stdout.write("alias ") sys.stdout.write(fld[0] + " ") sys.stdout.write(tocc + "\n")
#!/usr/bin/python import sys # # # # home = "/home/chris" filtfile = home + "/.mutt/filter" # # # Get mailing lists from filter file # f = open(filtfile, 'r') for ln in f: if ln[0] == '#': # ignore comments continue # # # split the line into fields # fld = ln.split() if (fld[1][0:4] == "Li:x"): continue # don't output if there's an x flag if (fld[1][0:2] == "Li"): sys.stdout.write(fld[2] + " ") # output the list address
import mailbox import logging import logging.handlers import os import time # # # log a message # def initLog(name): log = logging.getLogger(name) log.setLevel(logging.DEBUG) f = logging.handlers.RotatingFileHandler("/home/chris/tmp/mail.log", 'a', 1000000, 4) f.setLevel(logging.DEBUG) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') f.setFormatter(formatter) log.addHandler(f) return log # # # Deliver a message to a local maildir # def deliverMdMsg(dest, msg, log): # # # Create the destination maildir instance # md = mailbox.Maildir(dest, factory=None) log.info("From: " + msg.get("From", "unknown")) log.info("Destination is: " + dest) # # # Put the incoming message in the appropriate maildir # No need to lock, it's a maildir # try: md.add(msg) except exception as e: log.info("Failed to store message:" + e) return