#!/usr/bin/env python

#
# Grab email addresses from an email message, and append it into a
# Mutt aliases file.  Very badly written, but it works good enough.
# Peter Wang (tjaden@users.sourceforge.net)
#
# Put something like this into your .muttrc
#
#   macro pager T "|takeaddress.py ~/.mutt/aliases\n" "take addresses"
#

#
# Original: sometime in 1999/2000
# Updated:  28/03/2000 -- more hacks
#

import sys, string, re


aliasfile = sys.argv[1]
if not aliasfile:
    print "Missing argument (path to Mutt aliases file)."
    sys.exit(1)



# find addresses in the message

def get_addresses(file):
    addr = {}
    headers = 1

    addrpat = "(?P<address>[-.\w\d]+@[-.\w\d]+)"

    while 1:
        line = file.readline()
        if not line: break
        line = line[:-1]

        if headers:
            if len(line) == 0:
                headers = 0
            else:
                if string.find(line, "<") == -1:
                    m = re.search(r"^From:\s*" + addrpat, line, re.I)
                    if m: addr[m.group('address')] = 1
                else:
                    m = re.search(r"^From:(?P<name>[^<]*)?<" + addrpat, line, re.I)
                    if m: addr[m.group('address')] = string.strip(m.group('name'))

        else:              

            # attribution text
            m = re.search("^(?P<name>[-.'\w\s\d]+)\s+<?" + addrpat + ">?", line)
            if m:
                if not addr.has_key(m.group('address')):
                    addr[m.group('address')] = string.strip(m.group('name'))

            # general text (may have more than one on a line!)
	    while 1:
		m = re.search(addrpat, line)
		if not m:
		    break
		else:
		    if not addr.has_key(m.group('address')):
			addr[m.group('address')] = 1
		    line = line[m.end():]
                        
    return addr

addrlist = get_addresses(sys.stdin)
if not addrlist:
    print "No addresses found."
    sys.exit(0)

sys.stdin.close()



def input_str(prompt):
    return raw_input(prompt + " ")


def input_int(prompt):
    try:
        return string.atoi(input_str(prompt))
    except:
        return -1


def input_yn(prompt):
    while 1:
        str = string.lower(input_str(prompt))
        if str in ("yes", "y"):
            return 1
        elif str in ("no", "n"):
            return 0


# reopen stdin for interactive use
sys.stdin = open("/dev/tty", "r")

keys = addrlist.keys()
keys.sort()
max = len(keys)

if max == 1:
    num = 0
    print keys[num] + ((addrlist[keys[num]] != 1) and (", " + addrlist[keys[num]]) or "")
else:
    # more than one address, present user with menu of addresses

    def fullname(key):
            return (addrlist[k] != 1) and "(" + addrlist[k] + ")" or ""
    
    print "0: Cancel"
    i = 1
    for k in keys:
        print "%s: %s %s" % (i, k, fullname(addrlist[k]))
        i = i + 1
            
    num = input_int("Choice:")
    if num == 0:
        print "Cancelled."
        sys.exit(0)
    elif num < 1 or num > max:
        print "Out of range."
        sys.exit(1)
    else:
        num = num - 1


# Get user details
address = keys[num]

fullname = addrlist[address]
if fullname == 1:
    fullname = input_str("Full name:")

nickname = input_str("Nickname:")

# Write it out
if input_yn("Add to list?"):
    try:
        
        f = open(aliasfile, "a")
        if fullname:
            f.write("alias %s\t%s <%s>\n"
                    % (nickname, fullname, address))
        else:
            f.write("alias %s\t%s\n"
                    % (nickname, address))
            
        f.close()
    except:
        print "Error appending to", aliasfile
        sys.exit(1)

