##// END OF EJS Templates
Skip email notification if email or server are empty
Miguel Valdez -
r733:f32e8d5e77bd
parent child
Show More
@@ -1,382 +1,388
1 """The admin module contains all administrative classes relating to the schain python api.
1 """The admin module contains all administrative classes relating to the schain python api.
2
2
3 The main role of this module is to send some reports. It contains a
3 The main role of this module is to send some reports. It contains a
4 notification class and a standard error handing class.
4 notification class and a standard error handing class.
5
5
6 $Id: admin.py 3966 2015-12-01 14:32:29Z miguel.urco $
6 $Id: admin.py 3966 2015-12-01 14:32:29Z miguel.urco $
7 """
7 """
8 import os, sys
8 import os, sys
9 import traceback
9 import traceback
10 import smtplib
10 import smtplib
11 import ConfigParser
11 import ConfigParser
12 import StringIO
12 import StringIO
13
13
14 from email.mime.text import MIMEText
14 from email.mime.text import MIMEText
15 from email.mime.application import MIMEApplication
15 from email.mime.application import MIMEApplication
16 from email.mime.multipart import MIMEMultipart
16 from email.mime.multipart import MIMEMultipart
17
17
18 class SchainConfigure():
18 class SchainConfigure():
19
19
20 __DEFAULT_ADMINISTRATOR_EMAIL = "miguel.urco@jro.igp.gob.pe"
20 __DEFAULT_ADMINISTRATOR_EMAIL = "miguel.urco@jro.igp.gob.pe"
21 __DEFAULT_EMAIL_SERVER = "jro-zimbra.igp.gob.pe"
21 __DEFAULT_EMAIL_SERVER = "jro-zimbra.igp.gob.pe"
22 __DEFAULT_SENDER_EMAIL = "notifier-schain@jro.igp.gob.pe"
22 __DEFAULT_SENDER_EMAIL = "notifier-schain@jro.igp.gob.pe"
23 __DEFAULT_SENDER_PASS = ""
23 __DEFAULT_SENDER_PASS = ""
24
24
25 __SCHAIN_ADMINISTRATOR_EMAIL = "CONTACT"
25 __SCHAIN_ADMINISTRATOR_EMAIL = "CONTACT"
26 __SCHAIN_EMAIL_SERVER = "MAILSERVER"
26 __SCHAIN_EMAIL_SERVER = "MAILSERVER"
27 __SCHAIN_SENDER_EMAIL = "MAILSERVER_ACCOUNT"
27 __SCHAIN_SENDER_EMAIL = "MAILSERVER_ACCOUNT"
28 __SCHAIN_SENDER_PASS = "MAILSERVER_PASSWORD"
28 __SCHAIN_SENDER_PASS = "MAILSERVER_PASSWORD"
29
29
30 def __init__(self, initFile = None):
30 def __init__(self, initFile = None):
31
31
32 # Set configuration file
32 # Set configuration file
33 if (initFile == None):
33 if (initFile == None):
34 self.__confFilePath = "/etc/schain.conf"
34 self.__confFilePath = "/etc/schain.conf"
35 else:
35 else:
36 self.__confFilePath = initFile
36 self.__confFilePath = initFile
37
37
38 # open configuration file
38 # open configuration file
39 try:
39 try:
40 self.__confFile = open(self.__confFilePath, "r")
40 self.__confFile = open(self.__confFilePath, "r")
41 except IOError:
41 except IOError:
42 # can't read from file - use all hard-coded values
42 # can't read from file - use all hard-coded values
43 self.__initFromHardCode()
43 self.__initFromHardCode()
44 return
44 return
45
45
46 # create Parser using standard module ConfigParser
46 # create Parser using standard module ConfigParser
47 self.__parser = ConfigParser.ConfigParser()
47 self.__parser = ConfigParser.ConfigParser()
48
48
49 # read conf file into a StringIO with "[madrigal]\n" section heading prepended
49 # read conf file into a StringIO with "[madrigal]\n" section heading prepended
50 strConfFile = StringIO.StringIO("[schain]\n" + self.__confFile.read())
50 strConfFile = StringIO.StringIO("[schain]\n" + self.__confFile.read())
51
51
52 # parse StringIO configuration file
52 # parse StringIO configuration file
53 self.__parser.readfp(strConfFile)
53 self.__parser.readfp(strConfFile)
54
54
55 # read information from configuration file
55 # read information from configuration file
56 self.__readConfFile()
56 self.__readConfFile()
57
57
58 # close conf file
58 # close conf file
59 self.__confFile.close()
59 self.__confFile.close()
60
60
61
61
62 def __initFromHardCode(self):
62 def __initFromHardCode(self):
63
63
64 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
64 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
65 self.__sender_pass = self.__DEFAULT_SENDER_PASS
65 self.__sender_pass = self.__DEFAULT_SENDER_PASS
66 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
66 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
67 self.__email_server = self.__DEFAULT_EMAIL_SERVER
67 self.__email_server = self.__DEFAULT_EMAIL_SERVER
68
68
69 def __readConfFile(self):
69 def __readConfFile(self):
70 """__readConfFile is a private helper function that reads information from the parsed config file.
70 """__readConfFile is a private helper function that reads information from the parsed config file.
71
71
72 Inputs: None
72 Inputs: None
73
73
74 Returns: Void.
74 Returns: Void.
75
75
76 Affects: Initializes class member variables that are found in the config file.
76 Affects: Initializes class member variables that are found in the config file.
77
77
78 Exceptions: MadrigalError thrown if any key not found.
78 Exceptions: MadrigalError thrown if any key not found.
79 """
79 """
80
80
81 # get the sender email
81 # get the sender email
82 try:
82 try:
83 self.__sender_email = self.__parser.get("schain", self.__SCHAIN_SENDER_EMAIL)
83 self.__sender_email = self.__parser.get("schain", self.__SCHAIN_SENDER_EMAIL)
84 except:
84 except:
85 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
85 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
86
86
87 # get the sender password
87 # get the sender password
88 try:
88 try:
89 self.__sender_pass = self.__parser.get("schain", self.__SCHAIN_SENDER_PASS)
89 self.__sender_pass = self.__parser.get("schain", self.__SCHAIN_SENDER_PASS)
90 except:
90 except:
91 self.__sender_pass = self.__DEFAULT_SENDER_PASS
91 self.__sender_pass = self.__DEFAULT_SENDER_PASS
92
92
93 # get the administrator email
93 # get the administrator email
94 try:
94 try:
95 self.__admin_email = self.__parser.get("schain", self.__SCHAIN_ADMINISTRATOR_EMAIL)
95 self.__admin_email = self.__parser.get("schain", self.__SCHAIN_ADMINISTRATOR_EMAIL)
96 except:
96 except:
97 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
97 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
98
98
99 # get the server email
99 # get the server email
100 try:
100 try:
101 self.__email_server = self.__parser.get("schain", self.__SCHAIN_EMAIL_SERVER)
101 self.__email_server = self.__parser.get("schain", self.__SCHAIN_EMAIL_SERVER)
102 except:
102 except:
103 self.__email_server = self.__DEFAULT_EMAIL_SERVER
103 self.__email_server = self.__DEFAULT_EMAIL_SERVER
104
104
105 def getEmailServer(self):
105 def getEmailServer(self):
106
106
107 return self.__email_server
107 return self.__email_server
108
108
109 def getSenderEmail(self):
109 def getSenderEmail(self):
110
110
111 return self.__sender_email
111 return self.__sender_email
112
112
113 def getSenderPass(self):
113 def getSenderPass(self):
114
114
115 return self.__sender_pass
115 return self.__sender_pass
116
116
117 def getAdminEmail(self):
117 def getAdminEmail(self):
118
118
119 return self.__admin_email
119 return self.__admin_email
120
120
121 class SchainNotify:
121 class SchainNotify:
122 """SchainNotify is an object used to send messages to an administrator about a Schain software.
122 """SchainNotify is an object used to send messages to an administrator about a Schain software.
123
123
124 This object provides functions needed to send messages to an administrator about a Schain , for now
124 This object provides functions needed to send messages to an administrator about a Schain , for now
125 only sendAlert, which sends an email to the site administrator found is ADMIN_EMAIL
125 only sendAlert, which sends an email to the site administrator found is ADMIN_EMAIL
126
126
127 Usage example:
127 Usage example:
128
128
129 import schainpy.admin
129 import schainpy.admin
130
130
131 try:
131 try:
132
132
133 adminObj = schainpy.admin.SchainNotify()
133 adminObj = schainpy.admin.SchainNotify()
134 adminObj.sendAlert('This is important!', 'Important Message')
134 adminObj.sendAlert('This is important!', 'Important Message')
135
135
136 except schainpy.admin.SchainError, e:
136 except schainpy.admin.SchainError, e:
137
137
138 print e.getExceptionStr()
138 print e.getExceptionStr()
139
139
140
140
141 Non-standard Python modules used:
141 Non-standard Python modules used:
142 None
142 None
143
143
144 Exceptions thrown: None - Note that SchainNotify tries every trick it knows to avoid
144 Exceptions thrown: None - Note that SchainNotify tries every trick it knows to avoid
145 throwing exceptions, since this is the class that will generally be called when there is a problem.
145 throwing exceptions, since this is the class that will generally be called when there is a problem.
146
146
147 Change history:
147 Change history:
148
148
149 Written by "Miguel Urco":mailto:miguel.urco@jro.igp.gob.pe Dec. 1, 2015
149 Written by "Miguel Urco":mailto:miguel.urco@jro.igp.gob.pe Dec. 1, 2015
150 """
150 """
151
151
152 #constants
152 #constants
153
153
154 def __init__(self):
154 def __init__(self):
155 """__init__ initializes SchainNotify by getting some basic information from SchainDB and SchainSite.
155 """__init__ initializes SchainNotify by getting some basic information from SchainDB and SchainSite.
156
156
157 Note that SchainNotify tries every trick it knows to avoid throwing exceptions, since
157 Note that SchainNotify tries every trick it knows to avoid throwing exceptions, since
158 this is the class that will generally be called when there is a problem.
158 this is the class that will generally be called when there is a problem.
159
159
160 Inputs: Existing SchainDB object, by default = None.
160 Inputs: Existing SchainDB object, by default = None.
161
161
162 Returns: void
162 Returns: void
163
163
164 Affects: Initializes self.__binDir.
164 Affects: Initializes self.__binDir.
165
165
166 Exceptions: None.
166 Exceptions: None.
167 """
167 """
168
168
169 # note that the main configuration file is unavailable
169 # note that the main configuration file is unavailable
170 # the best that can be done is send an email to root using localhost mailserver
170 # the best that can be done is send an email to root using localhost mailserver
171 confObj = SchainConfigure()
171 confObj = SchainConfigure()
172
172
173 self.__emailFromAddress = confObj.getSenderEmail()
173 self.__emailFromAddress = confObj.getSenderEmail()
174 self.__emailPass = confObj.getSenderPass()
174 self.__emailPass = confObj.getSenderPass()
175 self.__emailToAddress = confObj.getAdminEmail()
175 self.__emailToAddress = confObj.getAdminEmail()
176 self.__emailServer = confObj.getEmailServer()
176 self.__emailServer = confObj.getEmailServer()
177
177
178 def sendEmail(self, email_from, email_to, subject='Error running ...', message="", subtitle="", filename="", html_format=True):
178 def sendEmail(self, email_from, email_to, subject='Error running ...', message="", subtitle="", filename="", html_format=True):
179
179
180 if not email_to:
181 return 0
182
183 if not self.__emailServer:
184 return 0
185
180 msg = MIMEMultipart()
186 msg = MIMEMultipart()
181 msg['Subject'] = subject
187 msg['Subject'] = subject
182 msg['From'] = "(Python SChain API): " + email_from
188 msg['From'] = "(Python SChain API): " + email_from
183 msg['Reply-to'] = email_from
189 msg['Reply-to'] = email_from
184 msg['To'] = email_to
190 msg['To'] = email_to
185
191
186 # That is what u see if dont have an email reader:
192 # That is what u see if dont have an email reader:
187 msg.preamble = 'SChainPy'
193 msg.preamble = 'SChainPy'
188
194
189 if html_format:
195 if html_format:
190 message = "<h1> %s </h1>" %subject + "<h3>" + subtitle.replace("\n", "</h3><h3>\n") + "</h3>" + message.replace("\n", "<br>\n")
196 message = "<h1> %s </h1>" %subject + "<h3>" + subtitle.replace("\n", "</h3><h3>\n") + "</h3>" + message.replace("\n", "<br>\n")
191 message = "<html>\n" + message + '</html>'
197 message = "<html>\n" + message + '</html>'
192
198
193 # This is the textual part:
199 # This is the textual part:
194 part = MIMEText(message, "html")
200 part = MIMEText(message, "html")
195 else:
201 else:
196 message = subject + "\n" + subtitle + "\n" + message
202 message = subject + "\n" + subtitle + "\n" + message
197 part = MIMEText(message)
203 part = MIMEText(message)
198
204
199 msg.attach(part)
205 msg.attach(part)
200
206
201 if os.path.isfile(filename):
207 if os.path.isfile(filename):
202 # This is the binary part(The Attachment):
208 # This is the binary part(The Attachment):
203 part = MIMEApplication(open(filename,"rb").read())
209 part = MIMEApplication(open(filename,"rb").read())
204 part.add_header('Content-Disposition',
210 part.add_header('Content-Disposition',
205 'attachment',
211 'attachment',
206 filename=os.path.basename(filename))
212 filename=os.path.basename(filename))
207 msg.attach(part)
213 msg.attach(part)
208
214
209 # Create an instance in SMTP server
215 # Create an instance in SMTP server
210 try:
216 try:
211 smtp = smtplib.SMTP(self.__emailServer)
217 smtp = smtplib.SMTP(self.__emailServer)
212 except:
218 except:
213 print "***** Could not connect to server %s *****" %self.__emailServer
219 print "***** Could not connect to server %s *****" %self.__emailServer
214 return 0
220 return 0
215
221
216 # Start the server:
222 # Start the server:
217 # smtp.ehlo()
223 # smtp.ehlo()
218 if self.__emailPass:
224 if self.__emailPass:
219 smtp.login(self.__emailFromAddress, self.__emailPass)
225 smtp.login(self.__emailFromAddress, self.__emailPass)
220
226
221 # Send the email
227 # Send the email
222 try:
228 try:
223 smtp.sendmail(msg['From'], msg['To'], msg.as_string())
229 smtp.sendmail(msg['From'], msg['To'], msg.as_string())
224 except:
230 except:
225 print "***** Could not send the email to %s *****" %msg['To']
231 print "***** Could not send the email to %s *****" %msg['To']
226 smtp.quit()
232 smtp.quit()
227 return 0
233 return 0
228
234
229 smtp.quit()
235 smtp.quit()
230
236
231 return 1
237 return 1
232
238
233 def sendAlert(self, message, subject = "", subtitle="", filename=""):
239 def sendAlert(self, message, subject = "", subtitle="", filename=""):
234 """sendAlert sends an email with the given message and optional title.
240 """sendAlert sends an email with the given message and optional title.
235
241
236 Inputs: message (string), and optional title (string)
242 Inputs: message (string), and optional title (string)
237
243
238 Returns: void
244 Returns: void
239
245
240 Affects: none
246 Affects: none
241
247
242 Exceptions: None.
248 Exceptions: None.
243 """
249 """
244 print "***** Sending alert to %s *****" %self.__emailToAddress
250 print "***** Sending alert to %s *****" %self.__emailToAddress
245 # set up message
251 # set up message
246
252
247 sent=self.sendEmail(email_from=self.__emailFromAddress,
253 sent=self.sendEmail(email_from=self.__emailFromAddress,
248 email_to=self.__emailToAddress,
254 email_to=self.__emailToAddress,
249 subject=subject,
255 subject=subject,
250 message=message,
256 message=message,
251 subtitle=subtitle,
257 subtitle=subtitle,
252 filename=filename)
258 filename=filename)
253
259
254 if sent:
260 if sent:
255 print "***** Your system administrator has been notified *****"
261 print "***** Your system administrator has been notified *****"
256
262
257
263
258 def notify(self, email, message, subject = "", subtitle="", filename=""):
264 def notify(self, email, message, subject = "", subtitle="", filename=""):
259 """notify sends an email with the given message and title to email.
265 """notify sends an email with the given message and title to email.
260
266
261 Inputs: email (string), message (string), and subject (string)
267 Inputs: email (string), message (string), and subject (string)
262
268
263 Returns: void
269 Returns: void
264
270
265 Affects: none
271 Affects: none
266
272
267 Exceptions: None.
273 Exceptions: None.
268 """
274 """
269
275
270 print "Notifying to %s ..." %email
276 print "Notifying to %s ..." %email
271
277
272 self.sendEmail(email_from=self.__emailFromAddress,
278 self.sendEmail(email_from=self.__emailFromAddress,
273 email_to=email,
279 email_to=email,
274 subject=subject,
280 subject=subject,
275 message=message,
281 message=message,
276 subtitle=subtitle,
282 subtitle=subtitle,
277 filename=filename)
283 filename=filename)
278
284
279 print "***** Your system administrator has been notified *****"
285 print "***** Your system administrator has been notified *****"
280
286
281 class SchainError(Exception):
287 class SchainError(Exception):
282 """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
288 """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
283
289
284 Usage example:
290 Usage example:
285
291
286 import sys, traceback
292 import sys, traceback
287 import schainpy.admin
293 import schainpy.admin
288
294
289 try:
295 try:
290
296
291 test = open('ImportantFile.txt', 'r')
297 test = open('ImportantFile.txt', 'r')
292
298
293 except:
299 except:
294
300
295 raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
301 raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
296 traceback.format_exception(sys.exc_info()[0],
302 traceback.format_exception(sys.exc_info()[0],
297 sys.exc_info()[1],
303 sys.exc_info()[1],
298 sys.exc_info()[2]))
304 sys.exc_info()[2]))
299 """
305 """
300
306
301
307
302 def __init__(self, strInterpretation, exceptionList=None):
308 def __init__(self, strInterpretation, exceptionList=None):
303 """ __init__ gathers the interpretation string along with all information from sys.exc_info().
309 """ __init__ gathers the interpretation string along with all information from sys.exc_info().
304
310
305 Inputs:
311 Inputs:
306 strIntepretation - A string representing the programmer's interpretation of
312 strIntepretation - A string representing the programmer's interpretation of
307 why the exception occurred
313 why the exception occurred
308
314
309 exceptionList - a list of strings completely describing the exception.
315 exceptionList - a list of strings completely describing the exception.
310 Generated by traceback.format_exception(sys.exc_info()[0],
316 Generated by traceback.format_exception(sys.exc_info()[0],
311 sys.exc_info()[1],
317 sys.exc_info()[1],
312 sys.exc_info()[2])
318 sys.exc_info()[2])
313
319
314 Returns: Void.
320 Returns: Void.
315
321
316 Affects: Initializes class member variables _strInterp, _strExcList.
322 Affects: Initializes class member variables _strInterp, _strExcList.
317
323
318 Exceptions: None.
324 Exceptions: None.
319 """
325 """
320
326
321 if not exceptionList:
327 if not exceptionList:
322 exceptionList = traceback.format_exception(sys.exc_info()[0],
328 exceptionList = traceback.format_exception(sys.exc_info()[0],
323 sys.exc_info()[1],
329 sys.exc_info()[1],
324 sys.exc_info()[2])
330 sys.exc_info()[2])
325
331
326 self._strInterp = strInterpretation
332 self._strInterp = strInterpretation
327 self._strExcList = exceptionList
333 self._strExcList = exceptionList
328
334
329
335
330 def getExceptionStr(self):
336 def getExceptionStr(self):
331 """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
337 """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
332
338
333 Inputs: None
339 Inputs: None
334
340
335 Returns: A formatted string ready for printing completely describing the exception.
341 Returns: A formatted string ready for printing completely describing the exception.
336
342
337 Affects: None
343 Affects: None
338
344
339 Exceptions: None.
345 Exceptions: None.
340 """
346 """
341 excStr = ''
347 excStr = ''
342 excStr = excStr + self._strInterp + '\n\n'
348 excStr = excStr + self._strInterp + '\n\n'
343
349
344 if self._strExcList != None:
350 if self._strExcList != None:
345 for item in self._strExcList:
351 for item in self._strExcList:
346 excStr = excStr + str(item) + '\n'
352 excStr = excStr + str(item) + '\n'
347
353
348 return excStr
354 return excStr
349
355
350 def __str__(self):
356 def __str__(self):
351
357
352 return(self.getExceptionStr())
358 return(self.getExceptionStr())
353
359
354
360
355 def getExceptionHtml(self):
361 def getExceptionHtml(self):
356 """ getExceptionHtml returns an Html formatted string completely describing the exception.
362 """ getExceptionHtml returns an Html formatted string completely describing the exception.
357
363
358 Inputs: None
364 Inputs: None
359
365
360 Returns: A formatted string ready for printing completely describing the exception.
366 Returns: A formatted string ready for printing completely describing the exception.
361
367
362 Affects: None
368 Affects: None
363
369
364 Exceptions: None.
370 Exceptions: None.
365 """
371 """
366
372
367 excStr = '<BR>The following Schain Python exception has occurred:\n<BR>'
373 excStr = '<BR>The following Schain Python exception has occurred:\n<BR>'
368 excStr = excStr + self._strInterp + '\n<BR>\n'
374 excStr = excStr + self._strInterp + '\n<BR>\n'
369
375
370 if self._strExcList != None:
376 if self._strExcList != None:
371 for item in self._strExcList:
377 for item in self._strExcList:
372 excStr = excStr + str(item) + '\n<BR>'
378 excStr = excStr + str(item) + '\n<BR>'
373
379
374 return excStr
380 return excStr
375
381
376 if __name__ == '__main__':
382 if __name__ == '__main__':
377
383
378 test = SchainNotify()
384 test = SchainNotify()
379
385
380 test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
386 test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
381
387
382 print 'Hopefully message sent - check.'
388 print 'Hopefully message sent - check.'
General Comments 0
You need to be logged in to leave comments. Login now