?? libgmail.py
字號:
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 != '':
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -