#!/usr/bin/python2
from __future__ import print_function
import contextlib
import glob
import ldap
import ldap.filter
import mmap
import re

def get_username(uid, cache={}):
    if uid in cache:
        return cache[uid]
    res = ll.search_s(
        'ou=People,dc=scripts,dc=mit,dc=edu',
        ldap.SCOPE_SUBTREE,
        ldap.filter.filter_format('(&(objectClass=scriptsAccount)(uidNumber=%s))', [uid]),
        ['uid'])
    if res:
        [(dn, attrs)] = res
        [cache[uid]] = attrs['uid']
    else:
        cache[uid] = None
    return cache[uid]

def get_vhosts(username, cache={}):
    if username in cache:
        return cache[username]
    res = ll.search_s(
        'ou=VirtualHosts,dc=scripts,dc=mit,dc=edu',
        ldap.SCOPE_SUBTREE,
        ldap.filter.filter_format('(&(objectClass=scriptsVhost)(scriptsVhostAccount=uid=%s,ou=People,dc=scripts,dc=mit,dc=edu))', [username]),
        ['scriptsVhostName', 'scriptsVhostAlias'])
    cache[username] = [vhost for (dn, attrs) in res for attr in ['scriptsVhostName', 'scriptsVhostAlias'] for vhost in attrs.get(attr, [])]
    return cache[username]

ll = ldap.initialize('ldapi://%2fvar%2frun%2fslapd-scripts.socket/')

for log_name in glob.glob('/var/log/maillog*'):
    with open(log_name) as log_file, \
         contextlib.closing(mmap.mmap(log_file.fileno(), 0, access=mmap.ACCESS_READ)) as mm:
        for m in re.finditer('^\S+ \d+ \S+ \S+ postfix/pickup\[\d+\]: \S+: uid=(\d+) from=<(\S+)>$', mm, flags=re.MULTILINE):
            uid, addr = m.groups()
            if uid == '0':
                continue
            username = get_username(uid)
            if username is None:
                print('no username: from=<{}> uid={}'.format(addr, uid))
            elif addr == username or addr == username + '@scripts.mit.edu' or (addr.startswith(username + '+') and addr.lower().endswith('@scripts.mit.edu')):
                pass
            elif '@' not in addr:
                print('wrong username: from=<{}> uid={} username={}'.format(addr, uid, username))
            elif any(addr.lower().endswith('@' + vhost.lower()) for vhost in get_vhosts(username)):
                pass
            else:
                print('bad address: from=<{}> uid={} username={} vhosts={}'.format(addr, uid, username, '|'.join(get_vhosts(username))))
