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').replace("\r","").replace("\n", "")
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.debug('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 isinstance(payloads, list):
139 payloads = payloads[0].get_payload()
140 if isinstance(payloads, basestring):
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 self.zem.sendEvent(event.__dict__)
150
151 - def enrich(self, event, subject):
152 """
153 Sanitize the event facility and severity fields.
154
155 @param event: event
156 @type event: simple class
157 @param subject: e-mail subject (unused)
158 @type subject: string
159 """
160 unused(subject)
161 event.facility = "unknown"
162 event.severity = self.eventSeverity
163
164
166 """
167 Set the Zenoss eventClassKey
168
169 @param evt: event
170 @type evt: simple class
171 @return: modified event
172 @rtype: simple class
173 """
174 if getattr(evt, 'eventClassKey', '') or getattr(evt, 'eventClass', ''):
175 return evt
176 elif getattr(evt, 'ntevid', ''):
177 evt.eventClassKey = "%s_%s" % (evt.component,evt.ntevid)
178 elif getattr(evt, 'component', ''):
179 evt.eventClassKey = evt.component
180 else:
181 evt.eventClassKey = 'email'
182
183 if getattr(evt, 'eventClassKey', ''):
184 log.debug("eventClassKey=%s", evt.eventClassKey)
185 else:
186 log.debug("No eventClassKey assigned")
187 return evt
188
189
190
192 """
193 Extension point for messages received via POP. If you need to
194 override the behavior of "process" you should do so by
195 implementing it here.
196 """
197
198 - def __init__(self, zem, defaultSeverity = 2):
199 """
200 Initializer
201
202 @param zem: class that provides sendEvent() method
203 @type zem: Zenoss event manager object
204 @param defaultSeverity: severity level to use if we can't figure one out
205 """
206 MessageProcessor.__init__(self, zem, defaultSeverity)
207
208
209
211 """
212 Extension point for messages received via SMTP. If you need to
213 override the behavior of "process" you should do so by
214 implementing it here.
215 """
216
217 - def __init__(self, zem, defaultSeverity = 2):
218 """
219 Initializer
220
221 @param zem: class that provides sendEvent() method
222 @type zem: Zenoss event manager object
223 @param defaultSeverity: severity level to use if we can't figure one out
224 """
225 MessageProcessor.__init__(self, zem, defaultSeverity)
226