#!/usr/bin/python

# mailheader_bogus_to.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       May 28, 2007
#       May 28, 2007            bar     sort the names
#       May 29, 2007            bar     only_allow_hosts
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 17, 2008            bar     email adr
#       November 15, 2008       bar     egad! I've been making default params as [] and {}
#       August 28, 2010         bar     show_info
#       May 27, 2012            bar     doxygen namespace
#       --eodstamps--
##      \file
#       \namespace              tzpython.mailheader_bogus_to
#
#
#       Put a X-bogus-to: header on email that has a "To:" address
#       with a name known to the given IIstore as bogus.
#
#       This script is run for emails by procmail.
#
#       This script can read the input email from stdin or from a file, if given,
#       and can write output to stdout or to a file if given.
#
#


import  email.Utils

import  tzemail
import  IIstoreClient


TO_HEADER           =   "To: "
CC_HEADER           =   "CC: "
RESENT_TO_HEADER    =   "Resent-To: "
RESENT_CC_HEADER    =   "Resent-CC: "

OUR_HEADER          =   "X-bogus-to: "


FRIENDLY_CHAR       =   "'"
EMAIL_ADR_CHAR      =   "."



def make_names_from_hdrs(eml, only_allow_hosts = None) :
    """
        Given an email in array form with lines without EOLs,
        return a list of both friendly and email names suitable for IIstore queries.

        If there are any (lower case) only_allow_hosts, then name
        pairs that don't have an email address ending in a host
        listed in 'only_allow_hosts' will be ignored.
    """

    only_allow_hosts    = only_allow_hosts or []

    names   = []

    hdrs    = tzemail.find_email_headers(eml, TO_HEADER)
    hdrs   += tzemail.find_email_headers(eml, CC_HEADER)
    hdrs   += tzemail.find_email_headers(eml, RESENT_TO_HEADER)
    hdrs   += tzemail.find_email_headers(eml, RESENT_CC_HEADER)
    nms   = email.Utils.getaddresses(hdrs)
    for n in nms :

        ok  = True
        if  len(only_allow_hosts) :
            ok  = False
            hn  = n[1].lower()
            for h in only_allow_hosts :
                if  hn.endswith(h) :
                    ok  = True
                    break
                pass
            pass

        if  ok :
            if  n[0] :
                names.append(FRIENDLY_CHAR  + n[0] + FRIENDLY_CHAR )
            if  n[1] :
                names.append(EMAIL_ADR_CHAR + n[1] + EMAIL_ADR_CHAR)
            pass
        pass

    names.sort()

    return(names)



def apply_header(eml, unknown_replies = None, only_allow_hosts = None, host = None, port = None, user_name = None, password = None, iiname = None, precedent_str = "", timeout = None, show_info = 0) :
    """
        Given an email in array form with lines without EOLs,
        apply the OUR_HEADER to the email if it can be.
    """

    clt     = None


    unknown_replies     = unknown_replies or [ 'bogus_to' ]
    unknown_replies     = tzlib.make_dictionary(map(lambda r : r.lower(), unknown_replies))

    only_allow_hosts    = only_allow_hosts or []
    only_allow_hosts    = [ h.lower() for h in only_allow_hosts ]

    tzemail.eliminate_email_header(eml, OUR_HEADER)

    nms     = make_names_from_hdrs(eml)
    if  show_info :
        print "nms", nms

    bads    = []

    for n in nms :

        if  not clt :
            clt     = IIstoreClient.an_iistore_client(host, port, user_name, password, iiname, precedent_str, timeout)
            if  not clt :
                if  show_info :
                    print "II server off line"
                break               # ignore an off line iistore
            pass

        # clt.screen_info = True

        r   = clt.make_query(n)
        if  show_info > 1 :
            print "query:", n, r
        if  r and unknown_replies.has_key(r.lower()) :
            bads.append( [ n, r ] )
        pass

    if  show_info   :
        print "bads", bads

    for nr in bads  :
        tzemail.add_email_header(eml, OUR_HEADER + nr[0] + " " + nr[1])

    return(eml)


#
#
#
if __name__ == '__main__' :

    import  sys

    import  tzlib
    import  TZCommandLineAtFile


    del sys.argv[0]

    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)

    unknown_replies     = []
    only_allow_hosts    = []
    host                = None
    port                = None
    user_name           = None
    password            = None
    iiname              = None
    precedent_str       = None
    timeout             = 5.0
    show_info           = 0


    while True :
        oi  = tzlib.array_find(sys.argv, [ "--host", "-h" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        host        = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--port", "-p" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        port        = int(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--user", "-u" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        user_name   = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--password", "-a" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        password    = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--iiname", "-i" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        iiname      = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--prec_str", "-s" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        precedent_str   = sys.argv.pop(oi)

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--timeout", "-t" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        timeout         = float(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--unknown", "-u" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        unknown_replies.append(sys.argv.pop(oi))

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--only", "-o" ])
        if  oi < 0 :    break
        del sys.argv[oi]
        only_allow_hosts.append(sys.argv.pop(oi).lower())

    while True :
        oi  = tzlib.array_find(sys.argv, [ "--show_info", ])
        if  oi < 0 :    break
        del sys.argv[oi]
        show_info  += 1



    if  len(sys.argv) > 2 :
        print sys.argv
        raise("Just tell me an input and output file. Nothing more.")


    if  len(sys.argv) > 0 :
        fi  = open(sys.argv.pop(0), "r")
    else :
        fi  = sys.stdin

    eml     = tzemail.read_email_from_file(fi)

    if  fi != sys.stdin :
        fi.close()

    eml     = apply_header(eml, unknown_replies, only_allow_hosts, host, port, user_name, password, iiname, precedent_str, timeout, show_info = show_info)

    if  len(sys.argv) > 0 :
        fo  = open(sys.argv.pop(0), "w")
    else :
        fo  = sys.stdout

    #
    #   Write the email out to stdout
    #
    for li in eml :
        print >> fo, li

    if  fo != sys.stdout :
        fo.close()

    pass

#
#
#
# eof
