I use Mailman with Postfix, and every so often, I would like to examine the outgoing mail queue and kill some messages. Postfix supplies "postsuper" to do this given that you know the queue ID, but won't, say, take an address and find all mail to that address and dequeue it. Also, I sorta hate the output format of mailq.
So I hacked together a Python program that: 1) formats the mailq output more nicely, in two different ways: a verbose format: id: E78C251BDD* size: 4317 datetime: Tue Jan 29 15:25:50 sender: <listname>[EMAIL PROTECTED] recipients: ['[EMAIL PROTECTED]', '[EMAIL PROTECTED]'] and a one-per-line greppable format: id=E78C251BDD* size=4317 datetime=Tue Jan 29 15:25:50 sender=<listname>[EMAIL PROTECTED] recipients=['[EMAIL PROTECTED]','[EMAIL PROTECTED]'] Both formats can optionally include the 'remote SMTP error message'. 2) filter by looking for any one-recipient queued messages that match a regular expression: mailq -v [EMAIL PROTECTED] might show id: E78C251BDD size: 4317 datetime: Tue Jan 29 15:25:50 sender: <listname>[EMAIL PROTECTED] recipients: ['[EMAIL PROTECTED]'] 3) output just the queue ID, useful in combination with 2) above, so that one can do postsuper -d `mq -i [EMAIL PROTECTED]` and delete all the queued messages going just to [EMAIL PROTECTED] Here's a usage message: mailq [-vie] [--verbose] [--id-only] [--show-errors] [recip RE] show the queued mail (using mailq) -v/--verbose: show a multiline view of each queued mail (default is one line per queue item) -i/--id-only: show only the queue IDs -e/--show-errors: show SMTP errors for each recipient recip RE: a regular expression to filter by recipient if that recipient is the only one for a queue item Example: mailq -i [EMAIL PROTECTED] shows queue IDs for any mails queued for [EMAIL PROTECTED] only Example: mailq -v shows all queue items in verbose format and here's the code. Use as you wish; any comments on Python style are especially welcome. I'd be happy to adapt this to other mailq output formats if I find out about them; obviously it's pretty fragile wrt the Postfix output format. It's either that or get my fingers into the queue directories, which is a less-stable interface, IMO. But if someone can document the sendmail format I'll see if I can't adapt to it as well. #!/usr/bin/env python import os import sys import re import getopt class MyRec: def __init__(self, id): self.id = id self.size = 0 self.sender = self.datetime = '' self.recipients = [] def __str__(self): return self.makestr(1) def makestr(self, errors): if errors: reciplist = self.recipients else: reciplist = map(lambda x: x[0], self.recipients) return '\n'.join(( "id: %s" % self.id, "size: %d" % self.size, "datetime: %s" % self.datetime, "sender: %s" % self.sender, "recipients: %s" % repr(reciplist))) def __repr__(self): return self.__str__() def oneline(self, errors): if errors: reciplist = self.recipients else: reciplist = map(lambda x: x[0], self.recipients) return ' '.join(( "id=%s" % self.id, "size=%d" % self.size, "datetime=%s" % self.datetime, "sender=%s" % self.sender, "recipients=%s" % repr(reciplist))) def multiline(self, errors): return self.makestr(errors) + '\n' def parsemailq(): hre = re.compile('.*Queue ID.*') idre = re.compile(r""" ^(?P<id>[0-9A-Z\*]+) \s+(?P<size>[0-9]+) \s+(?P<dow>\S+) \s+(?P<mon>\S+) \s+(?P<day>[0-9]+) \s+(?P<time>\S+) \s+(?P<sender>\S+) """, re.VERBOSE) reasonre = re.compile('^\s*\(') recre = re.compile('^\s+(?P<recip>[^@]+@[^@]+)') sepre = re.compile('^$') recs = [] mq = os.popen("mailq", "r") for line in mq.readlines(): line = line.rstrip() if hre.search(line): continue mo = idre.match(line) if mo: r = MyRec(mo.group('id')) reason = '' r.size = int(mo.group('size')) r.datetime = ' '.join((mo.group('dow'), mo.group('mon'), mo.group('day'), mo.group('time'))) r.sender = mo.group('sender') continue mo = reasonre.match(line) if mo: reason = line.strip() continue mo = recre.match(line) if mo: r.recipients.append([mo.group('recip'), reason]); reason = '' continue mo = sepre.match(line) if mo: recs.append(r) mq.close() return recs def usage(): print >> sys.stderr, """ mailq [-vie] [--verbose] [--id-only] [--show-errors] [recip RE] show the queued mail (using mailq) -v/--verbose: show a multiline view of each queued mail (default is one line per queue item) -i/--id-only: show only the queue IDs -e/--show-errors: show SMTP errors for each recipient recip RE: a regular expression to filter by recipient if that recipient is the only one for a queue item Example: mailq -i [EMAIL PROTECTED] shows queue IDs for any mails queued for [EMAIL PROTECTED] only Example: mailq -v shows all queue items in verbose format""" def main(): lookfor = None try: (optlist, trail) = getopt.getopt(sys.argv[1:], 'vieh', ['verbose', 'id-only', 'show-errors', 'help']) except getopt.GetoptError, v: print v usage() sys.exit(1) verbose = idonly = errors = 0 for (o, a) in optlist: if o in ("-v", "--verbose"): verbose = 1 if o in ("-i", "--id-only"): idonly = 1 if o in ("-e", "--show-errors"): errors = 1 if o in ("-h", "--help"): usage() sys.exit(0) if trail: lookfor = re.compile(trail[0]) recs = parsemailq() for r in recs: if lookfor: if len(r.recipients) == 1 and \ lookfor.search(r.recipients[0][0]): dump(r, idonly, verbose, errors) else: dump(r, idonly, verbose, errors) def dump(r, idonly, verbose, errors): if idonly: print r.id elif verbose: print r.multiline(errors) else: print r.oneline(errors) main() _______________________________________________ Mailman-Developers mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/mailman-developers