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 origFromAddr = fromAddr
94 log.debug("Found a 'from' address of %s" % fromAddr)
95 if not fromAddr or fromAddr.find('@') == -1:
96 log.warning("Unable to process the 'from' address %s -- ignoring mail" \
97 % fromAddr)
98 return
99
100 fromAddr = message.get('From').split('@')[1].rstrip('>')
101 fromAddr = fromAddr.split(' ')[0]
102 log.debug("The from address after processing is '%s'" % fromAddr)
103 try:
104 fromIp = socket.gethostbyname(fromAddr)
105 except socket.gaierror:
106 fromIp = None
107 log.info('Hostname lookup failed for host: %s' % fromAddr)
108
109 subject = message.get('Subject')
110
111
112
113
114
115
116
117
118 t = rfc822.parsedate_tz(message.get('Date'))
119
120 offset_secs = t[-1]
121
122
123 offset_mins = offset_secs / 60
124 tz = FixedOffset(offset_mins, "Unknown")
125
126
127 dt = datetime(t[0], t[1], t[2], t[3], t[4], t[5], 0, tz)
128 secs = calendar.timegm(dt.utctimetuple())
129 log.info('Timestamp of the event (should be in UTC): %f' % secs)
130
131 event = MailEvent(device=fromAddr, rcvtime=secs,
132 fromEmailAddress=origFromAddr)
133 if fromIp:
134 event.ipAddress = fromIp
135
136 payloads = message.get_payload()
137 payload = 'This is the default message'
138 while type(payloads) == types.ListType:
139 payloads = payloads[0].get_payload()
140 if type(payloads) == types.StringType:
141 payload = payloads
142
143 body = payload
144 event.summary = subject
145 event.message = body
146 self.enrich(event, subject)
147
148 event = self.buildEventClassKey(event)
149 log.info('Sending event...')
150 self.zem.sendEvent(event.__dict__)
151 log.info('The event has been sent.')
152
153
154 - def enrich(self, event, subject):
155 """
156 Sanitize the event facility and severity fields.
157
158 @param event: event
159 @type event: simple class
160 @param subject: e-mail subject (unused)
161 @type subject: string
162 """
163 unused(subject)
164 event.facility = "unknown"
165 event.severity = self.eventSeverity
166
167
169 """
170 Set the Zenoss eventClassKey
171
172 @param evt: event
173 @type evt: simple class
174 @return: modified event
175 @rtype: simple class
176 """
177 if getattr(evt, 'eventClassKey', '') or getattr(evt, 'eventClass', ''):
178 return evt
179 elif getattr(evt, 'ntevid', ''):
180 evt.eventClassKey = "%s_%s" % (evt.component,evt.ntevid)
181 elif getattr(evt, 'component', ''):
182 evt.eventClassKey = evt.component
183 else:
184 evt.eventClassKey = 'email'
185
186 if getattr(evt, 'eventClassKey', ''):
187 log.debug("eventClassKey=%s", evt.eventClassKey)
188 else:
189 log.debug("No eventClassKey assigned")
190 return evt
191
192
193
195 """
196 Extension point for messages received via POP. If you need to
197 override the behavior of "process" you should do so by
198 implementing it here.
199 """
200
201 - def __init__(self, zem, defaultSeverity = 2):
202 """
203 Initializer
204
205 @param zem: class that provides sendEvent() method
206 @type zem: Zenoss event manager object
207 @param defaultSeverity: severity level to use if we can't figure one out
208 """
209 MessageProcessor.__init__(self, zem, defaultSeverity)
210
211
212
214 """
215 Extension point for messages received via SMTP. If you need to
216 override the behavior of "process" you should do so by
217 implementing it here.
218 """
219
220 - def __init__(self, zem, defaultSeverity = 2):
221 """
222 Initializer
223
224 @param zem: class that provides sendEvent() method
225 @type zem: Zenoss event manager object
226 @param defaultSeverity: severity level to use if we can't figure one out
227 """
228 MessageProcessor.__init__(self, zem, defaultSeverity)
229