#!/usr/bin/python

"""Generate mailing list CSV data file for ml_db.pl

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

        ## Non-standard attribute
        try:
            created_by = mlist.created_by
        except AttributeError:
            created_by = "root"

        ## Non-standard attribute
        try:
            created_date = mlist.created_date
        except AttributeError:
            created_date = "2014/01/01 00:00:00"

        if mlist.generic_nonmember_action:
            post_policy = "personal"
        else:
            post_policy = "public"

        owner_uid = 'UNKNOWN'
        for owner in mlist.owner:
            owner = owner.lower()
            try:
                owner_uid = uid_by_email[owner]
                break
            except KeyError:
                pass

        print(
            mlist.real_name,
            owner_uid,
            created_by,
            ## Filter tab, CR, LF, comma
            re.sub(r'\s+', ' ', re.sub(r',', ' ', mlist.description)),
            re.sub(r'\s+', ' ', re.sub(r',', ' ', mlist.info)),
            post_policy,
            created_date,
            sep=","
        )

    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()
