3 # Copyright (c) 2004 The Trustees of Princeton University (Trustees).
5 # Faiyaz Ahmed <faiyaza@cs.princeton.edu>
7 # $Id: mailer.py,v 1.9 2007/07/03 19:57:16 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/rpm/opt/rt3/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 setAdminCCViaRT(ticket_id, to):
38 # Set ENV Variables/PATH
40 if ticket_id == None or ticket_id == "":
41 raise Exception("ERROR: ticket_id must be set to some integer value")
43 # This will raise an exception if it is not a valid id.
44 i_ticket_id = int(ticket_id)
46 # create a comma-separated list
48 cmd = "rt edit ticket/%s set admincc='%s'" % (ticket_id, s_to)
49 (f_in, f_out, f_err) = os.popen3(cmd)
51 l_values = value.split()
52 f_in.close() ; f_out.close() ; f_err.close()
53 if len(l_values) > 3 and "updated" in l_values[3]:
57 print "ERROR: RT failed to update AdminCC for ticket %s" % ticket_id
61 def setSubjectViaRT(ticket_id, subject):
62 # Set ENV Variables/PATH
64 if ticket_id == None or ticket_id == "":
65 raise Exception("ERROR: ticket_id must be set to some integer value")
67 # This will raise an exception if it is not a valid id.
68 i_ticket_id = int(ticket_id)
70 cmd = "rt edit ticket/%s set subject='%s'" % (ticket_id, subject)
71 (f_in, f_out, f_err) = os.popen3(cmd)
73 l_values = value.split()
74 f_in.close() ; f_out.close() ; f_err.close()
75 if len(l_values) > 3 and "updated" in l_values[3]:
79 print "ERROR: RT failed to update subject for ticket %s" % ticket_id
84 def addCommentViaRT(ticket_id, comment):
85 # Set ENV Variables/PATH
87 if ticket_id == None or ticket_id == "":
88 raise Exception("ERROR: ticket_id must be set to some integer value")
90 # This will raise an exception if it is not a valid id.
91 i_ticket_id = int(ticket_id)
93 cmd = "rt comment -m '%s' ticket/%s" % (comment, i_ticket_id)
94 (f_in, f_out, f_err) = os.popen3(cmd)
96 l_values = value.split()
97 f_in.close() ; f_out.close() ; f_err.close()
98 if len(l_values) > 1 and "recorded" in l_values[1]:
103 f_in.close() ; f_out.close() ; f_err.close()
104 print "ERROR: RT failed to add comment to id %s" % ticket_id
108 def closeTicketViaRT(ticket_id, comment):
109 # Set ENV Variables/PATH
110 _setupRTenvironment()
111 if ticket_id == None or ticket_id == "":
112 raise Exception("ERROR: ticket_id must be set to some integer value")
114 # This will raise an exception if it is not a valid id.
115 i_ticket_id = int(ticket_id)
117 # Append comment to RT ticket
118 addCommentViaRT(ticket_id, comment)
121 cmd = "rt edit ticket/%s set status=resolved" % i_ticket_id
122 (f_in, f_out, f_err) = os.popen3(cmd)
127 l_values = value.split()
128 if len(l_values) >= 4 and "updated" in l_values[3]:
133 print "FAILED to resolve Ticket %d" % ticket_id
134 print "FAILED to resolve Ticket %d" % i_ticket_id
138 def emailViaRT(subject, text, to, ticket_id=None):
139 if ticket_id == None or ticket_id == "":
140 return emailViaRT_NoTicket(subject, text, to)
143 # Set ENV Variables/PATH
144 _setupRTenvironment()
146 if config.mail and not config.debug:
147 setSubjectViaRT(ticket_id, subject)
148 setAdminCCViaRT(ticket_id, to)
150 cmd = "rt correspond -m - %s" % ticket_id
151 (f_in, f_out, f_err) = os.popen3(cmd)
157 # TODO: rt doesn't write to stderr on error!!!
159 raise Exception, f_err.read()
162 f_out.close(); del f_out
163 f_err.close(); del f_err
169 def emailViaRT_NoTicket(subject, text, to):
170 """Use RT command line tools to send email.
171 return the generated RT ticket ID number.
175 if config.mail and config.debug:
178 # Set ENV Variables/PATH
179 _setupRTenvironment()
181 # NOTE: AdminCc: (in PLC's RT configuration) gets an email sent.
182 # This is not the case (surprisingly) for Cc:
183 input_text = "Subject: %s\n"
184 input_text += "Requestor: monitor@planet-lab.org\n"
185 input_text += "id: ticket/new\n"
186 input_text += "Queue: Monitor\n"
188 input_text += "AdminCc: %s\n" % recipient
189 input_text += "Text: %s"
191 # Add a space for each new line to get RT to accept the file.
192 spaced_text = reformat_for_rt(text)
194 if config.mail and not config.debug:
195 cmd = "rt create -i -t ticket"
196 (f_in, f_out, f_err) = os.popen3(cmd)
197 f_in.write(input_text % (subject, spaced_text))
202 # TODO: rt doesn't write to stderr on error!!!
204 raise Exception, f_err.read()
206 print "MAILER: ticket value == %s" % value.split()[2]
207 i_ticket = int(value.split()[2])
208 # clean up the child process.
209 f_in.close(); del f_in
210 f_out.close(); del f_out
211 f_err.close(); del f_err
213 elif config.mail and config.debug:
214 email(subject, spaced_text, to)
221 def email(subject, text, to):
222 """Create a mime-message that will render HTML in popular
223 MUAs, text in better ones"""
228 if (config.mail and config.debug) or (not config.mail and not config.debug and config.bcc):
231 out = cStringIO.StringIO() # output buffer for our message
232 txtin = cStringIO.StringIO(text)
234 writer = MimeWriter.MimeWriter(out)
236 # set up some basic headers... we put subject here
237 # because smtplib.sendmail expects it to be in the
240 writer.addheader("Subject", subject)
241 if to.__class__ == [].__class__ :
242 writer.addheader("To", to[0])
244 for dest in to[1:len(to)]:
247 writer.addheader("Cc", cc)
249 writer.addheader("To", to)
251 if config.bcc and not config.debug:
252 writer.addheader("Bcc", config.email)
254 writer.addheader("Reply-To", 'monitor@planet-lab.org')
256 writer.addheader("MIME-Version", "1.0")
258 # start the multipart section of the message
259 # multipart/alternative seems to work better
260 # on some MUAs than multipart/mixed
262 writer.startmultipartbody("alternative")
263 writer.flushheaders()
265 # the plain text section
267 subpart = writer.nextpart()
268 subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
269 pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
270 mimetools.encode(txtin, pout, 'quoted-printable')
273 # Now that we're done, close our writer and
274 # return the message body
282 # mail and debug, 'to' changed at the beginning'
283 # nomail, but report who I'd send to.
286 # This is normal operation
287 server = smtplib.SMTP(MTA)
288 server.sendmail(FROM, to, msg)
289 if config.bcc and not config.debug:
290 server.sendmail(FROM, config.email, msg)
292 except Exception, err:
293 print "Mailer error: %s" % err
294 elif not config.debug and not config.mail and config.bcc:
296 server = smtplib.SMTP(MTA)
297 server.sendmail(FROM, to, msg)
299 except Exception, err:
300 print "Mailer error: %s" % err
302 #print "Would mail %s" %to
303 logger.debug("Would send mail to %s" % to)
305 if __name__=="__main__":
309 #email("[spam] bcc test from golf.cs.princeton.edu",
310 # "It gets to both recipients",
311 # "soltesz@cs.utk.edu")
312 #emailViaRT("rt via golf",
313 # "It gets to both recipients",
314 # "soltesz@cs.utk.edu")
315 email("Re: [PL #21323] TEST 7",
316 mailtxt.newbootcd_one[1] % {'hostname_list':"hostname list..."},
317 ['monitor@planet-lab.org'])
318 #print "ticketid: %d" % id
319 #id = plc.siteId(["alice.cs.princeton.edu"])
322 #email('TEST', emailTxt.mailtxt.ssh % {'hostname': "ALICE.cs.princeton.edu"}, "tech-" + id + "@sites.planet-lab.org")
325 #email("TEST111", "I'd like to see if this works anywhere", ["soltesz@cs.princeton.edu", "soltesz@cs.utk.edu"])
326 #print "mailer does nothing in main()"