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
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
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
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
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
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)
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
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
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
def raise_401(*args): raise ValidationError()
def login(self, email, password): if email not in self.logins or self.logins[email] != password: raise ValidationError(self.error_message)