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 getattr(evt, 'eventClassKey', '') or getattr(evt, 'eventClass', ''):
176 return evt
177 elif getattr(evt, 'ntevid', ''):
178 evt.eventClassKey = "%s_%s" % (evt.component,evt.ntevid)
179 elif getattr(evt, 'component', ''):
180 evt.eventClassKey = evt.component
181 else:
182 evt.eventClassKey = 'email'
183
184 if getattr(evt, 'eventClassKey', ''):
185 log.debug("eventClassKey=%s", evt.eventClassKey)
186 else:
187 log.debug("No eventClassKey assigned")
188 return evt
189
190
191
193 """
194 Extension point for messages received via POP. If you need to
195 override the behavior of "process" you should do so by
196 implementing it here.
197 """
198
199 - def __init__(self, zem, defaultSeverity = 2):
200 """
201 Initializer
202
203 @param zem: class that provides sendEvent() method
204 @type zem: Zenoss event manager object
205 @param defaultSeverity: severity level to use if we can't figure one out
206 """
207 MessageProcessor.__init__(self, zem, defaultSeverity)
208
209
210
212 """
213 Extension point for messages received via SMTP. If you need to
214 override the behavior of "process" you should do so by
215 implementing it here.
216 """
217
218 - def __init__(self, zem, defaultSeverity = 2):
219 """
220 Initializer
221
222 @param zem: class that provides sendEvent() method
223 @type zem: Zenoss event manager object
224 @param defaultSeverity: severity level to use if we can't figure one out
225 """
226 MessageProcessor.__init__(self, zem, defaultSeverity)
227