3 # Copyright (c) 2004 The Trustees of Princeton University (Trustees).
5 # Faiyaz Ahmed <faiyaza@cs.princeton.edu>
7 # $Id: mailer.py,v 1.10 2007/08/08 13:28:06 soltesz Exp $
10 from config import config
16 logger = logging.getLogger("monitor")
19 FROM="monitor@planet-lab.org"
21 def reformat_for_rt(text):
22 lines = text.split("\n")
25 spaced_text += " %s\n" %line
29 def _setupRTenvironment():
30 os.environ['PATH'] = os.environ['PATH'] + ":/home/soltesz/local/bin/"
31 os.environ['RTSERVER'] = "https://rt.planet-lab.org/"
32 os.environ['RTUSER'] = "monitor"
33 os.environ['RTPASSWD'] = "ssorcmor"
34 os.environ['RTDEBUG'] = "0"
37 def setTicketStatus(ticket_id, status):
39 if ticket_id == None or ticket_id == "":
42 cmd = "rt edit ticket/%s set status=%s" % (ticket_id, status)
43 (f_in, f_out, f_err) = os.popen3(cmd)
45 l_values = value.split('\n')
46 return "".join(l_values).strip()
48 def getTicketStatus(ticket_id):
50 if ticket_id == None or ticket_id == "":
53 cmd = "rt show -t ticket -f id,subject,status,queue %s" % (ticket_id)
54 (f_in, f_out, f_err) = os.popen3(cmd)
56 l_values = value.split('\n')
59 if len(line) == 0: continue
60 vals = line.split(':')
62 r_values[key] = "".join(vals[1:])
63 r_values[key] = r_values[key].strip()
66 def setAdminCCViaRT(ticket_id, to):
67 # Set ENV Variables/PATH
69 if ticket_id == None or ticket_id == "":
70 raise Exception("ERROR: ticket_id must be set to some integer value")
72 # This will raise an exception if it is not a valid id.
73 i_ticket_id = int(ticket_id)
75 # create a comma-separated list
77 cmd = "rt edit ticket/%s set admincc='%s'" % (ticket_id, s_to)
78 (f_in, f_out, f_err) = os.popen3(cmd)
80 l_values = value.split()
81 f_in.close() ; f_out.close() ; f_err.close()
82 if len(l_values) > 3 and "updated" in l_values[3]:
87 print "ERROR: RT failed to update AdminCC for ticket %s" % ticket_id
91 def setSubjectViaRT(ticket_id, subject):
92 # Set ENV Variables/PATH
94 if ticket_id == None or ticket_id == "":
95 raise Exception("ERROR: ticket_id must be set to some integer value")
97 # This will raise an exception if it is not a valid id.
98 i_ticket_id = int(ticket_id)
100 cmd = "rt edit ticket/%s set subject='%s'" % (ticket_id, subject)
101 (f_in, f_out, f_err) = os.popen3(cmd)
103 l_values = value.split()
104 f_in.close() ; f_out.close() ; f_err.close()
105 if len(l_values) > 3 and "updated" in l_values[3]:
109 print "VALUE:", value
110 print "ERROR: RT failed to update subject for ticket %s" % ticket_id
115 def addCommentViaRT(ticket_id, comment):
116 # Set ENV Variables/PATH
117 _setupRTenvironment()
118 if ticket_id == None or ticket_id == "":
119 raise Exception("ERROR: ticket_id must be set to some integer value")
121 # This will raise an exception if it is not a valid id.
122 i_ticket_id = int(ticket_id)
124 cmd = "rt comment -m '%s' ticket/%s" % (comment, i_ticket_id)
125 (f_in, f_out, f_err) = os.popen3(cmd)
127 l_values = value.split()
128 f_in.close() ; f_out.close() ; f_err.close()
129 if len(l_values) > 1 and "recorded" in l_values[1]:
134 f_in.close() ; f_out.close() ; f_err.close()
135 print "ERROR: RT failed to add comment to id %s" % ticket_id
139 def closeTicketViaRT(ticket_id, comment):
140 # Set ENV Variables/PATH
141 _setupRTenvironment()
142 if ticket_id == None or ticket_id == "":
143 raise Exception("ERROR: ticket_id must be set to some integer value")
145 # This will raise an exception if it is not a valid id.
146 i_ticket_id = int(ticket_id)
148 # Append comment to RT ticket
149 addCommentViaRT(ticket_id, comment)
152 cmd = "rt edit ticket/%s set status=resolved" % i_ticket_id
153 (f_in, f_out, f_err) = os.popen3(cmd)
158 l_values = value.split()
159 if len(l_values) >= 4 and "updated" in l_values[3]:
163 print "VALUE: ", value
165 print "FAILED to resolve Ticket %s" % ticket_id
166 print "FAILED to resolve Ticket %s" % i_ticket_id
170 def emailViaRT(subject, text, to, ticket_id=None):
171 if ticket_id == None or ticket_id == "":
173 return emailViaRT_NoTicket(subject, text, to)
176 # Set ENV Variables/PATH
177 _setupRTenvironment()
179 if config.mail and not config.debug:
180 setSubjectViaRT(ticket_id, subject)
181 setAdminCCViaRT(ticket_id, to)
183 cmd = "rt correspond -m - %s" % ticket_id
184 (f_in, f_out, f_err) = os.popen3(cmd)
190 # TODO: rt doesn't write to stderr on error!!!
192 raise Exception, f_err.read()
195 f_out.close(); del f_out
196 f_err.close(); del f_err
202 def emailViaRT_NoTicket(subject, text, to):
203 """Use RT command line tools to send email.
204 return the generated RT ticket ID number.
208 if config.mail and config.debug:
211 # Set ENV Variables/PATH
212 _setupRTenvironment()
214 # NOTE: AdminCc: (in PLC's RT configuration) gets an email sent.
215 # This is not the case (surprisingly) for Cc:
216 input_text = "Subject: %s\n"
217 input_text += "Requestor: monitor@planet-lab.org\n"
218 input_text += "id: ticket/new\n"
219 input_text += "Queue: Monitor\n"
221 input_text += "AdminCc: %s\n" % recipient
222 input_text += "Text: %s"
224 # Add a space for each new line to get RT to accept the file.
225 spaced_text = reformat_for_rt(text)
227 if config.mail and not config.debug:
228 cmd = "rt create -i -t ticket"
229 (f_in, f_out, f_err) = os.popen3(cmd)
230 f_in.write(input_text % (subject, spaced_text))
235 # TODO: rt doesn't write to stderr on error!!!
237 raise Exception, f_err.read()
239 print "MAILER: ticket value == %s" % value.split()[2]
240 i_ticket = int(value.split()[2])
241 # clean up the child process.
242 f_in.close(); del f_in
243 f_out.close(); del f_out
244 f_err.close(); del f_err
246 elif config.mail and config.debug:
247 email(subject, spaced_text, to)
254 def email(subject, text, to):
255 """Create a mime-message that will render HTML in popular
256 MUAs, text in better ones"""
261 if (config.mail and config.debug) or (not config.mail and not config.debug and config.bcc):
264 out = cStringIO.StringIO() # output buffer for our message
265 txtin = cStringIO.StringIO(text)
267 writer = MimeWriter.MimeWriter(out)
269 # set up some basic headers... we put subject here
270 # because smtplib.sendmail expects it to be in the
273 writer.addheader("Subject", subject)
274 if to.__class__ == [].__class__ :
275 writer.addheader("To", to[0])
277 for dest in to[1:len(to)]:
280 writer.addheader("Cc", cc)
282 writer.addheader("To", to)
284 if config.bcc and not config.debug:
285 writer.addheader("Bcc", config.email)
287 writer.addheader("Reply-To", 'monitor@planet-lab.org')
289 writer.addheader("MIME-Version", "1.0")
291 # start the multipart section of the message
292 # multipart/alternative seems to work better
293 # on some MUAs than multipart/mixed
295 writer.startmultipartbody("alternative")
296 writer.flushheaders()
298 # the plain text section
300 subpart = writer.nextpart()
301 subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
302 pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
303 mimetools.encode(txtin, pout, 'quoted-printable')
306 # Now that we're done, close our writer and
307 # return the message body
315 # mail and debug, 'to' changed at the beginning'
316 # nomail, but report who I'd send to.
318 for mta in [MTA, 'golf.cs.princeton.edu']:
320 # This is normal operation
325 server = smtplib.SMTP(mta)
326 #server = smtplib.SMTP('golf.cs.princeton.edu')
327 server.sendmail(FROM, to, msg)
328 if config.bcc and not config.debug:
329 server.sendmail(FROM, config.email, msg)
331 except Exception, err:
332 print "Mailer error1: failed using MTA(%s) with: %s" % (mta, err)
334 elif not config.debug and not config.mail and config.bcc:
335 for mta in [MTA, 'golf.cs.princeton.edu']:
337 server = smtplib.SMTP(mta)
338 server.sendmail(FROM, to, msg)
340 except Exception, err:
341 print "Mailer error2: failed using MTA(%s) with: %s" % (mta, err)
343 #print "Would mail %s" %to
344 logger.debug("Would send mail to %s" % to)
346 if __name__=="__main__":
350 #email("[spam] bcc test from golf.cs.princeton.edu",
351 # "It gets to both recipients",
352 # "soltesz@cs.utk.edu")
353 #emailViaRT("rt via golf",
354 # "It gets to both recipients",
355 # "soltesz@cs.utk.edu")
356 email("Re: [PL #21323] TEST 7",
357 mailtxt.newbootcd_one[1] % {'hostname_list':"hostname list..."},
358 ['monitor@planet-lab.org'])
359 #print "ticketid: %d" % id
360 #id = plc.siteId(["alice.cs.princeton.edu"])
363 #email('TEST', emailTxt.mailtxt.ssh % {'hostname': "ALICE.cs.princeton.edu"}, "tech-" + id + "@sites.planet-lab.org")
366 #email("TEST111", "I'd like to see if this works anywhere", ["soltesz@cs.princeton.edu", "soltesz@cs.utk.edu"])
367 #print "mailer does nothing in main()"