📄 addin.py
字号:
token = token.encode('mbcs', 'replace') else: token = repr(token) push("<code>" + token + "</code><br>\n") # Put the body together, then the rest of the message. body = ''.join(body) new_msg.Subject = "Spam Clues: " + item.Subject # As above, use HTMLBody else Outlook refuses to behave. new_msg.HTMLBody = """\<HTML><HEAD><STYLE> h2 {color: green}</STYLE></HEAD><BODY>""" + body + "</BODY></HTML>" # Attach the source message to it # Using the original message has the side-effect of marking the original # as unread. Tried to make a copy, but the copy then refused to delete # itself. # And the "UnRead" property of the message is not reflected in the object # model (we need to "refresh" the message). Oh well. new_msg.Attachments.Add(item, constants.olByValue, DisplayName="Original Message") new_msg.Display()# Event function fired from the "Empty Spam Folder" UI item.def EmptySpamFolder(mgr): config = mgr.config.filter ms = mgr.message_store spam_folder_id = getattr(config, "spam_folder_id") try: spam_folder = ms.GetFolder(spam_folder_id) except ms.MsgStoreException: mgr.LogDebug(0, "ERROR: Unable to open the spam folder for emptying - " \ "spam messages were not deleted") else: try: if spam_folder.GetItemCount() > 0: message = _("Are you sure you want to permanently delete " \ "all items in the \"%s\" folder?") \ % spam_folder.name if mgr.AskQuestion(message): mgr.LogDebug(2, "Emptying spam from folder '%s'" % \ spam_folder.GetFQName()) import manager spam_folder.EmptyFolder(manager._GetParent()) else: mgr.LogDebug(2, "Spam folder '%s' was already empty" % \ spam_folder.GetFQName()) message = _("The \"%s\" folder is already empty.") % \ spam_folder.name mgr.ReportInformation(message) except: mgr.LogDebug(0, "Error emptying spam folder '%s'!" % \ spam_folder.GetFQName()) traceback.print_exc()def CheckLatestVersion(manager): from spambayes.Version import get_current_version, get_version, \ get_download_page, fetch_latest_dict app_name = "Outlook" ver_current = get_current_version() cur_ver_string = ver_current.get_long_version(ADDIN_DISPLAY_NAME) try: SetWaitCursor(1) latest = fetch_latest_dict() SetWaitCursor(0) ver_latest = get_version(app_name, version_dict=latest) latest_ver_string = ver_latest.get_long_version(ADDIN_DISPLAY_NAME) except: print "Error checking the latest version" traceback.print_exc() manager.ReportError( _("There was an error checking for the latest version\r\n" "For specific details on the error, please see the SpamBayes log" "\r\n\r\nPlease check your internet connection, or try again later") ) return print "Current version is %s, latest is %s." % (str(ver_current), str(ver_latest)) if ver_latest > ver_current: url = get_download_page(app_name, version_dict=latest) msg = _("You are running %s\r\n\r\nThe latest available version is %s" \ "\r\n\r\nThe download page for the latest version is\r\n%s" \ "\r\n\r\nWould you like to visit this page now?") \ % (cur_ver_string, latest_ver_string, url) if manager.AskQuestion(msg): print "Opening browser page", url os.startfile(url) else: msg = _("The latest available version is %s\r\n\r\n" \ "No later version is available.") % latest_ver_string manager.ReportInformation(msg)# A hook for whatever tests we have setupdef Tester(manager): import tester # This is only used in source-code versions - so we may as well reload # the test suite to save shutting down Outlook each time we tweak it. reload(tester) try: print "Executing automated tests..." tester.test(manager) except: traceback.print_exc() print "Tests FAILED. Sorry about that. If I were you, I would do a full re-train ASAP" print "Please delete any test messages from your Spam, Unsure or Inbox/Watch folders first."# The "Spam" and "Not Spam" buttons# The event from Outlook's explorer that our folder has changed.class ButtonDeleteAsEventBase: def Init(self, manager, explorer): self.manager = manager self.explorer = explorer def Close(self): self.manager = self.explorer = Noneclass ButtonDeleteAsSpamEvent(ButtonDeleteAsEventBase): def OnClick(self, button, cancel): msgstore = self.manager.message_store msgstore_messages = self.explorer.GetSelectedMessages(True) if not msgstore_messages: return # If we are not yet enabled, tell the user. # (This is better than disabling the button as a) the user may not # understand why it is disabled, and b) as we would then need to check # the button state as the manager dialog closes. if not self.manager.config.filter.enabled: self.manager.ReportError( _("You must configure and enable SpamBayes before you " \ "can mark messages as spam")) return SetWaitCursor(1) # Delete this item as spam. spam_folder = None # It is unlikely that the spam folder is not specified, as the UI # will prevent enabling. But it could be invalid. spam_folder_id = self.manager.config.filter.spam_folder_id if spam_folder_id: try: spam_folder = msgstore.GetFolder(spam_folder_id) except msgstore.MsgStoreException: pass if spam_folder is None: self.manager.ReportError(_("You must configure the Spam folder"), _("Invalid Configuration")) return import train new_msg_state = self.manager.config.general.delete_as_spam_message_state for msgstore_message in msgstore_messages: # Record this recovery in our stats. self.manager.stats.RecordTraining(False, self.manager.score(msgstore_message)) # Record the original folder, in case this message is not where # it was after filtering, or has never been filtered. msgstore_message.RememberMessageCurrentFolder() msgstore_message.Save() # Must train before moving, else we lose the message! subject = msgstore_message.GetSubject() print "Moving and spam training message '%s' - " % (subject,), TrainAsSpam(msgstore_message, self.manager, save_db = False) # Do the new message state if necessary. try: if new_msg_state == "Read": msgstore_message.SetReadState(True) elif new_msg_state == "Unread": msgstore_message.SetReadState(False) else: if new_msg_state not in ["", "None", None]: print "*** Bad new_msg_state value: %r" % (new_msg_state,) except pythoncom.com_error: print "*** Failed to set the message state to '%s' for message '%s'" % (new_msg_state, subject) # Now move it. msgstore_message.MoveToReportingError(self.manager, spam_folder) # Note the move will possibly also trigger a re-train # but we are smart enough to know we have already done it. # And if the DB can save itself incrementally, do it now self.manager.classifier_data.SavePostIncrementalTrain() SetWaitCursor(0)class ButtonRecoverFromSpamEvent(ButtonDeleteAsEventBase): def OnClick(self, button, cancel): msgstore = self.manager.message_store msgstore_messages = self.explorer.GetSelectedMessages(True) if not msgstore_messages: return # If we are not yet enabled, tell the user. # (This is better than disabling the button as a) the user may not # understand why it is disabled, and b) as we would then need to check # the button state as the manager dialog closes. if not self.manager.config.filter.enabled: self.manager.ReportError( _("You must configure and enable SpamBayes before you " \ "can mark messages as not spam")) return SetWaitCursor(1) # Get the inbox as the default place to restore to # (incase we dont know (early code) or folder removed etc app = self.explorer.Application inbox_folder = msgstore.GetFolder( app.Session.GetDefaultFolder(constants.olFolderInbox)) new_msg_state = self.manager.config.general.recover_from_spam_message_state for msgstore_message in msgstore_messages: # Recover where they were moved from # During experimenting/playing/debugging, it is possible # that the source folder == dest folder - restore to # the inbox in this case. # (But more likely is that the original store may be read-only # so we were unable to record the initial folder, as we save it # *before* we do the move (and saving after is hard)) try: subject = msgstore_message.GetSubject() self.manager.classifier_data.message_db.load_msg(msgstore_message) restore_folder = msgstore_message.GetRememberedFolder() if restore_folder is None or \ msgstore_message.GetFolder() == restore_folder: print "Unable to determine source folder for message '%s' - restoring to Inbox" % (subject,) restore_folder = inbox_folder # Record this recovery in our stats. self.manager.stats.RecordTraining(True, self.manager.score(msgstore_message)) # Must train before moving, else we lose the message! print "Recovering to folder '%s' and ham training message '%s' - " % (restore_folder.name, subject), TrainAsHam(msgstore_message, self.manager, save_db = False) # Do the new message state if necessary. try: if new_msg_state == "Read": msgstore_message.SetReadState(True) elif new_msg_state == "Unread": msgstore_message.SetReadState(False) else: if new_msg_state not in ["", "None", None]: print "*** Bad new_msg_state value: %r" % (new_msg_state,) except msgstore.MsgStoreException, details: print "*** Failed to set the message state to '%s' for message '%s'" % (new_msg_state, subject) print details # Now move it. msgstore_message.MoveToReportingError(self.manager, restore_folder) except msgstore.NotFoundException: # Message moved under us - ignore. self.manager.LogDebug(1, "'Not Spam' had message moved from underneath us - ignored") # Note the move will possibly also trigger a re-train # but we are smart enough to know we have already done it. # And if the DB can save itself incrementally, do it now self.manager.classifier_data.SavePostIncrementalTrain() SetWaitCursor(0)# Helpers to work with images on buttons/toolbars.def SetButtonImage(button, fname, manager): # whew - http://support.microsoft.com/default.aspx?scid=KB;EN-US;q288771 # shows how to make a transparent bmp. # Also note that the clipboard takes ownership of the handle - # thus, we can not simply perform this load once and reuse the image. # Hacks for the binary - we can get the bitmaps from resources. if hasattr(sys, "frozen"): if fname=="recover_ham.bmp": bid = 6000 elif fname=="delete_as_spam.bmp": bid = 6001 else: raise RuntimeError, "What bitmap to use for '%s'?" % fname handle = win32gui.LoadImage(sys.frozendllhandle, bid, win32con.IMAGE_BITMAP, 0, 0, win32con.LR_DEFAULTSIZE) else: if not os.path.isabs(fname): # images relative to the application path fname = os.path.join(manager.application_directory, "images", fname) if not os.path.isfile(fname): print "WARNING - Trying to use image '%s', but it doesn't exist" % (fname,) return None handle = win32gui.LoadImage(0, fname, win32con.IMAGE_BITMAP, 0, 0, win32con.LR_DEFAULTSIZE | win32con.LR_LOADFROMFILE) win32clipboard.OpenClipboard()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -