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

Reply via email to