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