mail-merge: import rtkit from ~adehnert if needed
[user/alex/software/my-snippets.git] / mail-merge
1 #!/usr/bin/python
2
3 import csv
4 import email.parser
5 from optparse import OptionParser
6 import os
7 import smtplib
8 import subprocess
9 import sys
10
11
12 sender_header = 'mail-merge-sender@mit.edu'
13 rtkit_path = '/afs/athena.mit.edu/user/a/d/adehnert/arch/common/lib/python/'
14 smtp = None
15
16 def dictize_line(header, line,):
17     line_dict = {}
18     for key, elem in zip(header, line, ):
19         line_dict[key]=elem
20     return line_dict
21
22 def setup_sendmail_smtp():
23     global smtp
24     smtp = smtplib.SMTP()
25     smtp.connect()
26 def sendmail_smtp(addrs, text):
27     global smtp
28     smtp.sendmail(sender_header, addrs, text, )
29 smtp_funcs = (setup_sendmail_smtp, sendmail_smtp, )
30
31 def sendmail_cmd(addrs, text):
32     args = ["/usr/lib/sendmail", "--", ]
33     args.extend(addrs)
34     proc = subprocess.Popen(args, stdin=subprocess.PIPE)
35     proc.communicate(text)
36 cmd_funcs = (lambda: True, sendmail_cmd)
37
38 setup_sendmail, sendmail = smtp_funcs
39 setup_sendmail, sendmail = cmd_funcs
40
41 def parse_arguments():
42     parser = OptionParser(usage='usage: %prog [options] cc_addr template recipients')
43     parser.add_option('-q', '--rt-queue', dest='rt_queue',
44             help='Automatically create a ticket in queue QUEUE',
45             metavar='QUEUE',
46     )
47     parser.add_option('-o', '--rt-owner', dest='rt_owner',
48             help='Set RT owner and AdminCC to USER',
49             metavar='USER',
50     )
51     (options, args) = parser.parse_args()
52     if len(args) != 3:
53         parser.error("incorrect number of arguments")
54     if options.rt_owner and not options.rt_queue:
55         parser.error("--rt-owner requires specifying a queue")
56     return options, args
57
58 def nop_msg_filter(rcpt, body):
59     return rcpt, body
60
61 def msg_filter_factory(opts):
62     if not opts.rt_queue:
63         return nop_msg_filter
64
65     try:
66         import rtkit.tracker, rtkit.authenticators, rtkit.errors
67     except ImportError:
68         print "Note: using rtkit from %s" % (rtkit_path, )
69         sys.path.append(rtkit_path)
70         import rtkit.tracker, rtkit.authenticators, rtkit.errors
71
72     cookie = rtkit.authenticators.CookieAuthenticator
73     resource = rtkit.resource.RTResource.from_rtrc(cookie)
74     parser = email.parser.Parser()
75
76     def filter_rt(rcpt, body, ):
77         msg = parser.parsestr(body)
78         content = {
79             'content': {
80                 'Requestors': rcpt,
81                 'Queue': opts.rt_queue,
82                 'Subject' : msg['Subject'],
83                 'Text' : '',
84             }
85         }
86         if opts.rt_owner:
87             content['content']['AdminCC'] = opts.rt_owner
88             content['content']['Owner'] = opts.rt_owner
89
90         try:
91             response = resource.post(path='ticket/new', payload=content,)
92             results = dict(response.parsed[0])
93             ticket, ticket_number = results['id'].split('/')
94             assert ticket == 'ticket', 'unexpected value "%s" instead of ticket' % (ticket, )
95             subject = "%s [help.mit.edu #%s]" % (msg['Subject'], ticket_number)
96             del msg['Subject']
97             msg['Subject'] = subject
98         except rtkit.errors.RTResourceError as e:
99             logger.error(e.response.status_int)
100             logger.error(e.response.status)
101             logger.error(e.response.parsed)
102
103         # We don't want to send mail to the real recipient, because RT
104         # will send them a copy too.
105         return None, msg.as_string()
106
107     return filter_rt
108
109 def mail_merge(opts, cc_addr, email_file, recipients_file):
110     email_tmpl = open(email_file, 'r').read()
111     reader = csv.reader(open(recipients_file, 'r'))
112     header = reader.next()
113     msg_filter = msg_filter_factory(opts)
114     print header
115     for line in reader:
116         dct = dictize_line(header, line, )
117         print dct
118         text = email_tmpl % dct
119         rcpt, text = msg_filter(dct['email'], text, )
120         rcpts = [cc_addr]
121         if rcpt:
122             rcpts.append(rcpt)
123         sendmail(rcpts, text, )
124
125 if __name__=='__main__':
126     options, args = parse_arguments()
127     setup_sendmail()
128     mail_merge(options, *args)