#!/usr/bin/python
-import sys
-import os
import csv
+import email.parser
+from optparse import OptionParser
+import os
import smtplib
+import subprocess
+import sys
+
sender_header = 'mail-merge-sender@mit.edu'
+rtkit_path = '/afs/athena.mit.edu/user/a/d/adehnert/arch/common/lib/python/'
+smtp = None
def dictize_line(header, line,):
line_dict = {}
line_dict[key]=elem
return line_dict
-if __name__=='__main__':
- print "Syntax: $script $cc_addr $template $recipients"
+def setup_sendmail_smtp():
+ global smtp
smtp = smtplib.SMTP()
smtp.connect()
- cc_addr = sys.argv[1]
- email_file = sys.argv[2]
- email = open(email_file, 'r').read()
- reader = csv.reader(open(sys.argv[3]))
+def sendmail_smtp(addrs, text):
+ global smtp
+ smtp.sendmail(sender_header, addrs, text, )
+smtp_funcs = (setup_sendmail_smtp, sendmail_smtp, )
+
+def sendmail_cmd(addrs, text):
+ args = ["/usr/lib/sendmail", "--", ]
+ args.extend(addrs)
+ proc = subprocess.Popen(args, stdin=subprocess.PIPE)
+ proc.communicate(text)
+ if proc.returncode != 0:
+ raise RuntimeError, "sendmail returned %d" % (proc.returncode, )
+cmd_funcs = (lambda: True, sendmail_cmd)
+
+setup_sendmail, sendmail = smtp_funcs
+setup_sendmail, sendmail = cmd_funcs
+
+def parse_arguments():
+ parser = OptionParser(usage='usage: %prog [options] cc_addr template recipients')
+ parser.add_option('-q', '--rt-queue', dest='rt_queue',
+ help='Automatically create a ticket in queue QUEUE',
+ metavar='QUEUE',
+ )
+ parser.add_option('-o', '--rt-owner', dest='rt_owner',
+ help='Set RT owner and AdminCC to USER',
+ metavar='USER',
+ )
+ parser.add_option('--split', dest='split',
+ help='Split "email" field on SPLIT and send to each recipient',
+ metavar='SPLIT',
+ )
+ (options, args) = parser.parse_args()
+ if len(args) != 3:
+ parser.error("incorrect number of arguments")
+ if options.rt_owner and not options.rt_queue:
+ parser.error("--rt-owner requires specifying a queue")
+ return options, args
+
+def nop_msg_filter(rcpts, body):
+ return rcpts, body
+
+def msg_filter_factory(opts):
+ if not opts.rt_queue:
+ return nop_msg_filter
+
+ try:
+ import rtkit.tracker, rtkit.authenticators, rtkit.errors
+ except ImportError:
+ print "Note: using rtkit from %s" % (rtkit_path, )
+ sys.path.append(rtkit_path)
+ import rtkit.tracker, rtkit.authenticators, rtkit.errors
+
+ cookie = rtkit.authenticators.CookieAuthenticator
+ resource = rtkit.resource.RTResource.from_rtrc(cookie)
+ parser = email.parser.Parser()
+
+ def filter_rt(rcpts, body, ):
+ msg = parser.parsestr(body)
+ content = {
+ 'content': {
+ 'Requestors': ", ".join(rcpts),
+ 'Queue': opts.rt_queue,
+ 'Subject' : msg['Subject'],
+ 'Text' : '',
+ }
+ }
+ if opts.rt_owner:
+ content['content']['AdminCC'] = opts.rt_owner
+ content['content']['Owner'] = opts.rt_owner
+
+ try:
+ response = resource.post(path='ticket/new', payload=content,)
+ results = dict(response.parsed[0])
+ ticket, ticket_number = results['id'].split('/')
+ assert ticket == 'ticket', 'unexpected value "%s" instead of ticket' % (ticket, )
+ subject = "%s [help.mit.edu #%s]" % (msg['Subject'], ticket_number)
+ del msg['Subject']
+ msg['Subject'] = subject
+ except rtkit.errors.RTResourceError as e:
+ logger.error(e.response.status_int)
+ logger.error(e.response.status)
+ logger.error(e.response.parsed)
+
+ # We don't want to send mail to the real recipient, because RT
+ # will send them a copy too.
+ return [], msg.as_string()
+
+ return filter_rt
+
+def mail_merge(opts, cc_addr, email_file, recipients_file):
+ email_tmpl = open(email_file, 'rU').read()
+ reader = csv.reader(open(recipients_file, 'rU'))
header = reader.next()
+ msg_filter = msg_filter_factory(opts)
print header
+ if not 'email' in header:
+ print >>sys.stderr, "Your CSV file doesn't have an email field. You should fix that.\n(Note that this script is case-sensitive.)"
+ return False
for line in reader:
dct = dictize_line(header, line, )
print dct
- text = email % dct
- smtp.sendmail(sender_header, [dct['email'], cc_addr, ], text, )
+ text = email_tmpl % dct
+ if opts.split:
+ prop_rcpts = dct['email'].split(opts.split)
+ else:
+ prop_rcpts = [dct['email']]
+ rcpts, text = msg_filter(prop_rcpts, text, )
+ rcpts.append(cc_addr)
+ sendmail(rcpts, text, )
+
+if __name__=='__main__':
+ options, args = parse_arguments()
+ setup_sendmail()
+ mail_merge(options, *args)