Exemplo n.º 1
0
 def _authenticate_IMAP_connection(self, account, conn):
     """
     Overrides the same method in OAuthAuthHandler so that
     we can choose a token w/ the appropriate scope.
     """
     host, port = account.imap_endpoint
     try:
         token = g_token_manager.get_token_for_email(account)
         conn.oauth2_login(account.email_address, token)
     except IMAPClient.Error as exc:
         log.error('Error during IMAP XOAUTH2 login',
                   account_id=account.id, email=account.email_address,
                   host=host, port=port, error=exc)
         if not _auth_is_invalid(exc):
             raise
         # If we got an AUTHENTICATIONFAILED response, force a token refresh
         # and try again. If IMAP auth still fails, it's likely that IMAP
         # access is disabled, so propagate that errror.
         token = g_token_manager.get_token_for_email(
             account, force_refresh=True)
         try:
             conn.oauth2_login(account.email_address, token)
         except IMAPClient.Error as exc:
             if not _auth_is_invalid(exc):
                 raise
             raise ImapSupportDisabledError()
Exemplo n.º 2
0
 def get_token(self, account, force_refresh=False):
     if account.provider == 'gmail':
         return g_token_manager.get_token_for_email(
             account, force_refresh=force_refresh)
     else:
         return default_token_manager.get_token(
             account, force_refresh=force_refresh)
Exemplo n.º 3
0
def get_gmail_raw_contents(message):
    account = message.namespace.account
    auth_token = g_token_manager.get_token_for_email(account)

    # The Gmail API exposes the X-GM-MSGID field but encodes it
    # in hexadecimal.
    g_msgid = message.g_msgid

    if g_msgid is None:
        raise EmailDeletedException("Couldn't find message on backend server. This is a permanent error.")

    if isinstance(g_msgid, basestring):
        g_msgid = int(g_msgid)

    hex_id = format(g_msgid, 'x')
    url = 'https://www.googleapis.com/gmail/v1/users/me/messages/{}?format=raw'.format(hex_id, 'x')
    r = requests.get(url, auth=OAuthRequestsWrapper(auth_token))

    if r.status_code != 200:
        log.error('Got an error when fetching raw email', r.status_code, r.text)

    if r.status_code in [403, 429]:
        raise TemporaryEmailFetchException("Temporary usage limit hit. Please try again.")
    if r.status_code == 404:
        raise EmailDeletedException("Couldn't find message on backend server. This is a permanent error.")
    elif r.status_code >= 500 and r.status_code <= 599:
        raise TemporaryEmailFetchException("Backend server error. Please try again in a few minutes.")

    data = r.json()
    raw = str(data['raw'])
    return base64.urlsafe_b64decode(raw + '=' * (4 - len(raw) % 4))
Exemplo n.º 4
0
 def get_token(self, account, force_refresh=False):
     if account.provider == 'gmail':
         return g_token_manager.get_token_for_email(
             account, force_refresh=force_refresh)
     else:
         return default_token_manager.get_token(account,
                                                force_refresh=force_refresh)
Exemplo n.º 5
0
 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']]
Exemplo n.º 6
0
    def _authenticate_IMAP_connection(self, account, conn):
        """
        Overrides the same method in OAuthAuthHandler so that
        we can choose a token w/ the appropriate scope.

        """
        host, port = account.imap_endpoint
        try:
            token = g_token_manager.get_token_for_email(account)
            conn.oauth2_login(account.email_address, token)
        except IMAPClient.Error as exc:
            exc = _process_imap_exception(exc)
            # Raise all imap disabled errors except authentication_failed
            # error, swhich we handle differently
            if isinstance(exc, ImapSupportDisabledError) and \
                    exc.reason != 'authentication_failed':
                raise exc

            log.error('Error during IMAP XOAUTH2 login',
                      account_id=account.id,
                      email=account.email_address,
                      host=host,
                      port=port,
                      error=exc)
            if not isinstance(exc, ImapSupportDisabledError):
                raise  # Unknown IMAPClient error, reraise

            # If we got an AUTHENTICATIONFAILED response, force a token refresh
            # and try again. If IMAP auth still fails, it's likely that IMAP
            # access is disabled, so propagate that errror.
            token = g_token_manager.get_token_for_email(account,
                                                        force_refresh=True)
            try:
                conn.oauth2_login(account.email_address, token)
            except IMAPClient.Error as exc:
                exc = _process_imap_exception(exc)
                if not isinstance(exc, ImapSupportDisabledError) or \
                        exc.reason != 'authentication_failed':
                    raise exc
                else:
                    # Instead of authentication_failed, report imap disabled
                    raise ImapSupportDisabledError('imap_disabled_for_account')
Exemplo n.º 7
0
 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)
Exemplo n.º 8
0
 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)
Exemplo n.º 9
0
    def _authenticate_IMAP_connection(self, account, conn):
        """
        Overrides the same method in OAuthAuthHandler so that
        we can choose a token w/ the appropriate scope.

        """
        host, port = account.imap_endpoint
        try:
            token = g_token_manager.get_token_for_email(account)
            conn.oauth2_login(account.email_address, token)
        except IMAPClient.Error as exc:
            exc = _process_imap_exception(exc)
            # Raise all imap disabled errors except authentication_failed
            # error, swhich we handle differently
            if isinstance(exc, ImapSupportDisabledError) and \
                    exc.reason != 'authentication_failed':
                raise exc

            log.error('Error during IMAP XOAUTH2 login',
                      account_id=account.id, email=account.email_address,
                      host=host, port=port, error=exc)
            if not isinstance(exc, ImapSupportDisabledError):
                raise  # Unknown IMAPClient error, reraise

            # If we got an AUTHENTICATIONFAILED response, force a token refresh
            # and try again. If IMAP auth still fails, it's likely that IMAP
            # access is disabled, so propagate that errror.
            token = g_token_manager.get_token_for_email(
                account, force_refresh=True)
            try:
                conn.oauth2_login(account.email_address, token)
            except IMAPClient.Error as exc:
                exc = _process_imap_exception(exc)
                if not isinstance(exc, ImapSupportDisabledError) or \
                        exc.reason != 'authentication_failed':
                    raise exc
                else:
                    # Instead of authentication_failed, report imap disabled
                    raise ImapSupportDisabledError('imap_disabled_for_account')
Exemplo n.º 10
0
 def _authenticate_IMAP_connection(self, account, conn):
     """
     Overrides the same method in OAuthAuthHandler so that
     we can choose a token w/ the appropriate scope.
     """
     host, port = account.imap_endpoint
     try:
         token = g_token_manager.get_token_for_email(account)
         conn.oauth2_login(account.email_address, token)
     except IMAPClient.Error as exc:
         log.error('Error during IMAP XOAUTH2 login',
                   account_id=account.id,
                   email=account.email_address,
                   host=host,
                   port=port,
                   error=exc)
         raise
Exemplo n.º 11
0
def get_gmail_raw_contents(message):
    account = message.namespace.account
    auth_token = g_token_manager.get_token_for_email(account)

    # The Gmail API exposes the X-GM-MSGID field but encodes it
    # in hexadecimal.
    g_msgid = message.g_msgid

    if g_msgid is None:
        raise EmailDeletedException(
            "Couldn't find message on backend server. This is a permanent error."
        )

    if isinstance(g_msgid, basestring):
        g_msgid = int(g_msgid)

    hex_id = format(g_msgid, 'x')
    url = 'https://www.googleapis.com/gmail/v1/users/me/messages/{}?format=raw'.format(
        hex_id, 'x')
    r = requests.get(url, auth=OAuthRequestsWrapper(auth_token))

    if r.status_code != 200:
        log.error('Got an error when fetching raw email', r.status_code,
                  r.text)

    if r.status_code in [403, 429]:
        raise TemporaryEmailFetchException(
            "Temporary usage limit hit. Please try again.")
    if r.status_code == 404:
        raise EmailDeletedException(
            "Couldn't find message on backend server. This is a permanent error."
        )
    elif r.status_code >= 500 and r.status_code <= 599:
        raise TemporaryEmailFetchException(
            "Backend server error. Please try again in a few minutes.")

    data = r.json()
    raw = str(data['raw'])
    return base64.urlsafe_b64decode(raw + '=' * (4 - len(raw) % 4))