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

📄 libgmail.py

📁 一个用Python的gmail功能库
💻 PY
📖 第 1 页 / 共 4 页
字号:
                try:                    threads = items[D_THREAD]                except KeyError:                    break                else:                    for th in threads:                        if not type(th[0]) is types.ListType:                            th = [th]                        threadsInfo.append(th)                    # TODO: Check if the total or per-page values have changed?                    threadListSummary = items[D_THREADLIST_SUMMARY][0]                    threadsPerPage = threadListSummary[TS_NUM]                        start += threadsPerPage                # TODO: Record whether or not we retrieved all pages..?        return GmailSearchResult(self, (searchType, kwargs), threadsInfo)    def _retrieveJavascript(self, version = ""):        """        Note: `version` seems to be ignored.        """        return self._retrievePage(_buildURL(view = U_PAGE_VIEW,                                            name = "js",                                            ver = version))                    def getMessagesByFolder(self, folderName, allPages = False):        """        Folders contain conversation/message threads.          `folderName` -- As set in Gmail interface.        Returns a `GmailSearchResult` instance.        *** TODO: Change all "getMessagesByX" to "getThreadsByX"? ***        """        return self._parseThreadSearch(folderName, allPages = allPages)    def getMessagesByQuery(self, query,  allPages = False):        """        Returns a `GmailSearchResult` instance.        """        return self._parseThreadSearch(U_QUERY_SEARCH, q = query,                                       allPages = allPages)        def getQuotaInfo(self, refresh = False):        """        Return MB used, Total MB and percentage used.        """        # TODO: Change this to a property.        if not self._cachedQuotaInfo or refresh:            # TODO: Handle this better...            self.getMessagesByFolder(U_INBOX_SEARCH)        return self._cachedQuotaInfo[0][:3]    def getLabelNames(self, refresh = False):        """        """        # TODO: Change this to a property?        if not self._cachedLabelNames or refresh:            # TODO: Handle this better...            self.getMessagesByFolder(U_INBOX_SEARCH)        return self._cachedLabelNames    def getMessagesByLabel(self, label, allPages = False):        """        """        return self._parseThreadSearch(U_CATEGORY_SEARCH,                                       cat=label, allPages = allPages)        def getRawMessage(self, msgId):        """        """        # U_ORIGINAL_MESSAGE_VIEW seems the only one that returns a page.        # All the other U_* results in a 404 exception. Stas        PageView = U_ORIGINAL_MESSAGE_VIEW          return self._retrievePage(            _buildURL(view=PageView, th=msgId))    def getUnreadMessages(self):        """        """        return self._parseThreadSearch(U_QUERY_SEARCH,                                        q = "is:" + U_AS_SUBSET_UNREAD)                    def getUnreadMsgCount(self):        """        """        items = self._parseSearchResult(U_QUERY_SEARCH,                                        q = "is:" + U_AS_SUBSET_UNREAD)        try:            result = items[D_THREADLIST_SUMMARY][0][TS_TOTAL_MSGS]        except KeyError:            result = 0        return result    def _getActionToken(self):        """        """        try:            at = self.getCookie(ACTION_TOKEN_COOKIE)        except KeyError:            self.getLabelNames(True)             at = self.getCookie(ACTION_TOKEN_COOKIE)        return at    def sendMessage(self, msg, asDraft = False, _extraParams = None):        """          `msg` -- `GmailComposedMessage` instance.          `_extraParams` -- Dictionary containing additional parameters                            to put into POST message. (Not officially                            for external use, more to make feature                            additional a little easier to play with.)                Note: Now returns `GmailMessageStub` instance with populated              `id` (and `_account`) fields on success or None on failure.        """        # TODO: Handle drafts separately?        params = {U_VIEW: [U_SENDMAIL_VIEW, U_SAVEDRAFT_VIEW][asDraft],                  U_REFERENCED_MSG: "",                  U_THREAD: "",                  U_DRAFT_MSG: "",                  U_COMPOSEID: "1",                  U_ACTION_TOKEN: self._getActionToken(),                  U_COMPOSE_TO: msg.to,                  U_COMPOSE_CC: msg.cc,                  U_COMPOSE_BCC: msg.bcc,                  "subject": msg.subject,                  "msgbody": msg.body,                  }        if _extraParams:            params.update(_extraParams)        # Amongst other things, I used the following post to work out this:        # <http://groups.google.com/groups?        #  selm=mailman.1047080233.20095.python-list%40python.org>        mimeMessage = _paramsToMime(params, msg.filenames, msg.files)        #### TODO: Ughh, tidy all this up & do it better...        ## This horrible mess is here for two main reasons:        ##  1. The `Content-Type` header (which also contains the boundary        ##     marker) needs to be extracted from the MIME message so        ##     we can send it as the request `Content-Type` header instead.        ##  2. It seems the form submission needs to use "\r\n" for new        ##     lines instead of the "\n" returned by `as_string()`.        ##     I tried changing the value of `NL` used by the `Generator` class        ##     but it didn't work so I'm doing it this way until I figure        ##     out how to do it properly. Of course, first try, if the payloads        ##     contained "\n" sequences they got replaced too, which corrupted        ##     the attachments. I could probably encode the submission,        ##     which would probably be nicer, but in the meantime I'm kludging        ##     this workaround that replaces all non-text payloads with a        ##     marker, changes all "\n" to "\r\n" and finally replaces the        ##     markers with the original payloads.        ## Yeah, I know, it's horrible, but hey it works doesn't it? If you've        ## got a problem with it, fix it yourself & give me the patch!        ##        origPayloads = {}        FMT_MARKER = "&&&&&&%s&&&&&&"        for i, m in enumerate(mimeMessage.get_payload()):            if not isinstance(m, MIMEText): #Do we care if we change text ones?                origPayloads[i] = m.get_payload()                m.set_payload(FMT_MARKER % i)        mimeMessage.epilogue = ""        msgStr = mimeMessage.as_string()        contentTypeHeader, data = msgStr.split("\n\n", 1)        contentTypeHeader = contentTypeHeader.split(":", 1)        data = data.replace("\n", "\r\n")        for k,v in origPayloads.iteritems():            data = data.replace(FMT_MARKER % k, v)        ####                req = ClientCookie.Request(_buildURL(), data = data)        req.add_header(*contentTypeHeader)        items = self._parsePage(req)        # TODO: Check composeid?        # Sometimes we get the success message        # but the id is 0 and no message is sent        result = None        resultInfo = items[D_SENDMAIL_RESULT][0]                if resultInfo[SM_SUCCESS]:            result = GmailMessageStub(id = resultInfo[SM_NEWTHREADID],                                      _account = self)        else:            raise GmailSendError, resultInfo[SM_MSG]        return result    def trashMessage(self, msg):        """        """        # TODO: Decide if we should make this a method of `GmailMessage`.        # TODO: Should we check we have been given a `GmailMessage` instance?        params = {            U_ACTION: U_DELETEMESSAGE_ACTION,            U_ACTION_MESSAGE: msg.id,            U_ACTION_TOKEN: self._getActionToken(),            }        items = self._parsePage(_buildURL(**params))        # TODO: Mark as trashed on success?        return (items[D_ACTION_RESULT][0][AR_SUCCESS] == 1)    def _doThreadAction(self, actionId, thread):        """        """        # TODO: Decide if we should make this a method of `GmailThread`.        # TODO: Should we check we have been given a `GmailThread` instance?        params = {            U_SEARCH: U_ALL_SEARCH, #TODO:Check this search value always works.            U_VIEW: U_UPDATE_VIEW,            U_ACTION: actionId,            U_ACTION_THREAD: thread.id,            U_ACTION_TOKEN: self._getActionToken(),            }        items = self._parsePage(_buildURL(**params))        return (items[D_ACTION_RESULT][0][AR_SUCCESS] == 1)                    def trashThread(self, thread):        """        """        # TODO: Decide if we should make this a method of `GmailThread`.        # TODO: Should we check we have been given a `GmailThread` instance?        result = self._doThreadAction(U_MARKTRASH_ACTION, thread)                # TODO: Mark as trashed on success?        return result    def _createUpdateRequest(self, actionId): #extraData):        """        Helper method to create a Request instance for an update (view)        action.        Returns populated `Request` instance.        """        params = {            U_VIEW: U_UPDATE_VIEW,            }        data = {            U_ACTION: actionId,            U_ACTION_TOKEN: self._getActionToken(),            }        #data.update(extraData)        req = ClientCookie.Request(_buildURL(**params),                              data = urllib.urlencode(data))        return req    # TODO: Extract additional common code from handling of labels?    def createLabel(self, labelName):        """        """        req = self._createUpdateRequest(U_CREATECATEGORY_ACTION + labelName)        # Note: Label name cache is updated by this call as well. (Handy!)        items = self._parsePage(req)        print items        return (items[D_ACTION_RESULT][0][AR_SUCCESS] == 1)    def deleteLabel(self, labelName):        """        """        # TODO: Check labelName exits?        req = self._createUpdateRequest(U_DELETECATEGORY_ACTION + labelName)        # Note: Label name cache is updated by this call as well. (Handy!)        items = self._parsePage(req)        return (items[D_ACTION_RESULT][0][AR_SUCCESS] == 1)    def renameLabel(self, oldLabelName, newLabelName):        """        """        # TODO: Check oldLabelName exits?        req = self._createUpdateRequest("%s%s^%s" % (U_RENAMECATEGORY_ACTION,                                                   oldLabelName, newLabelName))        # Note: Label name cache is updated by this call as well. (Handy!)        items = self._parsePage(req)        return (items[D_ACTION_RESULT][0][AR_SUCCESS] == 1)    def storeFile(self, filename, label = None):        """        """        # TODO: Handle files larger than single attachment size.        # TODO: Allow file data objects to be supplied?        FILE_STORE_VERSION = "FSV_01"        FILE_STORE_SUBJECT_TEMPLATE = "%s %s" % (FILE_STORE_VERSION, "%s")        subject = FILE_STORE_SUBJECT_TEMPLATE % os.path.basename(filename)        msg = GmailComposedMessage(to="", subject=subject, body="",                                   filenames=[filename])        draftMsg = self.sendMessage(msg, asDraft = True)        if draftMsg and label:            draftMsg.addLabel(label)        return draftMsg    ## CONTACTS SUPPORT    def getContacts(self):        """        Returns a GmailContactList object        that has all the contacts in it as        GmailContacts        """        contactList = []        # pnl = a is necessary to get *all* contacts        myUrl = _buildURL(view='cl',search='contacts', pnl='a')        myData = self._parsePage(myUrl)        # This comes back with a dictionary        # with entry 'cl'        addresses = myData['cl']        for entry in addresses:            if len(entry) >= 6 and entry[0]=='ce':                newGmailContact = GmailContact(entry[1], entry[2], entry[4], entry[5])                #### new code used to get all the notes                 #### not used yet due to lockdown problems                ##rawnotes = self._getSpecInfo(entry[1])                ##print rawnotes                ##newGmailContact = GmailContact(entry[1], entry[2], entry[4],rawnotes)                contactList.append(newGmailContact)        return GmailContactList(contactList)    def addContact(self, myContact, *extra_args):        """        Attempts to add a GmailContact to the gmail        address book. Returns true if successful,        false otherwise        Please note that after version 0.1.3.3,        addContact takes one argument of type        GmailContact, the contact to add.        The old signature of:        addContact(name, email, notes='') is still        supported, but deprecated.         """        if len(extra_args) > 0:            # The user has passed in extra arguments            # He/she is probably trying to invoke addContact            # using the old, deprecated signature of:            # addContact(self, name, email, notes='')                    # Build a GmailContact object and use that instead            (name, email) = (myContact, extra_args[0])            if len(extra_args) > 1:                notes = extra_args[1]            else:                notes = ''            myContact = GmailContact(-1, name, email, notes)        # TODO: In the ideal world, we'd extract these specific        # constants into a nice constants file                # This mostly comes from the Johnvey Gmail API,        # but also from the gmail.py cited earlier        myURL = _buildURL(view='up')                myDataList =  [ ('act','ec'),                        ('at', self.getCookie(ACTION_TOKEN_COOKIE)),                        ('ct_nm', myContact.getName()),                        ('ct_em', myContact.getEmail()),                        ('ct_id', -1 )                       ]        notes = myContact.getNotes()        if notes != '':

⌨️ 快捷键说明

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