⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manager.py

📁 用python实现的邮件过滤器
💻 PY
📖 第 1 页 / 共 3 页
字号:
    # to change that.    use_db = bayes_options["Storage", "persistent_use_database"]    available = {"pickle" : PickleStorageManager,                 "dbm"    : DBStorageManager,                 "zodb"   : ZODBStorageManager,                 }    if use_db not in available:        # User is trying to use something fancy which isn't available.        # Fall back on bsddb.        print use_db, "storage type not available.  Using bsddb."        use_db = "dbm"    return available[use_db]# Our main "bayes manager"class BayesManager:    def __init__(self, config_base="default", outlook=None, verbose=0):        self.owner_thread_ident = thread.get_ident() # check we aren't multi-threaded        self.never_configured = True        self.reported_error_map = {}        self.reported_startup_error = False        self.config = self.options = None        self.addin = None        self.verbose = verbose        self.outlook = outlook        self.dialog_parser = None        self.test_suite_running = False        self.received_ham = self.received_unsure = self.received_spam = 0        self.notify_timer_id = None        import_early_core_spambayes_stuff()        self.application_directory = os.path.dirname(this_filename)        # Load the environment for translation.        lang_manager = bayes_i18n.LanguageManager()        # Set the system user default language.        lang_manager.set_language(lang_manager.locale_default_lang())        # where windows would like our data stored (and where        # we do, unless overwritten via a config file)        self.windows_data_directory = self.LocateDataDirectory()        # Read the primary configuration files        self.PrepareConfig()        # See if the initial config files specify a        # "data directory".  If so, use it, otherwise        # use the default Windows data directory for our app.        value = self.config.general.data_directory        if value:            # until I know otherwise, config files are ASCII - but our            # file system is unicode to some degree.            # (do config files support encodings at all?)            # Assume the file system encoding for file names!            try:                value = value.decode(filesystem_encoding)            except AttributeError: # May already be Unicode                pass            assert isinstance(value, types.UnicodeType), "%r should be a unicode" % value            try:                if not os.path.isdir(value):                    os.makedirs(value)                assert os.path.isdir(value), "just made the *ucker"                value = os.path.abspath(value)            except os.error:                print "The configuration files have specified a data " \                      "directory of", repr(value), "but it is not valid. " \                      "Using default."                value = None        if value:            self.data_directory = value        else:            self.data_directory = self.windows_data_directory        # Get the message store before loading config, as we use the profile        # name.        self.message_store = msgstore.MAPIMsgStore(outlook)        self.LoadConfig()        # Load the options for the classifier.  We support        # default_bayes_customize.ini in the app directory and user data        # directory (version 0.8 and earlier, we copied the app one to the        # user dir - that was a mistake - but supporting a version in that        # directory wasn't).  We also look for a        # {outlook-profile-name}_bayes_customize.ini file in the data        # directory, to allow per-profile customisations.        bayes_option_filenames = []        # data dir last so options there win.        for look_dir in [self.application_directory, self.data_directory]:            look_file = os.path.join(look_dir, "default_bayes_customize.ini")            if os.path.isfile(look_file):                bayes_option_filenames.append(look_file)        look_file = os.path.join(self.data_directory,                                 self.GetProfileName() + \                                 "_bayes_customize.ini")        if os.path.isfile(look_file):            bayes_option_filenames.append(look_file)        import_core_spambayes_stuff(bayes_option_filenames)        # Set interface to use the user language in configuration file.        for language in bayes_options["globals", "language"][::-1]:            # We leave the default in there as the last option, to fall            # back on if necessary.            lang_manager.add_language(language)        self.LogDebug(1, "Asked to add languages: " + \                      ", ".join(bayes_options["globals", "language"]))        self.LogDebug(1, "Set language to " + \                      str(lang_manager.current_langs_codes))        bayes_base = os.path.join(self.data_directory, "default_bayes_database")        mdb_base = os.path.join(self.data_directory, "default_message_database")        # determine which db manager to use, and create it.        ManagerClass = GetStorageManagerClass()        db_manager = ManagerClass(bayes_base, mdb_base)        self.classifier_data = ClassifierData(db_manager, self)        try:            self.classifier_data.Load()        except:            self.ReportFatalStartupError("Failed to load bayes database")            self.classifier_data.InitNew()        self.bayes_options = bayes_options        self.bayes_message = bayes_message        bayes_options["Categorization", "spam_cutoff"] = \                                        self.config.filter.spam_threshold \                                        / 100.0        bayes_options["Categorization", "ham_cutoff"] = \                                        self.config.filter.unsure_threshold \                                        / 100.0        self.stats = bayes_stats.Stats(bayes_options,                                       self.classifier_data.message_db)    # Logging - this should be somewhere else.    def LogDebug(self, level, *args):        if self.verbose >= level:            for arg in args[:-1]:                print arg,            print args[-1]    def ReportError(self, message, title = None):        if self.test_suite_running:            print "ReportError:", repr(message)            print "(but test suite running - not reported)"            return        ReportError(message, title)    def ReportInformation(self, message, title=None):        if self.test_suite_running:            print "ReportInformation:", repr(message)            print "(but test suite running - not reported)"            return        ReportInformation(message, title)    def AskQuestion(self, message, title=None):        return AskQuestion(message, title)    # Report a super-serious startup error to the user.    # This should only be used when SpamBayes was previously working, but a    # critical error means we are probably not working now.    # We just report the first such error - subsequent ones are likely a result of    # the first - hence, this must only be used for startup errors.    def ReportFatalStartupError(self, message):        if not self.reported_startup_error:            self.reported_startup_error = True            full_message = _(\                "There was an error initializing the Spam plugin.\r\n\r\n" \                "Spam filtering has been disabled.  Please re-configure\r\n" \                "and re-enable this plugin\r\n\r\n" \                "Error details:\r\n") + message            # Disable the plugin            if self.config is not None:                self.config.filter.enabled = False            self.ReportError(full_message)        else:            # We have reported the error, but for the sake of the log, we            # still want it logged there.            print "ERROR:", repr(message)            traceback.print_exc()    def ReportErrorOnce(self, msg, title = None, key = None):        if key is None: key = msg        # Always print the message and traceback.        if self.test_suite_running:            print "ReportErrorOnce:", repr(msg)            print "(but test suite running - not reported)"            return        print "ERROR:", repr(msg)        if key in self.reported_error_map:            print "(this error has already been reported - not displaying it again)"        else:            traceback.print_exc()            self.reported_error_map[key] = True            ReportError(msg, title)    # Outlook used to give us thread grief - now we avoid Outlook    # from threads, but this remains a worthwhile abstraction.    def WorkerThreadStarting(self):        pythoncom.CoInitialize()    def WorkerThreadEnding(self):        pythoncom.CoUninitialize()    def LocateDataDirectory(self):        # Locate the best directory for our data files.        from win32com.shell import shell, shellcon        try:            appdata = shell.SHGetFolderPath(0,shellcon.CSIDL_APPDATA,0,0)            path = os.path.join(appdata, "SpamBayes")            if not os.path.isdir(path):                os.makedirs(path)            return path        except pythoncom.com_error:            # Function doesn't exist on early win95,            # and it may just fail anyway!            return self.application_directory        except EnvironmentError:            # Can't make the directory.            return self.application_directory    def FormatFolderNames(self, folder_ids, include_sub):        names = []        for eid in folder_ids:            try:                folder = self.message_store.GetFolder(eid)                name = folder.name            except self.message_store.MsgStoreException:                name = "<unknown folder>"            names.append(name)        ret = '; '.join(names)        if include_sub:            ret += " (incl. Sub-folders)"        return ret    def EnsureOutlookFieldsForFolder(self, folder_id, include_sub=False):        # Should be called at least once once per folder you are        # watching/filtering etc        # Ensure that our fields exist on the Outlook *folder*        # Setting properties via our msgstore (via Ext Mapi) sets the props        # on the message OK, but Outlook doesn't see it as a "UserProperty".        # Using MAPI to set them directly on the folder also has no effect.        # Later: We have since discovered that Outlook stores user property        # information in the 'associated contents' folder - see        # msgstore.MAPIMsgStoreFolder.DoesFolderHaveOutlookField() for more        # details.  We can reverse engineer this well enough to determine        # if a property exists, but not well enough to actually add a        # property.  Thus, we resort to the Outlook object model to actually        # add it.        # Note that this means we need an object in the folder to modify.        # We could go searching for an existing item then modify and save it        # (indeed, we did once), but this could be bad-form, as the message        # we randomly choose to modify will then have a meaningless 'Spam'        # field.  If we are going to go to the effort of creating a temp        # item when no item exists, we may as well do it all the time,        # especially now we know how to check if the folder has the field        # without opening an Outlook item.        # Regarding the property type:        # We originally wanted to use the "Integer" Outlook field,        # but it seems this property type alone is not exposed via the Object        # model.  So we resort to olPercent, and live with the % sign        # (which really is OK!)        assert self.outlook is not None, "I need outlook :("        field_name = self.config.general.field_score_name        for msgstore_folder in self.message_store.GetFolderGenerator(                                                    [folder_id], include_sub):            folder_name = msgstore_folder.GetFQName()            if msgstore_folder.DoesFolderHaveOutlookField(field_name):                self.LogDebug(1, "Folder '%s' already has field '%s'" \                                 % (folder_name, field_name))                continue            self.LogDebug(0, "Folder '%s' has no field named '%s' - creating" \                      % (folder_name, field_name))            # Creating the item via the Outlook model does some strange            # things (such as moving it to "Drafts" on save), so we create            # it using extended MAPI (via our msgstore)            message = msgstore_folder.CreateTemporaryMessage(msg_flags=1)            outlook_message = message.GetOutlookItem()            ups = outlook_message.UserProperties            try:                # Display format is documented as being the 1-based index in                # the combo box in the outlook UI for the given data type.                # 1 is the first - "Rounded", which seems fine.                format = 1                ups.Add(field_name,                       win32com.client.constants.olPercent,                       True, # Add to folder                       format)                outlook_message.Save()            except pythoncom.com_error, details:                if msgstore.IsReadOnlyCOMException(details):                    self.LogDebug(1, "The folder '%s' is read-only - user "                                     "property can't be added" % (folder_name,))                else:                    print "Warning: failed to create the Outlook " \                          "user-property in folder '%s'" \                          % (folder_name,)                    print "", details            msgstore_folder.DeleteMessages((message,))            # Check our DoesFolderHaveOutlookField logic holds up.            if not msgstore_folder.DoesFolderHaveOutlookField(field_name):                self.LogDebug(0,                        "WARNING: We just created the user field in folder "                        "%s, but it appears to not exist.  Something is "                        "probably wrong with DoesFolderHaveOutlookField()" % \                        folder_name)    def PrepareConfig(self):        # Load our Outlook specific configuration.  This is done before        # SpamBayes is imported, and thus we are able to change the INI        # file used for the engine.  It is also done before the primary        # options are loaded - this means we can change the directory        # from which these options are loaded.        import config        self.options = config.CreateConfig()        # Note that self.options really *is* self.config - but self.config        # allows a "." notation to access the values.  Changing one is reflected        # immediately in the other.        self.config = config.OptionsContainer(self.options)        filename = os.path.join(self.application_directory, "default_configuration.ini")        self._MergeConfigFile(filename)        filename = os.path.join(self.windows_data_directory, "default_configuration.ini")        self._MergeConfigFile(filename)    def _MergeConfigFile(self, filename):        try:            self.options.merge_file(filename)        except:            msg = _("The configuration file named below is invalid.\r\n" \                    "Please either correct or remove this file\r\n\r\n" \                    "Filename: ") + filename            self.ReportError(msg)    def GetProfileName(self):        profile_name = self.message_store.GetProfileName()        # The profile name may include characters invalid in file names.        if profile_name is not None:            profile_name = "".join([c for c in profile_name                                    if ord(c)>127 or c in filename_chars])        if profile_name is None:            # should only happen in source-code versions - older win32alls can't            # determine this.            profile_name = "unknown_profile"            print "*** NOTE: It appears you are running the source-code version of"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -