📄 proxyui.py
字号:
options["Headers", "header_spam_string"]: [], } invalid_keys = [] for key in keys: if isinstance(key, types.TupleType): key, sourceCorpus = key else: sourceCorpus = state.unknownCorpus # Parse the message, get the judgement header and build a message # info object for each message. message = sourceCorpus[key] try: message.load() except IOError: # Someone has taken this file away from us. It was # probably a virus protection program, so that's ok. # Don't list it in the review, though. invalid_keys.append(key) continue judgement = message[options["Headers", "classification_header_name"]] if judgement is None: judgement = options["Headers", "header_unsure_string"] else: judgement = judgement.split(';')[0].strip() messageInfo = self._makeMessageInfo(message) keyedMessageInfo[judgement].append((key, messageInfo)) for key in invalid_keys: keys.remove(key) # Present the list of messages in their groups in reverse order of # appearance, by default, or according to the specified sort order. if keys: page = self.html.reviewtable.clone() if prior: page.prior.value = prior del page.priorButton.disabled if next: page.next.value = next del page.nextButton.disabled templateRow = page.reviewRow.clone() # The decision about whether to reverse the sort # order has to go here, because _sortMessages gets called # thrice, and so the ham list would end up sorted backwards. sort_order = params.get('sort') if self.previous_sort == sort_order: reverse = True self.previous_sort = None else: reverse = False self.previous_sort = sort_order page.table = "" # To make way for the real rows. for header, label in ((options["Headers", "header_unsure_string"], 'Unsure'), (options["Headers", "header_ham_string"], 'Ham'), (options["Headers", "header_spam_string"], 'Spam')): messages = keyedMessageInfo[header] if messages: sh = self.html.reviewSubHeader.clone() # Setup the header row sh.optionalHeaders = '' h = self.html.headerHeader.clone() for header in options["html_ui", "display_headers"]: h.headerLink.href = 'review?sort=%sHeader' % \ (header.lower(),) h.headerName = header.title() sh.optionalHeaders += h if not options["html_ui", "display_score"]: del sh.score_header if not options["html_ui", "display_received_time"]: del sh.received_header subHeader = str(sh) subHeader = subHeader.replace('TYPE', label) page.table += self.html.blankRow page.table += subHeader self._appendMessages(page.table, messages, label, sort_order, reverse) page.table += self.html.trainRow if title == "": title = _("Untrained messages received on %s") % date box = self._buildBox(title, None, page) # No icon, to save space. else: page = _("<p>There are no untrained messages to display. " \ "Return <a href='home'>Home</a>, or " \ "<a href='review'>check again</a>.</p>") title = _("No untrained messages") box = self._buildBox(title, 'status.gif', page) self.write(box) self._writePostamble(help_topic="review") def _contains(self, a, b, ignore_case=False): """Return true if substring b is part of string a.""" assert isinstance(a, types.StringTypes) assert isinstance(b, types.StringTypes) if ignore_case: a = a.lower() b = b.lower() return a.find(b) >= 0 def onView(self, key, corpus): """View a message - linked from the Review page.""" self._writePreamble(_("View message"), parent=('review', _('Review'))) sourceCorpus = None message = None if state.unknownCorpus.get(key) is not None: sourceCorpus = state.unknownCorpus elif state.hamCorpus.get(key) is not None: sourceCorpus = state.hamCorpus elif state.spamCorpus.get(key) is not None: sourceCorpus = state.spamCorpus if sourceCorpus is not None: message = sourceCorpus.get(key) if message is not None: self.write("<pre>%s</pre>" % cgi.escape(message.as_string())) else: self.write(_("<p>Can't find message %r. Maybe it expired.</p>") % key) self._writePostamble() def onShowclues(self, key, subject, tokens='0'): """Show clues for a message - linked from the Review page.""" tokens = bool(int(tokens)) # needs the int, as bool('0') is True self._writePreamble(_("Message clues"), parent=('review', _('Review'))) sourceCorpus = None message = None if state.unknownCorpus.get(key) is not None: sourceCorpus = state.unknownCorpus elif state.hamCorpus.get(key) is not None: sourceCorpus = state.hamCorpus elif state.spamCorpus.get(key) is not None: sourceCorpus = state.spamCorpus if sourceCorpus is not None: message = sourceCorpus.get(key).as_string() if message is not None: message = message.replace('\r\n', '\n').replace('\r', '\n') # For Macs results = self._buildCluesTable(message, subject, tokens) del results.classifyAnother self.write(results) else: self.write(_("<p>Can't find message %r. Maybe it expired.</p>") % key) self._writePostamble() def _makeMessageInfo(self, message): """Given an email.Message, return an object with subjectHeader, bodySummary and other header (as needed) attributes. These objects are passed into appendMessages by onReview - passing email.Message objects directly uses too much memory. """ # Remove notations before displaying - see: # [ 848365 ] Remove subject annotations from message review page message.delNotations() subjectHeader = message["Subject"] or "(none)" headers = {"subject" : subjectHeader} for header in options["html_ui", "display_headers"]: headers[header.lower()] = (message[header] or "(none)") score = message[options["Headers", "score_header_name"]] if score: # the score might have the log info at the end op = score.find('(') if op >= 0: score = score[:op] try: score = float(score) * 100 except ValueError: # Hmm. The score header should only contain a floating # point number. What's going on here, then? score = "Err" # Let the user know something is wrong. else: # If the lookup fails, this means that the "include_score" # option isn't activated. We have the choice here to either # calculate it now, which is pretty inefficient, since we have # already done so, or to admit that we don't know what it is. # We'll go with the latter. score = "?" try: part = typed_subpart_iterator(message, 'text', 'plain').next() text = part.get_payload() except StopIteration: try: part = typed_subpart_iterator(message, 'text', 'html').next() text = part.get_payload() text, unused = tokenizer.crack_html_style(text) text, unused = tokenizer.crack_html_comment(text) text = tokenizer.html_re.sub(' ', text) text = _('(this message only has an HTML body)\n') + text except StopIteration: text = _('(this message has no text body)') if type(text) == type([]): # gotta be a 'right' way to do this text = _("(this message is a digest of %s messages)") % (len(text)) elif text is None: text = _("(this message has no body)") else: text = text.replace(' ', ' ') # Else they'll be quoted text = re.sub(r'(\s)\s+', r'\1', text) # Eg. multiple blank lines text = text.strip() class _MessageInfo: pass messageInfo = _MessageInfo() for headerName, headerValue in headers.items(): headerValue = self._trimHeader(headerValue, 45, True) setattr(messageInfo, "%sHeader" % (headerName,), headerValue) messageInfo.score = score messageInfo.bodySummary = self._trimHeader(text, 200) return messageInfo def close_database(self): state.close() def reReadOptions(self): """Called by the config page when the user saves some new options, or restores the defaults.""" # Re-read the options. global state import Options Options.load_options() global options from Options import options # Recreate the state. state = self.state_recreator() self.classifier = state.bayes def verifyInput(self, parms, pmap): '''Check that the given input is valid.''' # Most of the work here is done by the parent class, but # we have a few extra checks errmsg = UserInterface.UserInterface.verifyInput(self, parms, pmap) if pmap != parm_ini_map: return errmsg # check for equal number of pop3servers and ports slist = list(parms['pop3proxy_remote_servers']) plist = list(parms['pop3proxy_listen_ports']) if len(slist) != len(plist): errmsg += _('<li>The number of POP3 proxy ports specified ' \ 'must match the number of servers specified</li>\n') # check for duplicate ports plist.sort() for p in range(len(plist)-1): try: if plist[p] == plist[p+1]: errmsg += _('<li>All POP3 port numbers must be unique</li>') break except IndexError: pass # check for equal number of smtpservers and ports slist = list(parms['smtpproxy_remote_servers']) plist = list(parms['smtpproxy_listen_ports']) if len(slist) != len(plist): errmsg += _('<li>The number of SMTP proxy ports specified ' \ 'must match the number of servers specified</li>\n') # check for duplicate ports plist.sort() for p in range(len(plist)-1): try: if plist[p] == plist[p+1]: errmsg += _('<li>All SMTP port numbers must be unique</li>') break except IndexError: pass return errmsg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -