📄 imapui.py
字号:
"""IMAPFilter Web InterfaceClasses: IMAPUserInterface - Interface class for the IMAP filterAbstract:This module implements a browser based Spambayes user interface for theIMAP filter. Users may use it to interface with the filter - it isexpected that this will primarily be for configuration, although usersmay also wish to look up words in the database, or classify a message.The following functions are currently included:[From the base class UserInterface] onClassify - classify a given message onWordquery - query a word from the database onTrain - train a message or mbox onSave - save the database and possibly shutdown[Here] onHome - a home page with various optionsTo do: o This could have a neat review page, like pop3proxy, built up by asking the IMAP server appropriate questions. I don't know whether this is needed, however. This would then allow viewing a message, showing the clues for it, and so on. Finding a message (via the spambayes id) could also be done. o Suggestions?"""# This module is part of the spambayes project, which is Copyright 2002-3# The Python Software Foundation and is covered by the Python Software# Foundation license.__author__ = "Tony Meyer <ta-meyer@ihug.co.nz>, Tim Stone"__credits__ = "All the Spambayes folk."try: True, Falseexcept NameError: # Maintain compatibility with Python 2.2 True, False = 1, 0import reimport cgiimport typesimport UserInterfacefrom spambayes.Options import options, optionsPathname, _# These are the options that will be offered on the configuration page.# If the option is None, then the entry is a header and the following# options will appear in a new box on the configuration page.# These are also used to generate http request parameters and template# fields/variables.parm_map = ( (_('IMAP Options'), None), ('imap', 'server'), ('imap', 'username'), # to display, or not to display; that is the question! # if we show this here, it's in plain text for everyone to # see (and worse - if we don't restrict connections to # localhost, it's available for the world to see) # on the other hand, we have to be able to enter it somehow... ('imap', 'password'), ('imap', 'use_ssl'), (_('Header Options'), None), ('Headers', 'notate_to'), ('Headers', 'notate_subject'), (_('Storage Options'), None), ('Storage', 'persistent_storage_file'), ('Storage', 'messageinfo_storage_file'), (_('Statistics Options'), None), ('Categorization', 'ham_cutoff'), ('Categorization', 'spam_cutoff'),)# Like the above, but hese are the options that will be offered on the# advanced configuration page.adv_map = ( (_('Statistics Options'), None), ('Classifier', 'max_discriminators'), ('Classifier', 'minimum_prob_strength'), ('Classifier', 'unknown_word_prob'), ('Classifier', 'unknown_word_strength'), ('Classifier', 'use_bigrams'), (_('Header Options'), None), ('Headers', 'include_score'), ('Headers', 'header_score_digits'), ('Headers', 'header_score_logarithm'), ('Headers', 'include_thermostat'), ('Headers', 'include_evidence'), ('Headers', 'clue_mailheader_cutoff'), (_('Storage Options'), None), ('Storage', 'persistent_use_database'), (_('Tokenising Options'), None), ('Tokenizer', 'mine_received_headers'), ('Tokenizer', 'replace_nonascii_chars'), ('Tokenizer', 'summarize_email_prefixes'), ('Tokenizer', 'summarize_email_suffixes'), ('Tokenizer', 'x-pick_apart_urls'), (_('Interface Options'), None), ('html_ui', 'display_adv_find'), ('html_ui', 'allow_remote_connections'), ('html_ui', 'http_authentication'), ('html_ui', 'http_user_name'), ('html_ui', 'http_password'), ('globals', 'language'),)# This is here because we need to refer to it here, and in sb_imapfilter.# I suppose it really belongs somewhere else, where both can refer to it,# but there isn't any such place, and creating it just for this is rather# pointless.class LoginFailure(Exception): """Login to the IMAP server failed.""" def __init__(self, details): self.details = details def __str__(self): return "Login failure: %s" % (self.details,)class IMAPUserInterface(UserInterface.UserInterface): """Serves the HTML user interface for the proxies.""" def __init__(self, cls, imaps, pwds, imap_session_class, lang_manager=None, stats=None, close_db=None, change_db=None): global parm_map # Only offer SSL if it is available try: from imaplib import IMAP4_SSL except ImportError: parm_list = list(parm_map) parm_list.remove(("imap", "use_ssl")) parm_map = tuple(parm_list) else: del IMAP4_SSL UserInterface.UserInterface.__init__(self, cls, parm_map, adv_map, lang_manager, stats) self.classifier = cls self.imaps = imaps self.imap_pwds = pwds self.app_for_version = "SpamBayes IMAP Filter" self.imap_session_class = imap_session_class self.close_database = close_db self.change_db = change_db def onHome(self): """Serve up the homepage.""" stateDict = self.classifier.__dict__.copy() stateDict["warning"] = "" stateDict.update(self.classifier.__dict__) statusTable = self.html.statusTable.clone() del statusTable.proxyDetails # This could be a bit more modular statusTable.configurationLink += "<br /> " \ " " + _("You can also <a href='filterfolders'>configure" \ " folders to filter</a><br />and " \ "<a href='trainingfolders'>Configure folders to" \ " train</a>") findBox = self._buildBox(_('Word query'), 'query.gif', self.html.wordQuery) if not options["html_ui", "display_adv_find"]: del findBox.advanced content = (self._buildBox(_('Status and Configuration'), 'status.gif', statusTable % stateDict)+ self._buildTrainBox() + self._buildClassifyBox() + findBox ) self._writePreamble(_("Home")) self.write(content) self._writePostamble() def reReadOptions(self): """Called by the config page when the user saves some new options, or restores the defaults.""" # Re-read the options. import Options Options.load_options() global options from Options import options self.change_db() def onSave(self, how): for imap in self.imaps: if imap: imap.logout() UserInterface.UserInterface.onSave(self, how) def onFilterfolders(self): self._writePreamble(_("Select Filter Folders")) self._login_to_imap() available_folders = [] for imap in self.imaps: if imap and imap.logged_in: available_folders.extend(imap.folder_list()) if not available_folders: content = self._buildBox(_("Error"), None, _("No folders available")) self.write(content) self._writePostamble() return content = self.html.configForm.clone() content.configFormContent = "" content.introduction = _("This page allows you to change " \ "which folders are filtered, and " \ "where filtered mail ends up.") content.config_submit.value = _("Save Filter Folders") content.optionsPathname = optionsPathname for opt in ("unsure_folder", "spam_folder", "filter_folders"): folderBox = self._buildFolderBox("imap", opt, available_folders) content.configFormContent += folderBox self.write(content) self._writePostamble() def _login_to_imap(self): new_imaps = [] for i in xrange(len(self.imaps)): imap = self.imaps[i] imap_logged_in = self._login_to_imap_server(imap, i) if imap_logged_in: new_imaps.append(imap_logged_in) self.imaps = new_imaps def _login_to_imap_server(self, imap, i): if imap and imap.logged_in: return imap if imap is None or not imap.connected: try: server = options["imap", "server"][i] except KeyError: content = self._buildBox(_("Error"), None, _("Please check server/port details.")) self.write(content) return None if server.find(':') > -1: server, port = server.split(':', 1) port = int(port) else: if options["imap", "use_ssl"]: port = 993 else: port = 143 imap = self.imap_session_class(server, port) if not imap.connected: # Failed to connect. content = self._buildBox(_("Error"), None, _("Please check server/port details.")) self.write(content) return None usernames = options["imap", "username"] if not usernames: content = self._buildBox(_("Error"), None, _("Must specify username first.")) self.write(content) return None if not self.imap_pwds: self.imap_pwd = options["imap", "password"] if not self.imap_pwds: content = self._buildBox(_("Error"), None, _("Must specify password first.")) self.write(content) return None try: imap.login(usernames[i], self.imap_pwds[i]) except KeyError: content = self._buildBox(_("Error"), None, _("Please check username/password details.")) self.write(content) return None except LoginFailure, e: content = self._buildBox(_("Error"), None, str(e)) self.write(content) return None return imap def onTrainingfolders(self): self._writePreamble(_("Select Training Folders")) self._login_to_imap() available_folders = [] for imap in self.imaps: if imap and imap.logged_in: available_folders.extend(imap.folder_list()) if not available_folders: content = self._buildBox(_("Error"), None, _("No folders available")) self.write(content) self._writePostamble() return content = self.html.configForm.clone() content.configFormContent = "" content.introduction = _("This page allows you to change " \ "which folders contain mail to " \ "train Spambayes.") content.config_submit.value = _("Save Training Folders") content.optionsPathname = optionsPathname for opt in ("ham_train_folders", "spam_train_folders"): folderBox = self._buildFolderBox("imap", opt, available_folders) content.configFormContent += folderBox self.write(content) self._writePostamble() def onChangeopts(self, **parms): backup = self.parm_ini_map if parms["how"] == _("Save Training Folders") or \ parms["how"] == _("Save Filter Folders"): del parms["how"] self.parm_ini_map = () for opt, value in parms.items(): del parms[opt] # Under strange circumstances this could break, # so if we can think of a better way to do this, # that would be nice. if opt[-len(value):] == value: opt = opt[:-len(value)] self.parm_ini_map += ("imap", opt), key = "imap_" + opt if parms.has_key(key): parms[key] += ',' + value else: parms[key] = value UserInterface.UserInterface.onChangeopts(self, **parms) self.parm_ini_map = backup def _buildFolderBox(self, section, option, available_folders): folderTable = self.html.configTable.clone() del folderTable.configTextRow1 del folderTable.configTextRow2 del folderTable.configCbRow1 del folderTable.configRow2 del folderTable.blankRow del folderTable.folderRow firstRow = True for folder in available_folders: folder = cgi.escape(folder) folderRow = self.html.configTable.folderRow.clone() if firstRow: folderRow.helpCell = options.doc(section, option) firstRow = False else: del folderRow.helpCell folderRow.folderBox.name = option folderRow.folderBox.value = folder folderRow.folderName = folder if options.multiple_values_allowed(section, option): if folder in options[section, option]: folderRow.folderBox.checked = "checked" folderRow.folderBox.name += folder else: if folder == options[section, option]: folderRow.folderBox.checked = "checked" folderRow.folderBox.type = "radio" folderTable += folderRow return self._buildBox(options.display_name(section, option), None, folderTable)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -