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

# Source Code for Module Products.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