Package ZenEvents :: Module MailProcessor
[hide private]
[frames] | no frames]

Source Code for Module ZenEvents.MailProcessor

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13  #! /usr/bin/env python  
 14   
 15  import email, socket, time, rfc822, types 
 16  import calendar 
 17  from datetime import tzinfo, timedelta, datetime 
 18   
 19  from Event import Event 
 20   
 21  import logging 
 22  log = logging.getLogger("zen.mail") 
 23   
 24   
25 -class MailEvent(Event):
26 agent="zenmail" 27 eventGroup="mail"
28 29 30 ZERO = timedelta(0) 31 32 # A class building tzinfo objects for fixed-offset time zones. 33 # Note that FixedOffset(0, "UTC") is a different way to build a 34 # UTC tzinfo object.
35 -class FixedOffset(tzinfo):
36 """Fixed offset in minutes east from UTC.""" 37
38 - def __init__(self, offset, name):
39 self.__offset = timedelta(minutes = offset) 40 self.__name = name
41
42 - def utcoffset(self, dt):
43 return self.__offset
44
45 - def tzname(self, dt):
46 return self.__name
47
48 - def dst(self, dt):
49 return ZERO
50 51 52
53 -class MessageProcessor(object):
54 '''Base class for parsing email messages that are retrieved via POP or 55 received via SMTP.''' 56
57 - def __init__(self, zem):
58 self.zem = zem
59
60 - def process(self, messageStr):
61 message = email.message_from_string(messageStr) 62 self.message = message 63 64 fromAddr = message.get('From').split('@')[1][:-1] 65 fromAddr = fromAddr.split(' ')[0] 66 try: 67 fromIp = socket.gethostbyname(fromAddr) 68 except socket.gaierror, e: 69 fromIp = None 70 log.error('hostname lookup failed for host: %s' % fromAddr, exc_info=1) 71 72 subject = message.get('Subject') 73 74 # this is tricky... date comes in with an offset value that 75 # represents the number of seconds of difference between the 76 # parsed timezone and UTC. the events database wants all time 77 # as seconds since the epoch and treats it as UTC. as a 78 # result we have to use the datetime class to do the 79 # conversion because the functions in the time module do all 80 # kinds of covnersions "to be helpful" 81 t = rfc822.parsedate_tz(message.get('Date')) 82 83 offset_secs = t[-1] 84 85 # convert the offset in seconds to minutes. calendar wants minutes 86 offset_mins = offset_secs / 60 87 tz = FixedOffset(offset_mins, "Unknown") 88 89 # construct dt using the date and time as well as the timezone 90 dt = datetime(t[0], t[1], t[2], t[3], t[4], t[5], 0, tz) 91 secs = calendar.timegm(dt.utctimetuple()) 92 log.info('timestamp of event (should be in UTC): %f' % secs) 93 94 event = MailEvent(device=fromAddr, ipAddress=fromIp, rcvtime=secs) 95 96 payloads = message.get_payload() 97 payload = 'This is the default message' 98 if type(payloads) == types.ListType: 99 payload = payloads[0].get_payload() 100 if type(payloads) == types.StringType: 101 payload = payloads 102 103 body = payload 104 event.summary = body 105 self.enrich(event, subject) 106 107 event = self.buildEventClassKey(event) 108 log.info('sending event...') 109 self.zem.sendEvent(event) 110 log.info('event sent.')
111 112
113 - def enrich(self, event, subject):
114 pri = self.zem.defaultPriority 115 event.priority = pri 116 event.facility = "unknown" 117 event.severity = 5
118 119
120 - def buildEventClassKey(self, evt):
121 if hasattr(evt, 'eventClassKey') or hasattr(evt, 'eventClass'): 122 return evt 123 elif hasattr(evt, 'ntevid'): 124 evt.eventClassKey = "%s_%s" % (evt.component,evt.ntevid) 125 elif hasattr(evt, 'component'): 126 evt.eventClassKey = evt.component 127 if hasattr(evt, 'eventClassKey'): 128 log.debug("eventClassKey=%s", evt.eventClassKey) 129 else: 130 log.debug("no eventClassKey assigned") 131 return evt
132 133
134 -class POPProcessor(MessageProcessor):
135 '''Extension point for messages received via POP. If you need to 136 override the behavior of "process" you should do so by 137 implementing it here.''' 138
139 - def __init__(self, zem):
140 MessageProcessor.__init__(self, zem)
141 142
143 -class MailProcessor(MessageProcessor):
144 '''Extension point for messages received via SMTP. If you need to 145 override the behavior of "process" you should do so by 146 implementing it here.''' 147
148 - def __init__(self, zem):
149 MessageProcessor.__init__(self, zem)
150