#!/usr/bin/env python3 """ mq: formats the output of Postfix' mailq command url: http://www.postconf.com/docs/mq license: http://www.roble.com/docs/RobleBSDlicense.html TODO: fix sort by arrival time """ #### defaults #### termwidth = 80 # linelength w/o terminfo longlines = False # linewrapping html = False # plaintext/html formatting rv = False # reverse video if html debug = False ############### import subprocess, string, sys, os, re os.environ.clear() os.environ['PATH'] = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin' def printusage(): print(" USAGE: " + sys.argv[0] + " [ -h | -html | -rhtml | -txt | -l= | -l ]") sys.exit() def getoutput(cmd): """ take a command, return command's output (stdout) """ # when will python have a clean syntax for this ? if not type(cmd) == str: return '' return subprocess.Popen(cmd,shell=True,cwd='/tmp',text=True, stderr=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0] #### parse command line #### for arg in sys.argv[1:]: if debug: print(' DEBUG: arg: ' + arg) if arg == "-html": html = True rv = False elif arg == "-rhtml": html = True rv = True else: if arg == "-txt": html = False elif arg.startswith('-l='): try: termwidth = int(arg[3:]) longlines = True except ValueError: print(" ERROR: \"" + arg[3:] + "\" is not an integer") printusage() elif arg == "-l": longlines = True termwidth = 0 elif arg == "-r": rv = True else: printusage() #### determine terminal width to avoid linewrap #### if not html and not longlines: try: termwidth = int(getoutput('stty size').split()[1]) -1 except: termwidth = 143 if debug: print(' DEBUG: html = ' + str(html) + ', longlines = ' + str(longlines) + ', termwidth = ' + str(termwidth)) #### check for multiple postfix instances #### mailconfigs = [] try: mailconfigs.append( getoutput('postconf -h config_directory').strip() ) if debug: print(' DEBUG: config_directory = ' + str(mailconfigs)) except: if os.path.exists('/usr/local/etc/postfix/main.cf'): mailconfigs.append('/usr/local/etc/postfix') else: mailconfigs.append('/etc/postfix') try: for config in getoutput('postconf -h alternate_config_directories').split(","): config = str( config.strip() ) if os.path.exists(config + '/main.cf'): mailconfigs.append( config.strip() ) if debug: print(' DEBUG: mailconfigs += ' + str(config).strip()) except: pass if len(mailconfigs) == 0: print(" ERROR: postfix not found") sys.exit() if debug: print(' DEBUG: mailconfigs = ' + str(mailconfigs)) #### parse mailq output to array with one row per message #### queue = [] for config in mailconfigs: os.environ["MAIL_CONFIG"] = str(config) qline = ["", "", "", ""] for line in getoutput('mailq').splitlines(): if re.match( '^[-|postqueue:|Mail]', line ): # discard in-queue wrapper continue elif re.match( '^[A-Z0-9]', line ): #### queueid/.../sender qline[0] = line[:line.rindex( " " )].strip() qline[1] = line[line.rindex( " " ):].strip() elif line.count( ')' ) > 0: #### status qline[2] = line.strip() elif re.match( '^\s', line ): #### recipient/s qline[3] = ( qline[3] + " " + line.lstrip() ).strip() elif not line: #### end of record if html: if '!' in qline[0]: # held openTag = '' elif '*' in qline[0]: # in delivery openTag = '' else: openTag = '' closeTag = '' queue.append( openTag + qline[0] + closeTag + openTag + qline[1] + closeTag + openTag + qline[3] + closeTag + openTag + qline[2] + closeTag + "\n" ) else: queue.append( qline[0] + " " + qline[1] + " " + qline[3] + " " + qline[2] + "\n" ) qline = ["", "", "", ""] else: #### should never get here print( " ERROR: unknown input: \"" + line + "\"") #### attempt to sort by arrival time #### queue.sort(key = lambda line: line.split(" ")[5]) queue.sort(key = lambda line: line.split(" ")[4]) #### output already #### lineNum = 0 if not html: if ( queue ): header='# --Queue ID-- -Size- ---Arrival Time---- ---Sender/Recipient(s)/(Status)---' if longlines and termwidth == 0: print( header ) else: print( header[:termwidth] ) for line in ' '.join( queue ).splitlines(): lineNum += 1 if longlines or termwidth == 0: print( str( lineNum ) + " " + line.strip() ) else: try: print( (str( lineNum ) + " " + line.strip())[:termwidth] ) except: if debug: print(' DEBUG: unknown termwidth error') pass else: if (rv): htmlopts='bgcolor="#000000" text="#FFFFFF"' else: htmlopts='bgcolor="#FFFFFF"' header=('Postfix mailq
\n' +
      '' +
      '' +
      '' +
      '' +
      '')
  print('Content-type: text/html\n\n' + header)
  if ( queue ):
    for line in ''.join( queue ).splitlines():
      lineNum += 1
      print( '' + line.strip() + "" )
  print( '
#  --Queue ID-- -Size- ---Arrival Time----  ---Sender---  ---Recipient(s)---  --(Status)--
' + str(lineNum) + ' 
' )