1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__ = """MailProcessor
15 Base class module that other servers will subclass.
16 """
17
18 import email, socket, rfc822, types
19 import calendar
20 from datetime import tzinfo, timedelta, datetime
21
22 from Event import Event
23
24 from Products.ZenUtils.Utils import unused
25
26 import logging
27 log = logging.getLogger("zen.mail")
28
29
31 """
32 Defaults for events created by the processor
33 """
34 agent="zenmail"
35 eventGroup="mail"
36
37
38
39
40 ZERO = timedelta(0)
41
42
43
44
46 """Fixed offset in minutes east from UTC."""
47
49 self.__offset = timedelta(minutes = offset)
50 self.__name = name
51
54
57
60
61
62
64 """
65 Base class for parsing email messages that are retrieved via POP or
66 received via SMTP.
67 """
68
69 - def __init__(self, zem, defaultSeverity = 2):
70 """
71 Initializer
72
73 @param zem: class that provides sendEvent() method
74 @type zem: Zenoss event manager object
75 @param defaultSeverity: severity level to use if we can't figure one out
76 @type defaultSeverity: integer
77 """
78 self.zem = zem
79 self.eventSeverity = defaultSeverity
80
81
83 """
84 Convert an e-mail message into a Zenoss event.
85
86 @param messageStr: e-mail message
87 @type messageStr: string
88 """
89 message = email.message_from_string(messageStr)
90 self.message = message
91
92 fromAddr = message.get('From')
93 log.debug("Found a 'from' address of %s" % fromAddr)
94 if not fromAddr or fromAddr.find('@') == -1:
95 log.warning("Unable to process the 'from' address %s -- ignoring mail" \
96 % fromAddr)
97 return
98
99 fromAddr = message.get('From').split('@')[1].rstrip('>')
100 fromAddr = fromAddr.split(' ')[0]
101 log.debug("The from address after processing is '%s'" % fromAddr)
102 try:
103 fromIp = socket.gethostbyname(fromAddr)
104 except socket.gaierror:
105 fromIp = None
106 log.info('Hostname lookup failed for host: %s' % fromAddr)
107
108 subject = message.get('Subject')
109
110
111
112
113
114
115
116
117 t = rfc822.parsedate_tz(message.get('Date'))
118
119 offset_secs = t[-1]
120
121
122 offset_mins = offset_secs / 60
123 tz = FixedOffset(offset_mins, "Unknown")
124
125
126 dt = datetime(t[0], t[1], t[2], t[3], t[4], t[5], 0, tz)
127 secs = calendar.timegm(dt.utctimetuple())
128 log.info('Timestamp of the event (should be in UTC): %f' % secs)
129
130 event = MailEvent(device=fromAddr, rcvtime=secs)
131 if fromIp:
132 event.ipAddress = fromIp
133
134 payloads = message.get_payload()
135 payload = 'This is the default message'
136 while type(payloads) == types.ListType:
137 payloads = payloads[0].get_payload()
138 if type(payloads) == types.StringType:
139 payload = payloads
140
141 body = payload
142 event.summary = subject
143 event.message = body
144 self.enrich(event, subject)
145
146 event = self.buildEventClassKey(event)
147 log.info('Sending event...')
148 self.zem.sendEvent(event.__dict__)
149 log.info('The event has been sent.')
150
151
152 - def enrich(self, event, subject):
153 """
154 Sanitize the event facility and severity fields.
155
156 @param event: event
157 @type event: simple class
158 @param subject: e-mail subject (unused)
159 @type subject: string
160 """
161 unused(subject)
162 event.facility = "unknown"
163 event.severity = self.eventSeverity
164
165
167 """
168 Set the Zenoss eventClassKey
169
170 @param evt: event
171 @type evt: simple class
172 @return: modified event
173 @rtype: simple class
174 """
175 if hasattr(evt, 'eventClassKey') or hasattr(evt, 'eventClass'):
176 return evt
177 elif hasattr(evt, 'ntevid'):
178 evt.eventClassKey = "%s_%s" % (evt.component,evt.ntevid)
179 elif hasattr(evt, 'component'):
180 evt.eventClassKey = evt.component
181 if hasattr(evt, 'eventClassKey'):
182 log.debug("eventClassKey=%s", evt.eventClassKey)
183 else:
184 log.debug("No eventClassKey assigned")
185 return evt
186
187
188
190 """
191 Extension point for messages received via POP. If you need to
192 override the behavior of "process" you should do so by
193 implementing it here.
194 """
195
196 - def __init__(self, zem, defaultSeverity = 2):
197 """
198 Initializer
199
200 @param zem: class that provides sendEvent() method
201 @type zem: Zenoss event manager object
202 @param defaultSeverity: severity level to use if we can't figure one out
203 """
204 MessageProcessor.__init__(self, zem, defaultSeverity)
205
206
207
209 """
210 Extension point for messages received via SMTP. If you need to
211 override the behavior of "process" you should do so by
212 implementing it here.
213 """
214
215 - def __init__(self, zem, defaultSeverity = 2):
216 """
217 Initializer
218
219 @param zem: class that provides sendEvent() method
220 @type zem: Zenoss event manager object
221 @param defaultSeverity: severity level to use if we can't figure one out
222 """
223 MessageProcessor.__init__(self, zem, defaultSeverity)
224