#!/usr/bin/python

"""Update mail alias entries in LDAP DIT for Mailman lists

Usage: %(program)s [options]

Where:

    --domain=DOMAIN

    -h / --help
        Print this text and exit.

"""

from __future__ import print_function;

import sys
import getopt
import paths
import re
import imp
import ldap

from Mailman import mm_cfg
from Mailman import MailList
from Mailman import Utils

program = sys.argv[0]

def usage(code, msg=''):
    if code:
        fd = sys.stderr
    else:
        fd = sys.stdout
    print(_(__doc__), file=fd)
    if msg:
        print(msg, file=fd)
    sys.exit(code)



def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'h',
                                   ['domain=',
                                    'members',
                                    'help'])
    except getopt.error, msg:
        usage(1, msg)

    domain = None
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(0)
        elif opt in ('--domain'):
            domain = arg.lower()

    names = [i.lower() for i in args] if args else Utils.list_names()
    names.sort()

    config = imp.load_source("config", "/var/www/tufs-mail/etc/config.py")

    ldap_c = ldap.initialize(config.ldap_uri_read)
    ldap_c.set_option(ldap.OPT_REFERRALS, 1)

    uid_by_email = {}
    ## FIXME: e-mail address in LDAP filter must be escape
    ldap_r = ldap_c.search_s(config.ldap_search_base, ldap.SCOPE_SUBTREE,
            '(objectClass=posixAccount)', ['uid', 'mail', 'mailAlternateAddress'])
    for dn, entry in ldap_r:
        uid = entry['uid'][0]
        if 'mail' in entry:
            for email in entry['mail']:
                uid_by_email[email.lower()] = uid
        if 'mailAlternateAddress' in entry:
            for email in entry['mailAlternateAddress']:
                uid_by_email[email.lower()] = uid

    mlists_by_addr = {}
    for n in names:
        mlist = MailList.MailList(n, lock=0)
        if domain and mlist.host_name.lower() != domain:
            continue

        mlists_by_addr[('%s@%s' % (n, mlist.host_name)).lower()] = mlist

    ldap_r = ldap_c.search_s(config.ldap_ml_base, ldap.SCOPE_SUBTREE,
            '(mail=*)', ['mail'])
    ldap_c = ldap.initialize(config.ldap_uri_write)
    ldap_c.set_option(ldap.OPT_REFERRALS, 0)
    ldap_c.simple_bind_s(config.ldap_bind_dn, config.ldap_bind_pass)
    for dn, entry in ldap_r:
        mail = entry['mail'][0]
        if not mail in mlists_by_addr:
            ldap_c.delete_s(dn)
        else:
            del mlists_by_addr[mail]
    for mail, mlist in mlists_by_addr.items():
        name = mlist.internal_name()
        domain = mlist.host_name
        dn = 'cn=' + name + ',' + config.ldap_ml_base
        entry = [
            ('objectClass', ['inetOrgPerson', 'mailRecipient']),
            ('cn', [name]),
            ('sn', [name]),
            ('mail', [mail]),
            ('mailAlternateAddress', [
                name + '-bounces@' + domain,
                name + '-confirm@' + domain,
                name + '-join@' + domain,
                name + '-leave@' + domain,
                name + '-owner@' + domain,
                name + '-request@' + domain,
                name + '-subscribe@' + domain,
                name + '-unsubscribe@' + domain,
            ]),
        ]
        ldap_c.add_s(dn, entry)

    ldap_c.unbind_s


if __name__ == '__main__':
    main()
