예제 #1
0
파일: oauth.py 프로젝트: chengjunjian/inbox
def connect_account(account):
    """Provide a connection to a IMAP account.

    Raises
    ------
    socket.error
        If we cannot connect to the IMAP host.
    IMAPClient.error
        If the credentials are invalid.
    """

    info = provider_info(account.provider)
    host = info["imap"]
    try:
        conn = IMAPClient(host, use_uid=True, ssl=True)
    except IMAPClient.Error as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Can't connect to host (Failure)")
        raise ConnectionError(str(e))
    except gaierror as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Name resolution faiure (Failure)")
        raise ConnectionError(str(e))
    except socket_error as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Socket connection failure (Failure)")
        raise ConnectionError(str(e))

    conn.debug = False
    try:
        conn.oauth2_login(account.email_address, account.access_token)
    except IMAPClient.Error as e:
        log.error("IMAP Login error, refresh auth token for: {}"
                  .format(account.email_address))
        log.error("Error was: {}".format(e))
        if str(e) == '[ALERT] Invalid credentials (Failure)':
            # maybe the access token expired?
            try:
                conn.oauth2_login(account.email_address,
                                  account.renew_access_token())
            except IMAPClient.Error as e:
                raise ValidationError()
        else:
            raise ValidationError()
    except SSLError as e:
        log.error('account_verify_failed',
                  email=account.email_address,
                  host=host,
                  error="[ALERT] SSL Connection error (Failure)")
        raise ConnectionError(str(e))

    return conn
예제 #2
0
    def connect_account(self, email, pw, imap_endpoint, account_id=None):
        """Provide a connection to a IMAP account.

        Raises
        ------
        socket.error
            If we cannot connect to the IMAP host.
        IMAPClient.error
            If the credentials are invalid.
        """
        host, port = imap_endpoint
        try:
            conn = IMAPClient(host, port=port, use_uid=True, ssl=True)
        except IMAPClient.AbortError as e:
            log.error('account_connect_failed',
                      account_id=account_id,
                      email=email,
                      host=host,
                      port=port,
                      error="[ALERT] Can't connect to host - may be transient")
            raise TransientConnectionError(str(e))
        except (IMAPClient.Error, gaierror, socket_error) as e:
            log.error('account_connect_failed',
                      account_id=account_id,
                      email=email,
                      host=host,
                      port=port,
                      error='[ALERT] (Failure): {0}'.format(str(e)))
            raise ConnectionError(str(e))

        conn.debug = False
        try:
            conn.oauth2_login(email, pw)
        except IMAPClient.AbortError as e:
            log.error('account_verify_failed',
                      account_id=account_id,
                      email=email,
                      host=host,
                      port=port,
                      error="[ALERT] Can't connect to host - may be transient")
            raise TransientConnectionError(str(e))
        except IMAPClient.Error as e:
            log.error('IMAP Login error during connection. '
                      'Account: {}, error: {}'.format(email, e),
                      account_id=account_id)
            if (str(e) == '[ALERT] Invalid credentials (Failure)'
                    or str(e).startswith('[AUTHENTICATIONFAILED]')):
                raise ValidationError(str(e))
            else:
                raise ConnectionError(str(e))
        except SSLError as e:
            log.error('account_verify_failed',
                      account_id=account_id,
                      email=email,
                      host=host,
                      port=port,
                      error='[ALERT] (Failure) SSL Connection error')
            raise ConnectionError(str(e))

        return conn
예제 #3
0
    def connect_account(self, provider, email, credential):
        """Provide a connection to a generic IMAP account.

        Raises
        ------
        ConnectionError
            If we cannot connect to the IMAP host.
        TransientConnectionError
            Sometimes the server bails out on us. Retrying may
            fix things.
        ValidationError
            If the credentials are invalid.
        """

        info = provider_info(provider, email)
        host, port = info['imap']
        try:
            conn = IMAPClient(host, port=port, use_uid=True, ssl=True)
        except IMAPClient.AbortError as e:
            log.error('account_connect_failed',
                      email=email,
                      host=host,
                      port=port,
                      error="[ALERT] Can't connect to host - may be transient")
            raise TransientConnectionError(str(e))
        except(IMAPClient.Error, gaierror, socket_error) as e:
            log.error('account_connect_failed',
                      email=email,
                      host=host,
                      port=port,
                      error='[ALERT] (Failure): {0}'.format(str(e)))
            raise ConnectionError(str(e))

        conn.debug = False
        try:
            conn.login(email, credential)
        except IMAPClient.AbortError as e:
            log.error('account_verify_failed',
                      email=email,
                      host=host,
                      port=port,
                      error="[ALERT] Can't connect to host - may be transient")
            raise TransientConnectionError(str(e))
        except IMAPClient.Error as e:
            log.error('account_verify_failed',
                      email=email,
                      host=host,
                      port=port,
                      error='[ALERT] Invalid credentials (Failure)')
            raise ValidationError(str(e))
        except SSLError as e:
            log.error('account_verify_failed',
                      email=email,
                      host=host,
                      port=port,
                      error='[ALERT] SSL Connection error (Failure)')
            raise ConnectionError(str(e))

        return conn
예제 #4
0
파일: oauth.py 프로젝트: rbs-pli/inbox
def connect_account(account):
    """Provide a connection to a IMAP account.

    Raises
    ------
    socket.error
        If we cannot connect to the IMAP host.
    IMAPClient.error
        If the credentials are invalid.
    """
    info = provider_info(account.provider)
    host = info['imap']
    try:
        conn = IMAPClient(host, use_uid=True, ssl=True)
    except IMAPClient.AbortError as e:
        log.error('account_connect_failed',
                  email=account.email_address,
                  host=host,
                  error=("[ALERT] Can't connect to host - may be transient"))
        raise TransientConnectionError(str(e))
    except(IMAPClient.Error, gaierror, socket_error) as e:
        log.error('account_connect_failed',
                  email=account.email_address,
                  host=host,
                  error='[ALERT] (Failure): {0}'.format(str(e)))
        raise ConnectionError(str(e))

    conn.debug = False
    try:
        conn.oauth2_login(account.email_address, account.access_token)
    except IMAPClient.AbortError as e:
        log.error('account_verify_failed',
                  email=account.email_address,
                  host=host,
                  error="[ALERT] Can't connect to host - may be transient")
        raise TransientConnectionError(str(e))
    except IMAPClient.Error as e:
        log.error('IMAP Login error during refresh auth token. '
                  'Account: {}, error: {}'.format(account.email_address, e))
        if str(e) == '[ALERT] Invalid credentials (Failure)':
            # Access token could've expired
            try:
                conn.oauth2_login(account.email_address,
                                  account.renew_access_token())
            except IMAPClient.Error as e:
                raise ValidationError(str(e))
        else:
            raise ConnectionError(str(e))
    except SSLError as e:
        log.error('account_verify_failed',
                  email=account.email_address,
                  host=host,
                  error='[ALERT] (Failure) SSL Connection error')
        raise ConnectionError(str(e))

    return conn
예제 #5
0
파일: oauth.py 프로젝트: wmv/inbox
def connect_account(provider, email, pw):
    """Provide a connection to a IMAP account.

    Raises
    ------
    socket.error
        If we cannot connect to the IMAP host.
    IMAPClient.error
        If the credentials are invalid.
    """
    info = provider_info(provider)
    host, port = info['imap']
    try:
        conn = IMAPClient(host, port=port, use_uid=True, ssl=True)
    except IMAPClient.AbortError as e:
        log.error('account_connect_failed',
                  email=email,
                  host=host,
                  port=port,
                  error=("[ALERT] Can't connect to host - may be transient"))
        raise TransientConnectionError(str(e))
    except (IMAPClient.Error, gaierror, socket_error) as e:
        log.error('account_connect_failed',
                  email=email,
                  host=host,
                  port=port,
                  error='[ALERT] (Failure): {0}'.format(str(e)))
        raise ConnectionError(str(e))

    conn.debug = False
    try:
        conn.oauth2_login(email, pw)
    except IMAPClient.AbortError as e:
        log.error('account_verify_failed',
                  email=email,
                  host=host,
                  port=port,
                  error="[ALERT] Can't connect to host - may be transient")
        raise TransientConnectionError(str(e))
    except IMAPClient.Error as e:
        log.error('IMAP Login error during refresh auth token. '
                  'Account: {}, error: {}'.format(email, e))
        if str(e) == '[ALERT] Invalid credentials (Failure)' or \
           str(e) == '[AUTHENTICATIONFAILED] OAuth authentication failed.':
            raise ValidationError(str(e))
        else:
            raise ConnectionError(str(e))
    except SSLError as e:
        log.error('account_verify_failed',
                  email=email,
                  host=host,
                  port=port,
                  error='[ALERT] (Failure) SSL Connection error')
        raise ConnectionError(str(e))

    return conn
예제 #6
0
    def fetch_items(self, sync_from_time=None):
        response_items = []
        with session_scope() as db_session:
            account = db_session.query(GenericAccount).get(self.account_id)
            email_address = account.email_address
            password = account.password

        session = requests.Session()
        session.headers = {'origin': ICLOUD_URL}

        instance = uuid.uuid4().hex.encode('utf-8')
        sha_id = hashlib.sha1(email_address.encode('utf-8') + instance)

        data = json.dumps({
            'apple_id': email_address,
            'password': password,
            'id': sha_id.hexdigest().upper(),
            'extended_login': False
        })

        # First login to iCloud to verify credentials
        req = session.post(ICLOUD_LOGIN, data=data)

        if not req.ok:
            raise ValidationError()

        # Next validate to get the dsInfo.dsid
        req = session.get(ICLOUD_VALIDATE)
        resp = req.json()

        if 'dsInfo' not in resp:
            self.log.warn('Event parse error', account_id=self.account_id)
            return

        dsid = resp['dsInfo']['dsid']

        calendar_url = resp['webservices']['calendar']['url']
        event_url = calendar_url + '/ca/events'

        params = {
            'dsid': dsid,
            'lang': 'en-us',
            'usertz': 'UTC',
            'startDate': '1999-12-31',
            'endDate': '2999-12-31'
        }
        resp = session.get(event_url, params=params)

        resp = resp.json()

        calendar_id = self.get_calendar_id('default')
        response_items = resp['Event']

        for response_event in response_items:
            yield (calendar_id, response_event, None)
예제 #7
0
def connect_account(account):
    """Provide a connection to a generic IMAP account.

    Raises
    ------
    ConnectionError
        If we cannot connect to the IMAP host.
    ValidationError
        If the credentials are invalid.
    """

    info = provider_info(account.provider)
    host = info["imap"]
    try:
        conn = IMAPClient(host, use_uid=True, ssl=True)
    except IMAPClient.Error as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Can't connect to host (Failure)")
        raise ConnectionError(str(e))
    except gaierror as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Name resolution faiure (Failure)")
        raise ConnectionError(str(e))
    except socket_error as e:
        log.error('account_connect_failed',
                  host=host,
                  error="[ALERT] Socket connection failure (Failure)")
        raise ConnectionError(str(e))

    conn.debug = False
    try:
        conn.login(account.email_address, account.password)
    except IMAPClient.Error as e:
        log.error('account_verify_failed',
                  email=account.email_address,
                  host=host,
                  error="[ALERT] Invalid credentials (Failure)")
        raise ValidationError()
    except SSLError as e:
        log.error('account_verify_failed',
                  email=account.email_address,
                  host=host,
                  error="[ALERT] SSL Connection error (Failure)")
        raise ConnectionError(str(e))

    return conn
예제 #8
0
 def authenticate_imap_connection(self, account, conn):
     try:
         conn.login(account.imap_username, account.imap_password)
     except IMAPClient.Error as exc:
         if auth_is_invalid(exc):
             log.error(
                 "IMAP login failed",
                 account_id=account.id,
                 error=exc,
             )
             raise ValidationError(exc)
         elif auth_requires_app_password(exc):
             raise AppPasswordError(exc)
         else:
             log.error(
                 "IMAP login failed for an unknown reason. Check auth_is_invalid",
                 account_id=account.id,
                 error=exc,
             )
             raise
예제 #9
0
    def connect_account(self, account, use_timeout=True):
        """
        Returns an authenticated IMAP connection for the given account.

        Raises
        ------
        ValidationError
            If IMAP LOGIN failed because of invalid username/password
        imapclient.IMAPClient.Error, socket.error
            If other errors occurred establishing the connection or logging in.

        """
        host, port = account.imap_endpoint
        ssl_required = account.ssl_required
        try:
            conn = create_imap_connection(host, port, ssl_required,
                                          use_timeout)
        except (IMAPClient.Error, socket.error) as exc:
            log.error('Error instantiating IMAP connection',
                      account_id=account.id,
                      host=host,
                      port=port,
                      ssl_required=ssl_required,
                      error=exc)
            raise
        try:
            conn.login(account.imap_username, account.imap_password)
        except IMAPClient.Error as exc:
            if _auth_is_invalid(exc):
                log.error('IMAP login failed',
                          account_id=account.id,
                          host=host,
                          port=port,
                          ssl_required=ssl_required,
                          error=exc)
                raise ValidationError(exc)
            elif _auth_requires_app_password(exc):
                raise AppPasswordError(exc)
            else:
                log.error(
                    'IMAP login failed for an unknown reason. Check _auth_is_invalid',
                    account_id=account.id,
                    host=host,
                    port=port,
                    ssl_required=ssl_required,
                    error=exc)
                raise

        if 'ID' in conn.capabilities():
            # Try to issue an IMAP ID command. Some whacky servers
            # (163.com) require this, but it's an encouraged practice in any
            # case. Since this isn't integral to the sync in general, don't
            # fail if there are any errors.
            # (Note that as of May 2015, this depends on a patched imapclient
            # that implements the ID command.)
            try:
                conn.id_({
                    'name': 'Nylas Sync Engine',
                    'vendor': 'Nylas',
                    'contact': '*****@*****.**'
                })
            except Exception as exc:
                log.warning('Error issuing IMAP ID command; continuing',
                            account_id=account.id,
                            host=host,
                            port=port,
                            ssl_required=ssl_required,
                            error=exc)

        return conn
예제 #10
0
 def raise_401(*args):
     raise ValidationError()
예제 #11
0
 def login(self, email, password):
     if email not in self.logins or self.logins[email] != password:
         raise ValidationError(self.error_message)