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