📄 sb_server.py
字号:
if options["globals", "verbose"]: print "Asked to add languages: " + \ ", ".join(options["globals", "language"]) print "Set language to " + \ str(self.lang_manager.current_langs_codes) # Open the log file. if options["globals", "verbose"]: self.logFile = open('_pop3proxy.log', 'wb', 0) if not hasattr(self, "servers"): # Could have already been set via the command line. self.servers = [] if options["pop3proxy", "remote_servers"]: for server in options["pop3proxy", "remote_servers"]: server = server.strip() if server.find(':') > -1: server, port = server.split(':', 1) else: port = '110' self.servers.append((server, int(port))) if not hasattr(self, "proxyPorts"): # Could have already been set via the command line. self.proxyPorts = [] if options["pop3proxy", "listen_ports"]: splitPorts = options["pop3proxy", "listen_ports"] self.proxyPorts = map(_addressAndPort, splitPorts) if len(self.servers) != len(self.proxyPorts): print "pop3proxy_servers & pop3proxy_ports are different lengths!" sys.exit() # Remember reported errors. self.reported_errors = {} # Set up the statistics. self.totalSessions = 0 self.activeSessions = 0 self.numSpams = 0 self.numHams = 0 self.numUnsure = 0 # Unique names for cached messages - see `getNewMessageName()` below. self.lastBaseMessageName = '' self.uniquifier = 2 def close(self): assert self.prepared, "closed without being prepared!" self.servers = None if self.bayes is not None: # Only store a non-empty db. if self.bayes.nham != 0 and self.bayes.nspam != 0: state.bayes.store() self.bayes.close() self.bayes = None if self.mdb is not None: self.mdb.store() self.mdb.close() self.mdb = None spambayes.message.Message.message_info_db = None self.spamCorpus = self.hamCorpus = self.unknownCorpus = None self.spamTrainer = self.hamTrainer = None self.prepared = False close_platform_mutex(self.platform_mutex) self.platform_mutex = None def prepare(self, can_stop=True): """Do whatever needs to be done to prepare for running. If can_stop is False, then we may not let the user shut down the proxy - for example, running as a Windows service this should be the case.""" # If we can, prevent multiple servers from running at the same time. assert self.platform_mutex is None, "Should not already have the mutex" self.platform_mutex = open_platform_mutex() self.can_stop = can_stop # Do whatever we've been asked to do... self.createWorkers() self.prepared = True def buildServerStrings(self): """After the server details have been set up, this creates string versions of the details, for display in the Status panel.""" serverStrings = ["%s:%s" % (s, p) for s, p in self.servers] self.serversString = ', '.join(serverStrings) self.proxyPortsString = ', '.join(map(_addressPortStr, self.proxyPorts)) def buildStatusStrings(self): """Build the status message(s) to display on the home page of the web interface.""" nspam = self.bayes.nspam nham = self.bayes.nham if nspam > 10 and nham > 10: db_ratio = nham/float(nspam) big = small = None if db_ratio > 5.0: self.warning = _("Warning: you have much more ham than " \ "spam - SpamBayes works best with " \ "approximately even numbers of ham and " \ "spam.") elif db_ratio < (1/5.0): self.warning = _("Warning: you have much more spam than " \ "ham - SpamBayes works best with " \ "approximately even numbers of ham and " \ "spam.") else: self.warning = "" elif nspam > 0 or nham > 0: self.warning = _("Database only has %d good and %d spam - " \ "you should consider performing additional " \ "training.") % (nham, nspam) else: self.warning = _("Database has no training information. " \ "SpamBayes will classify all messages as " \ "'unsure', ready for you to train.") # Add an additional warning message if the user's thresholds are # truly odd. spam_cut = options["Categorization", "spam_cutoff"] ham_cut = options["Categorization", "ham_cutoff"] if spam_cut < 0.5: self.warning += _("<br/>Warning: we do not recommend " \ "setting the spam threshold less than 0.5.") if ham_cut > 0.5: self.warning += _("<br/>Warning: we do not recommend " \ "setting the ham threshold greater than 0.5.") if ham_cut > spam_cut: self.warning += _("<br/>Warning: your ham threshold is " \ "<b>higher</b> than your spam threshold. " \ "Results are unpredictable.") def createWorkers(self): """Using the options that were initialised in __init__ and then possibly overridden by the driver code, create the Bayes object, the Corpuses, the Trainers and so on.""" print "Loading database...", if self.isTest: self.useDB = "pickle" self.DBName = '_pop3proxy_test.pickle' # This is never saved. if not hasattr(self, "DBName"): self.DBName, self.useDB = storage.database_type([]) self.bayes = storage.open_storage(self.DBName, self.useDB) self.mdb = spambayes.message.Message().message_info_db # Load stats manager. self.stats = Stats.Stats(options, self.mdb) self.buildStatusStrings() # Don't set up the caches and training objects when running the self-test, # so as not to clutter the filesystem. if not self.isTest: # Create/open the Corpuses. Use small cache sizes to avoid hogging # lots of memory. sc = get_pathname_option("Storage", "spam_cache") hc = get_pathname_option("Storage", "ham_cache") uc = get_pathname_option("Storage", "unknown_cache") map(storage.ensureDir, [sc, hc, uc]) if self.gzipCache: factory = GzipFileMessageFactory() else: factory = FileMessageFactory() age = options["Storage", "cache_expiry_days"]*24*60*60 self.spamCorpus = ExpiryFileCorpus(age, factory, sc, '[0123456789\-]*', cacheSize=20) self.hamCorpus = ExpiryFileCorpus(age, factory, hc, '[0123456789\-]*', cacheSize=20) self.unknownCorpus = ExpiryFileCorpus(age, factory, uc, '[0123456789\-]*', cacheSize=20) # Given that (hopefully) users will get to the stage # where they do not need to do any more regular training to # be satisfied with spambayes' performance, we expire old # messages from not only the trained corpora, but the unknown # as well. self.spamCorpus.removeExpiredMessages() self.hamCorpus.removeExpiredMessages() self.unknownCorpus.removeExpiredMessages() # Create the Trainers. self.spamTrainer = storage.SpamTrainer(self.bayes) self.hamTrainer = storage.HamTrainer(self.bayes) self.spamCorpus.addObserver(self.spamTrainer) self.hamCorpus.addObserver(self.hamTrainer) def getNewMessageName(self): # The message name is the time it arrived, with a uniquifier # appended if two arrive within one clock tick of each other. messageName = "%10.10d" % long(time.time()) if messageName == self.lastBaseMessageName: messageName = "%s-%d" % (messageName, self.uniquifier) self.uniquifier += 1 else: self.lastBaseMessageName = messageName self.uniquifier = 2 return messageName def RecordClassification(self, cls, score): """Record the classification in the session statistics. cls should match one of the options["Headers", "header_*_string"] values. score is the score the message received. """ if cls == options["Headers", "header_ham_string"]: self.numHams += 1 elif cls == options["Headers", "header_spam_string"]: self.numSpams += 1 else: self.numUnsure += 1 self.stats.RecordClassification(score)# Option-parsing helper functionsdef _addressAndPort(s): """Decode a string representing a port to bind to, with optional address.""" s = s.strip() if ':' in s: addr, port = s.split(':') return addr, int(port) else: return '', int(s)def _addressPortStr((addr, port)): """Encode a string representing a port to bind to, with optional address.""" if not addr: return str(port) else: return '%s:%d' % (addr, port)state = State()proxyListeners = []def _createProxies(servers, proxyPorts): """Create BayesProxyListeners for all the given servers.""" for (server, serverPort), proxyPort in zip(servers, proxyPorts): ssl = options["pop3proxy", "use_ssl"] if ssl == "automatic": ssl = serverPort == 995 listener = BayesProxyListener(server, serverPort, proxyPort, ssl) proxyListeners.append(listener)def _recreateState(): global state # Close the existing listeners and create new ones. This won't # affect any running proxies - once a listener has created a proxy, # that proxy is then independent of it. # (but won't closing the database screw them?) for proxy in proxyListeners: proxy.close() del proxyListeners[:] if state.prepared: # Close the state (which saves if necessary) state.close() # And get a new one going. state = State() prepare() _createProxies(state.servers, state.proxyPorts) return statedef main(servers, proxyPorts, uiPort, launchUI): """Runs the proxy forever or until a 'KILL' command is received or someone hits Ctrl+Break.""" _createProxies(servers, proxyPorts) httpServer = UserInterfaceServer(uiPort) proxyUI = ProxyUserInterface(state, _recreateState) httpServer.register(proxyUI) Dibbler.run(launchBrowser=launchUI)def prepare(can_stop=True): state.init() state.prepare(can_stop) # Launch any SMTP proxies. Note that if the user hasn't specified any # SMTP proxy information in their configuration, then nothing will # happen. from spambayes import smtpproxy servers, proxyPorts = smtpproxy.LoadServerInfo() proxyListeners.extend(smtpproxy.CreateProxies(servers, proxyPorts, smtpproxy.SMTPTrainer(state.bayes, state))) # setup info for the web interface state.buildServerStrings()def start(): # kick everything off assert state.prepared, "starting before preparing state" try: main(state.servers, state.proxyPorts, state.uiPort, state.launchUI) finally: state.close()def stop(): # Shutdown as though through the web UI. This will save the DB, allow # any open proxy connections to complete, etc. from urllib import urlopen, urlencode urlopen('http://localhost:%d/save' % state.uiPort, urlencode({'how': _('Save & shutdown')})).read()# ===================================================================# __main__ driver.# ===================================================================def run(): global state # Read the arguments. try: opts, args = getopt.getopt(sys.argv[1:], 'hbd:p:l:u:o:') except getopt.error, msg: print >>sys.stderr, str(msg) + '\n\n' + __doc__ sys.exit() runSelfTest = False for opt, arg in opts: if opt == '-h': print >>sys.stderr, __doc__ sys.exit() elif opt == '-b': state.launchUI = True # '-p' and '-d' are handled by the storage.database_type call # below, in case you are wondering why they are missing. elif opt == '-l': state.proxyPorts = [_addressAndPort(a) for a in arg.split(',')] elif opt == '-u': state.uiPort = int(arg) elif opt == '-o': options.set_from_cmdline(arg, sys.stderr) state.DBName, state.useDB = storage.database_type(opts) # Let the user know what they are using... v = get_current_version() print "%s\n" % (v.get_long_version("SpamBayes POP3 Proxy"),) if 0 <= len(args) <= 2: # Normal usage, with optional server name and port number. if len(args) == 1: state.servers = [(args[0], 110)] elif len(args) == 2: state.servers = [(args[0], int(args[1]))] # Default to listening on port 110 for command-line-specified servers. if len(args) > 0 and state.proxyPorts == []: state.proxyPorts = [('', 110)] try: prepare() except AlreadyRunningException: print >>sys.stderr, \ "ERROR: The proxy is already running on this machine." print >>sys.stderr, "Please stop the existing proxy and try again" return start() else: print >>sys.stderr, __doc__if __name__ == '__main__': run()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -