def _open_crispin_connection(self, db_session): account = db_session.query(Account).get(self.account_id) try: conn = account.auth_handler.connect_account(account) except (IMAPClient.Error, socket.error, IMAP4.error): raise SearchBackendException(('Unable to connect to the IMAP ' 'server. Please retry in a ' 'couple minutes.'), 503) except ValidationError: raise SearchBackendException(("This search can't be performed " "because the account's credentials " "are out of date. Please " "reauthenticate and try again."), 403) try: acct_provider_info = provider_info(account.provider) except NotSupportedError: self.log.warn('Account provider not supported', provider=account.provider) raise self.crispin_client = CrispinClient(self.account_id, acct_provider_info, account.email_address, conn, readonly=True)
def _search(self, search_query, limit): try: token = g_token_manager.get_token_for_email(self.account) except OAuthError: raise SearchBackendException( "This search can't be performed because the account's " "credentials are out of date. Please reauthenticate and try " "again.", 403) ret = requests.get( u'https://www.googleapis.com/gmail/v1/users/me/messages', params={'q': search_query, 'maxResults': limit}, auth=OAuthRequestsWrapper(token)) log.info('Gmail API search request completed', elapsed=ret.elapsed.total_seconds()) if ret.status_code != 200: log.critical('HTTP error making search request', account_id=self.account.id, url=ret.url, response=ret.content) raise SearchBackendException( "Error issuing search request", 503, server_error=ret.content) data = ret.json() if 'messages' not in data: return [] # Note that the Gmail API returns g_msgids in hex format. So for # example the IMAP X-GM-MSGID 1438297078380071706 corresponds to # 13f5db9286538b1a in the API response we have here. return [int(m['id'], 16) for m in data['messages']]
def _search(self, search_query, limit): results = [] params = dict(q=search_query, maxResults=limit) # Could have used while True: but I don't like infinite loops. for i in range(1, 10): ret = requests.get( u"https://www.googleapis.com/gmail/v1/users/me/messages", params=params, auth=OAuthRequestsWrapper(self.auth_token), ) log.info( "Gmail API search request completed", elapsed=ret.elapsed.total_seconds(), ) if ret.status_code != 200: log.critical( "HTTP error making search request", account_id=self.account.id, url=ret.url, response=ret.content, ) raise SearchBackendException("Error issuing search request", 503, server_error=ret.content) data = ret.json() if "messages" not in data: return results # Note that the Gmail API returns g_msgids in hex format. So for # example the IMAP X-GM-MSGID 1438297078380071706 corresponds to # 13f5db9286538b1a in the API response we have here. results = results + [int(m["id"], 16) for m in data["messages"]] if len(results) >= limit: return results[:limit] if "nextPageToken" not in data: return results else: # We don't have <limit> results and there's more to fetch --- # get them! params["pageToken"] = data["nextPageToken"] log.info("Getting next page of search results") continue # If we've been through the loop 10 times, it means we got a request # a crazy-high offset --- raise an error. log.error("Too many search results", query=search_query, limit=limit) raise SearchBackendException("Too many results", 400)
def __init__(self, account): self.account_id = int(account.id) try: with session_scope(self.account_id) as db_session: self.account = db_session.query(Account).get(self.account_id) self.auth_token = g_token_manager.get_token_for_email( self.account) db_session.expunge_all() except OAuthError: raise SearchBackendException( "This search can't be performed because the account's " "credentials are out of date. Please reauthenticate and try " "again.", 403)
def _search_folder(self, folder, criteria, charset): try: self.crispin_client.select_folder(folder.name, uidvalidity_cb) except FolderMissingError: self.log.warn("Won't search missing IMAP folder", exc_info=True) return [] except UidInvalid: self.log.error(("Got Uidvalidity error when searching. " "Skipping."), exc_info=True) return [] try: uids = self.crispin_client.conn.search(criteria, charset=charset) except IMAP4.error: self.log.warn('Search error', exc_info=True) raise SearchBackendException(('Unknown IMAP error when ' 'performing search.'), 503) self.log.debug('Search found messages for folder', folder_name=folder.id, uids=len(uids)) return uids