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  from EventServer import EventServer 
 25   
 26  from twisted.mail.pop3client import POP3Client 
 27  from twisted.internet import reactor, protocol, defer, task 
 28  from twisted.internet.ssl import ClientContextFactory 
 29  from zope.interface import implements 
 30  from Products.ZenRRD.RRDDaemon import RRDDaemon 
 31  from Products.ZenUtils.Driver import drive, driveLater 
 32   
 33   
 34  from MailProcessor import POPProcessor 
 35   
 36  import logging 
 37  log = logging.getLogger("zen.pop3") 
 38   
 39   
40 -class POPProtocol(POP3Client):
41 ''' protocol that is responsible for conversing with a pop server 42 after a connection has been established. downloads messages (and 43 deletes them by default), and passes the messages back up to the 44 factory to process (and turn into events)''' 45 46 allowInsecureLogin = True 47 timeout = 15 48
49 - def serverGreeting(self, greeting):
50 log.info('server greeting received.') 51 log.info('logging in...') 52 53 login = self.login(self.factory.user, self.factory.passwd) 54 login.addCallback(self._loggedIn) 55 login.addErrback(self.factory.deferred.errback)
56 57
58 - def _loggedIn(self, result):
59 log.info('logged in') 60 return self.retrieveAndParse()
61 62
63 - def retrieveAndParse(self):
64 d = self.listSize() 65 d.addCallback(self._gotMessageSizes) 66 67 return d
68 69
70 - def _gotMessageSizes(self, sizes):
71 log.info('messages to retrieve: %d' % len(sizes)) 72 73 self.sizes = sizes 74 75 retreivers = [] 76 for i in range(len(sizes)): 77 log.info('retrieving message #%d...' % i) 78 d = self.retrieve(i) 79 d.addCallback(self._gotMessageLines) 80 retreivers.append(d) 81 82 deferreds = defer.DeferredList(retreivers) 83 deferreds.addCallback(self._delete) 84 85 if self.factory.cycle: 86 return deferreds.addCallback(self._finished) 87 else: 88 return deferreds.addCallback(self.factory.scanComplete)
89 90
91 - def _gotMessageLines(self, messageLines):
92 log.info('passing message up to factory') 93 self.factory.handleMessage("\r\n".join(messageLines))
94 95
96 - def _delete(self, results):
97 if not self.factory.nodelete: 98 deleters = [] 99 for index in range(len(self.sizes)): 100 log.info('deleting message #%d...' % index) 101 d = self.delete(index) 102 deleters.append(d) 103 104 deferreds = defer.DeferredList(deleters) 105 return deferreds
106 107
108 - def _finished(self, downloadResults):
109 log.info('sleeping for %d seconds.' % self.factory.cycletime) 110 reactor.callLater(self.factory.cycletime, self.retrieveAndParse)
111 112 113
114 -class POPFactory(protocol.ClientFactory):
115 ''' factory that stores the configuration the protocol uses to do it's 116 job.''' 117 118 protocol = POPProtocol 119
120 - def __init__(self, user, passwd, 121 processor, cycletime, cycle, nodelete, finish):
122 self.user = user 123 self.passwd = passwd 124 self.processor = processor 125 self.cycletime = cycletime 126 self.cycle = cycle 127 self.deferred = defer.Deferred() 128 self.nodelete = nodelete 129 self.finish = finish
130 131
132 - def handleMessage(self, messageData):
133 self.processor.process(messageData)
134 135
136 - def clientConnectionFailed(self, connection, reason):
137 self.deferred.errback(reason)
138 139
140 - def scanComplete(self, results):
141 log.info("scan complete") 142 self.finish()
143 144
145 -class ZenPOP3(EventServer, RRDDaemon):
146 name = 'zenpop3' 147
148 - def __init__(self):
149 EventServer.__init__(self) 150 RRDDaemon.__init__(self, ZenPOP3.name) 151 152 self.changeUser() 153 self.processor = POPProcessor(self.dmd.ZenEventManager) 154 host = self.options.pophost 155 port = self.options.popport 156 popuser = self.options.popuser 157 poppasswd = self.options.poppass 158 usessl = self.options.usessl 159 cycletime = int(self.options.cycletime) 160 cycle = int(self.options.cycle) 161 nodelete = int(self.options.nodelete) 162 163 log.info("credentials user: %s; pass: %s" % (popuser, 164 len(poppasswd) * '*')) 165 self.factory = POPFactory(popuser, poppasswd, 166 self.processor, cycletime, cycle, nodelete, 167 self._finish) 168 log.info("connecting to pop server: %s:%s" % (host, port)) 169 self.factory.deferred.addErrback(self.handleError) 170 171 if usessl: 172 log.info("connecting to server using SSL") 173 reactor.connectSSL(host, port, self.factory, ClientContextFactory()) 174 else: 175 log.info("connceting to server using plaintext") 176 reactor.connectTCP(host, port, self.factory)
177 178
179 - def handleError(self, error):
180 log.error(error) 181 log.error(error.getErrorMessage()) 182 183 self.finish()
184 185
186 - def _finish(self):
187 self.finish()
188 189
190 - def buildOptions(self):
191 EventServer.buildOptions(self) 192 self.parser.add_option('--usessl', 193 dest='usessl', 194 default=False, 195 action="store_true", 196 help="Use SSL when connecting to POP server") 197 self.parser.add_option('--nodelete', 198 dest='nodelete', 199 default=False, 200 action="store_true", 201 help="Leave messages on POP server") 202 self.parser.add_option('--pophost', 203 dest='pophost', 204 default="pop.zenoss.com", 205 help="POP server to auth against") 206 self.parser.add_option('--popport', 207 dest='popport', 208 default="110", 209 type="int", 210 help="POP port to auth against") 211 self.parser.add_option('--popuser', 212 dest='popuser', 213 default="zenoss", 214 help="POP user to auth using") 215 self.parser.add_option('--poppass', 216 dest='poppass', 217 default="zenoss", 218 help="POP password to auth using") 219 self.parser.add_option('--cycletime', 220 dest='cycletime', 221 default=60, 222 help="Frequency (in secs) to poll POP server")
223 224 225 226 if __name__ == '__main__': 227 ZenPOP3().main() 228