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

📄 msgstore.py

📁 用python实现的邮件过滤器
💻 PY
📖 第 1 页 / 共 5 页
字号:
        # Problem #2:  Outlook decodes quoted-printable and base64 on its        # own, but leaves any Content-Transfer-Encoding line in the headers.        # This can cause the email pkg to try to decode the text again,        # with unpleasant (but rarely fatal) results.  If we strip that        # header too, no problem -- although the fact that a msg was        # encoded in base64 is usually a good spam clue, and we miss that.        #        # Short course:  we either have to synthesize non-insane MIME        # structure, or eliminate all evidence of original MIME structure.        # Since we don't have a way to the former, by default this function        # does the latter.        import email        text = self._GetMessageText()        try:            try:                msg = email.message_from_string(text)            except email.Errors.BoundaryError:                # In case this is the                #    "No terminating boundary and no trailing empty line"                # flavor of BoundaryError, we can supply a trailing empty                # line to shut it up.  It's certainly ill-formed MIME, and                # probably spam.  We don't care about the exact MIME                # structure, just the words it contains, so no harm and                # much good in trying to suppress this error.                try:                    msg = email.message_from_string(text + "\n\n")                except email.Errors.BoundaryError:                    msg = None            except email.Errors.HeaderParseError:                # This exception can come from parsing the header *or* the                # body of a mime message.                msg = None            # But even this doesn't get *everything*.  We can still see:            #  "multipart message with no defined boundary" or the            # HeaderParseError above.  Time to get brutal - hack out            # the Content-Type header, so we see it as plain text.            if msg is None:                butcher_pos = text.lower().find("\ncontent-type: ")                if butcher_pos < 0:                    # This error just just gunna get caught below anyway                    raise RuntimeError(                        "email package croaked with a MIME related error, but "                        "there appears to be no 'Content-Type' header")                # Put it back together, skipping the original "\n" but                # leaving the header leaving "\nSpamBayes-Content-Type: "                butchered = text[:butcher_pos] + "\nSpamBayes-" + \                            text[butcher_pos+1:] + "\n\n"                msg = email.message_from_string(butchered)        except:            print "FAILED to create email.message from: ", `text`            raise        if strip_mime_headers:            if msg.has_key('content-type'):                del msg['content-type']            if msg.has_key('content-transfer-encoding'):                del msg['content-transfer-encoding']        return msg    def SetField(self, prop, val):        # Future optimization note - from GetIDsFromNames doco        # Name-to-identifier mapping is represented by an object's        # PR_MAPPING_SIGNATURE property. PR_MAPPING_SIGNATURE contains        # a MAPIUID structure that indicates the service provider        # responsible for the object. If the PR_MAPPING_SIGNATURE        # property is the same for two objects, assume that these        # objects use the same name-to-identifier mapping.        # [MarkH: MAPIUID objects are supported and hashable]        # XXX If the SpamProb (Hammie, whatever) property is passed in as an        # XXX int, Outlook displays the field as all blanks, and sorting on        # XXX it doesn't do anything, etc.  I don't know why.  Since I'm        # XXX running Python 2.2.2, the _MapiTypeMap above confuses ints        # XXX with bools, but the problem persists even if I comment out the        # XXX PT_BOOLEAN entry from that dict.  Dumping in prints below show        # XXX that type_tag is 3 then, and that matches the defn of PT_I4 in        # XXX my system header files.        # XXX Later:  This works after all, but the field shows up as all        # XXX blanks unless I *first* modify the view (like Messages) in        # XXX Outlook to define a custom Integer field of the same name.        self._EnsureObject()        try:            if type(prop) != type(0):                props = ( (mapi.PS_PUBLIC_STRINGS, prop), )                propIds = self.mapi_object.GetIDsFromNames(props, mapi.MAPI_CREATE)                type_tag = _MapiTypeMap.get(type(val))                if type_tag is None:                    raise ValueError, "Don't know what to do with '%r' ('%s')" % (                                         val, type(val))                prop = PROP_TAG(type_tag, PROP_ID(propIds[0]))            help_test_suite("MAPIMsgStoreMsg.SetField")            if val is None:                # Delete the property                self.mapi_object.DeleteProps((prop,))            else:                self.mapi_object.SetProps(((prop,val),))            self.dirty = True        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def GetField(self, prop):        # xxx - still raise_errors?        self._EnsureObject()        if type(prop) != type(0):            props = ( (mapi.PS_PUBLIC_STRINGS, prop), )            prop = self.mapi_object.GetIDsFromNames(props, 0)[0]            if PROP_TYPE(prop) == PT_ERROR: # No such property                return None            prop = PROP_TAG( PT_UNSPECIFIED, PROP_ID(prop))        try:            hr, props = self.mapi_object.GetProps((prop,), 0)            ((tag, val), ) = props            if PROP_TYPE(tag) == PT_ERROR:                if val == mapi.MAPI_E_NOT_ENOUGH_MEMORY:                    # Too big for simple properties - get via a stream                    return GetPropFromStream(self.mapi_object, prop)                return None            return val        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def GetReadState(self):        val = self.GetField(PR_MESSAGE_FLAGS)        return (val&MSGFLAG_READ) != 0    def SetReadState(self, is_read):        try:            self._EnsureObject()            # always try and clear any pending delivery reports of read/unread            help_test_suite("MAPIMsgStoreMsg.SetReadState")            if is_read:                self.mapi_object.SetReadFlag(USE_DEFERRED_ERRORS|SUPPRESS_RECEIPT)            else:                self.mapi_object.SetReadFlag(USE_DEFERRED_ERRORS|CLEAR_READ_FLAG)            if __debug__:                if self.GetReadState() != is_read:                    print "MAPI SetReadState appears to have failed to change the message state"                    print "Requested set to %s but the MAPI field after was %r" % \                          (is_read, self.GetField(PR_MESSAGE_FLAGS))        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def Save(self):        assert self.dirty, "asking me to save a clean message!"        # It seems that *not* specifying mapi.MAPI_DEFERRED_ERRORS solves a lot        # problems!  So we don't!        try:            help_test_suite("MAPIMsgStoreMsg.Save")            self.mapi_object.SaveChanges(mapi.KEEP_OPEN_READWRITE)            self.dirty = False        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def _DoCopyMove(self, folder, isMove):        assert not self.dirty, \               "asking me to move a dirty message - later saves will fail!"        try:            dest_folder = self.msgstore._OpenEntry(folder.id)            source_folder = self.msgstore._OpenEntry(self.folder_id)            flags = 0            if isMove: flags |= MESSAGE_MOVE            eid = self.id[1]            help_test_suite("MAPIMsgStoreMsg._DoCopyMove")            source_folder.CopyMessages((eid,),                                        None,                                        dest_folder,                                        0,                                        None,                                        flags)            # At this stage, I think we have lost meaningful ID etc values            # Set everything to None to make it clearer what is wrong should            # this become an issue.  We would need to re-fetch the eid of            # the item, and set the store_id to the dest folder.            self.id = None            self.folder_id = None        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def MoveTo(self, folder):        self._DoCopyMove(folder, True)    def CopyTo(self, folder):        self._DoCopyMove(folder, False)    # Functions to perform operations, but report the error (ONCE!) to the    # user.  Any errors are re-raised so the caller can degrade gracefully if    # necessary.    # XXX - not too happy with these - they should go, and the caller should    # handle (especially now that we work exclusively with exceptions from    # this module.    def MoveToReportingError(self, manager, folder):        try:            self.MoveTo(folder)        except MsgStoreException, details:            ReportMAPIError(manager, _("Moving a message"),                            details.mapi_exception)    def CopyToReportingError(self, manager, folder):        try:            self.MoveTo(folder)        except MsgStoreException, details:            ReportMAPIError(manager, _("Copying a message"),                            details.mapi_exception)    def GetFolder(self):        # return a folder object with the parent, or None        folder_id = (mapi.HexFromBin(self.folder_id[0]),                     mapi.HexFromBin(self.folder_id[1]))        return self.msgstore.GetFolder(folder_id)    def RememberMessageCurrentFolder(self):        self._EnsureObject()        try:            folder = self.GetFolder()            # Also save this information in our messageinfo database, which            # means that restoring should work even with IMAP.            self.original_folder = folder.id[0], folder.id[1]            props = ( (mapi.PS_PUBLIC_STRINGS, "SpamBayesOriginalFolderStoreID"),                      (mapi.PS_PUBLIC_STRINGS, "SpamBayesOriginalFolderID")                      )            resolve_ids = self.mapi_object.GetIDsFromNames(props, mapi.MAPI_CREATE)            prop_ids = PROP_TAG( PT_BINARY, PROP_ID(resolve_ids[0])), \                       PROP_TAG( PT_BINARY, PROP_ID(resolve_ids[1]))            prop_tuples = (prop_ids[0],folder.id[0]), (prop_ids[1],folder.id[1])            self.mapi_object.SetProps(prop_tuples)            self.dirty = True        except pythoncom.com_error, details:            raise MsgStoreExceptionFromCOMException(details)    def GetRememberedFolder(self):        props = ( (mapi.PS_PUBLIC_STRINGS, "SpamBayesOriginalFolderStoreID"),                  (mapi.PS_PUBLIC_STRINGS, "SpamBayesOriginalFolderID")                  )        try:            self._EnsureObject()            resolve_ids = self.mapi_object.GetIDsFromNames(props, mapi.MAPI_CREATE)            prop_ids = PROP_TAG( PT_BINARY, PROP_ID(resolve_ids[0])), \                       PROP_TAG( PT_BINARY, PROP_ID(resolve_ids[1]))            hr, data = self.mapi_object.GetProps(prop_ids,0)            if hr != 0:                return None            (store_tag, store_id), (eid_tag, eid) = data            folder_id = mapi.HexFromBin(store_id), mapi.HexFromBin(eid)            help_test_suite("MAPIMsgStoreMsg.GetRememberedFolder")            return self.msgstore.GetFolder(folder_id)        except:            # Try to get it from the message info database, if possible            if self.original_folder:                return self.msgstore.GetFolder(self.original_folder)            print "Error locating origin of message", self            return Nonedef test():    from win32com.client import Dispatch    outlook = Dispatch("Outlook.Application")    inbox = outlook.Session.GetDefaultFolder(constants.olFolderInbox)    folder_id = inbox.Parent.StoreID, inbox.EntryID    store = MAPIMsgStore()    for folder in store.GetFolderGenerator([folder_id,], True):        print folder        for msg in folder.GetMessageGenerator():            print msg    store.Close()if __name__=='__main__':    test()

⌨️ 快捷键说明

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