Package ZenEvents :: Module zenpop3
[hide private]
[frames] | no frames]

Source Code for Module ZenEvents.zenpop3

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13  #! /usr/bin/env python  
 14  # Notes: database wants events in UTC time 
 15  # Events page shows local time, as determined on the server where zenoss runs 
 16   
 17  __doc__='''zenpop3 
 18   
 19  Turn email messages into events. 
 20   
 21  $Id$ 
 22  ''' 
 23   
 24  import Globals 
 25   
 26  from Products.ZenEvents.EventServer import EventServer 
 27  from Products.ZenEvents.MailProcessor import POPProcessor 
 28   
 29  from twisted.mail.pop3client import POP3Client 
 30  from twisted.internet import reactor, protocol, defer, error 
 31   
 32  import logging 
 33  log = logging.getLogger("zen.pop3") 
 34   
 35   
36 -class POPProtocol(POP3Client):
37 ''' protocol that is responsible for conversing with a pop server 38 after a connection has been established. downloads messages (and 39 deletes them by default), and passes the messages back up to the 40 factory to process (and turn into events)''' 41 42 allowInsecureLogin = True 43 timeout = 15 44
45 - def serverGreeting(self, unused):
46 log.info('server greeting received.') 47 log.info('logging in...') 48 49 login = self.login(self.factory.user, self.factory.passwd) 50 login.addCallback(self._loggedIn) 51 login.addErrback(self.factory.deferred.errback)
52 53
54 - def _loggedIn(self, unused):
55 log.info('logged in') 56 return self.retrieveAndParse()
57 58
59 - def retrieveAndParse(self):
60 d = self.listSize() 61 d.addCallback(self._gotMessageSizes) 62 63 return d
64 65
66 - def _gotMessageSizes(self, sizes):
67 log.info('messages to retrieve: %d' % len(sizes)) 68 69 self.sizes = sizes 70 71 retreivers = [] 72 for i in range(len(sizes)): 73 log.info('retrieving message #%d...' % i) 74 d = self.retrieve(i) 75 d.addCallback(self._gotMessageLines) 76 retreivers.append(d) 77 78 deferreds = defer.DeferredList(retreivers) 79 deferreds.addCallback(self._delete) 80 return deferreds.addCallback(self.scanComplete)
81 82
83 - def _gotMessageLines(self, messageLines):
84 log.info('passing message up to factory') 85 self.factory.handleMessage("\r\n".join(messageLines))
86 87
88 - def _delete(self, unused):
89 deleters = [] 90 if not self.factory.nodelete: 91 for index in range(len(self.sizes)): 92 log.info('deleting message #%d...' % index) 93 d = self.delete(index) 94 deleters.append(d) 95 96 deferreds = defer.DeferredList(deleters) 97 return deferreds
98 99
100 - def scanComplete(self, unused):
101 log.info("scan complete") 102 self.quit()
103 104
105 -class POPFactory(protocol.ClientFactory):
106 """ factory that stores the configuration the protocol uses to do it's 107 job.""" 108 109 protocol = POPProtocol 110
111 - def __init__(self, user, passwd, processor, nodelete):
112 self.user = user 113 self.passwd = passwd 114 self.processor = processor 115 self.deferred = defer.Deferred() 116 self.nodelete = nodelete
117 118
119 - def handleMessage(self, messageData):
120 self.processor.process(messageData)
121 122
123 - def clientConnectionFailed(self, unused, reason):
124 self.deferred.errback(reason)
125 126
127 -class ZenPOP3(EventServer):
128 name = 'zenpop3' 129
130 - def __init__(self):
131 EventServer.__init__(self) 132 133 self.changeUser() 134 self.processor = POPProcessor(self,self.options.eventseverity) 135 136 log.info("credentials user: %s; pass: %s" % (self.options.popuser, 137 len(self.options.poppass) * '*')) 138 139 self.makeFactory()
140 141
142 - def makeFactory(self):
143 self.factory = POPFactory(self.options.popuser, self.options.poppass, 144 self.processor, self.options.nodelete) 145 self.factory.deferred.addErrback(self.handleError)
146 147
148 - def connected(self):
149 self.checkForMessages()
150 151
152 - def checkForMessages(self):
153 reactor.callLater(self.options.cycletime, self.checkForMessages) 154 if self.options.usessl: 155 log.info("connecting to server using SSL") 156 from twisted.internet.ssl import ClientContextFactory 157 reactor.connectSSL(self.options.pophost, self.options.popport, 158 self.factory, ClientContextFactory()) 159 else: 160 log.info("connecting to server using plaintext") 161 reactor.connectTCP(self.options.pophost, self.options.popport, 162 self.factory) 163 164 self.heartbeat()
165 166
167 - def handleError(self, err):
168 if err.type == error.TimeoutError: 169 log.error("Timed out connecting to %s:%d", 170 self.options.pophost, self.options.popport) 171 elif err.type == error.ConnectionRefusedError: 172 log.error("Connection refused by %s:%d", 173 self.options.pophost, self.options.popport) 174 elif err.type == error.ConnectError: 175 log.error("Connection failed to %s:%d", 176 self.options.pophost, self.options.popport) 177 else: 178 log.error(err.getErrorMessage()) 179 self.stop() 180 181 self.makeFactory()
182 183
184 - def buildOptions(self):
185 EventServer.buildOptions(self) 186 self.parser.add_option('--usessl', 187 dest='usessl', 188 default=False, 189 action="store_true", 190 help="Use SSL when connecting to POP server") 191 self.parser.add_option('--nodelete', 192 dest='nodelete', 193 default=False, 194 action="store_true", 195 help="Leave messages on POP server") 196 self.parser.add_option('--pophost', 197 dest='pophost', 198 default="pop.zenoss.com", 199 help="POP server to auth against") 200 self.parser.add_option('--popport', 201 dest='popport', 202 default="110", 203 type="int", 204 help="POP port to auth against") 205 self.parser.add_option('--popuser', 206 dest='popuser', 207 default="zenoss", 208 help="POP user to auth using") 209 self.parser.add_option('--poppass', 210 dest='poppass', 211 default="zenoss", 212 help="POP password to auth using") 213 self.parser.add_option('--cycletime', 214 dest='cycletime', 215 type="int", 216 default=60, 217 help="Frequency (in secs) to poll POP server") 218 self.parser.add_option('--eventseverity', 219 dest='eventseverity', 220 default="2", 221 type="int", 222 help="Severity for events created")
223 224 225 226 if __name__ == '__main__': 227 ZenPOP3().run() 228