#!/usr/bin/python3

'''
salpack-maillog

Usage: salpack-maillog [-h|-a|-v] [maillog_filename|-j|-j=since]
'''

import re, sys, os

emails = {}
qids = []
verbose = False

def getemail(s):
    try:
      return re.compile("[<>]").split(s)[1]
    except IndexError:
      print(s)
      raise

ignore1 = [
  "connect", "disconnect",
  "certificate verification failed",
  "SSL_accept error",
  "SSL_connect error",
  "connect from",
  "disconnect from",
  "lost connection after AUTH from",
  "improper command pipelining",
]
ignore2 = [
  "message-id=", "client=",
  "host ",
  "resent-message-id=",
  "enabling PIX workarounds",
  "skipped",
  "lost connection with",
  "sender delay notification",
]

def check_ignore(column, texts):
    for t in texts:
      if column.startswith(t):
        return True
    return False

def processlog(logfile):
    if logfile.startswith("-j"):
      # use journal
      args = logfile.split("=", 1)
      if len(args)==1:
        since = "-1 day"
      else:
        since = args[1]
      f = os.popen("journalctl -u postfix --since='%s'" % since, "r")
    else:
      if os.path.getsize(logfile)==0:
        print("WARNING: Empty file: %s" % logfile)
      if sys.version_info[0]>2:
        f = open(logfile, "r", encoding="utf-8", errors="ignore")
      else:
        f = open(logfile)
    for line in f.readlines():
      cols = line.strip().split(": ")
      if "postfix/" in cols[0]:
        if cols[1] in ["warning", "statistics", "fatal"]:
          continue
        elif len(cols)<3:
          continue
        elif cols[2] in ["removed", "reject", "sender non-delivery notification"]:
          continue
        elif check_ignore(cols[1], ignore1):
          continue
        elif check_ignore(cols[2], ignore2):
          continue
        qid = cols[1]
        if qid not in emails:
          emails[qid] = {"dt": cols[0][:15]}
          qids.append(qid)
        if cols[2].startswith("uid="):
          emails[qid]["from"] = getemail(cols[2].split(" ", 1)[-1])
        elif cols[2].startswith("from="):
          emails[qid]["from"] = getemail(cols[2])
        elif cols[2].startswith("to="):
          emails[qid]["to"] = getemail(cols[2])
          if len(cols)>3 and cols[3].startswith("orig_to="):
            emails[qid]["orig_to"] = getemail(cols[3])
        elif verbose:
          print(cols)

if "-h" in sys.argv or "--help" in sys.argv:
  print(__doc__)
  sys.exit()
if "-v" in sys.argv:
  verbose = True
  sys.argv.remove("-v")
if "-a" in sys.argv:
  sys.argv.remove("-a")
  logs = [
    os.path.join("/var/log", x)
    for x in os.listdir("/var/log")
    if x.startswith("maillog-")
  ]
  for log in logs:
    processlog(log)
if sys.argv[1:]:
  for log in sys.argv[1:]:
    processlog(log)
else:
  processlog("/var/log/maillog")

for queue_id in qids:
  email = emails[queue_id]
  orig = email.get("orig_to")
  if orig:
    orig = "(" + orig + ")"
  else:
    orig = ""
  print(
    "%s: %s -> %s%s [%s]"
    % (email.get("dt"), email.get("from"), email.get("to"), orig, queue_id)
  )
