Exemple #1
0
def test_imap_not_fully_enabled(monkeypatch):

    def folder_list_fail(conn):
        raise Exception("LIST failed: '[ALERT] full IMAP support "
                        "is NOT enabled for this account'")

    monkeypatch.setattr('imapclient.IMAPClient.list_folders',
                        folder_list_fail)

    def fake_connect(account):
        return MockIMAPClient()

    response = {
        'email': '*****@*****.**',
        'password': '******',
        'imap_server_host': '0.0.0.0',
        'imap_server_port': 22,
        'smtp_server_host': '0.0.0.0',
        'smtp_server_port': 23
    }

    handler = GenericAuthHandler('custom')
    acct = handler.create_account(
        '*****@*****.**',
        response)
    handler.connect_account = fake_connect
    handler._supports_condstore = lambda x: True
    with pytest.raises(UserRecoverableConfigError):
        verified = handler.verify_account(acct)
        assert verified is not True
Exemple #2
0
def modify_account(namespace_public_id):
    """
    Modify an existing account

    This stops syncing an account until it is explicitly resumed.
    """

    data = request.get_json(force=True)

    with global_session_scope() as db_session:
        namespace = (db_session.query(Namespace).filter(
            Namespace.public_id == namespace_public_id).one())
        account = namespace.account

        if isinstance(account, GenericAccount):
            auth_handler = GenericAuthHandler()
            account_data = _get_account_data_for_generic_account(data)
        elif isinstance(account, GmailAccount):
            auth_handler = GoogleAuthHandler()
            account_data = _get_account_data_for_google_account(data)
        elif isinstance(account, OutlookAccount):
            auth_handler = MicrosoftAuthHandler()
            account_data = _get_account_data_for_microsoft_account(data)
        else:
            raise ValueError("Account type not supported.")

        account = auth_handler.update_account(account, account_data)
        db_session.add(account)
        db_session.commit()

        encoder = APIEncoder()
        return encoder.jsonify(account.namespace)
Exemple #3
0
def yahoo_account(db):
    account = GenericAuthHandler('yahoo').create_account(
        TEST_YAHOO_EMAIL,
        {"email": TEST_YAHOO_EMAIL, "password": "******"})
    db.session.add(account)
    db.session.commit()
    return account
Exemple #4
0
def test_successful_reauth_resets_sync_state(db):
    settings = {
        'provider': 'yahoo',
        'settings': {
            'name': 'Y.Y!',
            'locale': 'fr',
            'email': '*****@*****.**',
            'password': '******'
        }
    }
    email = settings['settings']['email']
    handler = GenericAuthHandler(settings['provider'])

    account = handler.create_account(email, settings['settings'])
    assert handler.verify_account(account) is True
    # Brand new accounts have `sync_state`=None.
    assert account.sync_state is None
    db.session.add(account)
    db.session.commit()

    # Pretend account sync starts, and subsequently the password changes,
    # causing the account to be in `sync_state`='invalid'.
    account.mark_invalid()
    db.session.commit()
    assert account.sync_state == 'invalid'

    # Verify the `sync_state` is reset to 'running' on a successful "re-auth".
    account = handler.update_account(account, settings['settings'])
    assert handler.verify_account(account) is True
    assert account.sync_state == 'running'
    db.session.add(account)
    db.session.commit()
def test_successful_reauth_resets_sync_state(db, mock_imapclient):
    email = account_data.email
    password = account_data.imap_password
    mock_imapclient._add_login(email, password)
    handler = GenericAuthHandler()

    account = handler.create_account(account_data)
    assert handler.verify_account(account) is True
    # Brand new accounts have `sync_state`=None.
    assert account.sync_state is None
    db.session.add(account)
    db.session.commit()

    # Pretend account sync starts, and subsequently the password changes,
    # causing the account to be in `sync_state`='invalid'.
    account.mark_invalid()
    db.session.commit()
    assert account.sync_state == "invalid"

    # Verify the `sync_state` is reset to 'running' on a successful "re-auth".
    account = handler.update_account(account, account_data)
    assert handler.verify_account(account) is True
    assert account.sync_state == "running"
    db.session.add(account)
    db.session.commit()
def _create_account(settings, ssl):
    email = settings['settings']['email']
    handler = GenericAuthHandler(settings['provider'])
    credentials = copy.deepcopy(settings)
    credentials['settings']['ssl_required'] = ssl
    account = handler.create_account(email, credentials['settings'])
    return account
Exemple #7
0
def test_auth(creds):
    handler = GenericAuthHandler(creds['provider'])
    email = creds['settings']['email']
    account = handler.create_account(email, creds['settings'])

    # Test that the account was successfully created by the handler.
    if 'smtp_password' in creds['settings']:
        assert account.imap_password == creds['settings']['imap_password']
        assert account.smtp_password == creds['settings']['smtp_password']
    else:
        assert account.imap_password == creds['settings']['password']
        assert account.smtp_password == creds['settings']['password']

    # Test that the account is valid.
    assert handler.verify_account(account) is True

    # Test that the password can be updated...
    bad_creds = {'email': creds['settings']['email'],
                 'imap_password': '******',
                 'imap_server_host': creds['settings'].get('imap_server_host'),
                 'imap_server_port': 993,
                 'smtp_server_host': creds['settings'].get('smtp_server_host'),
                 'smtp_server_port': 587
                 }
    handler.update_account(account, bad_creds)
    assert account.imap_password == 'bad_password'
    # ...but logging in again won't work.
    with pytest.raises(ValidationError):
        handler.verify_account(account)
Exemple #8
0
def test_update_account_when_no_server_provided(db):
    email = settings['settings']['email']
    imap_host = settings['settings']['imap_server_host']
    imap_port = settings['settings']['imap_server_port']
    smtp_host = settings['settings']['smtp_server_host']
    smtp_port = settings['settings']['smtp_server_port']

    handler = GenericAuthHandler(settings['provider'])

    account = handler.create_account(email, settings['settings'])
    # On successful auth, the account's imap_server is stored.
    db.session.add(account)
    db.session.commit()
    id_ = account.id
    db.session.commit()

    # Valid updates:
    # A future authentication does not include the `imap_server_host` either.
    db.session.expire(account)
    account = db.session.query(Account).get(id_)

    updated_settings = copy.deepcopy(settings)
    del updated_settings['settings']['imap_server_host']
    del updated_settings['settings']['smtp_server_host']

    account = handler.update_account(account, updated_settings['settings'])
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    acc_imap_host, acc_imap_port = account.imap_endpoint
    assert acc_imap_host == imap_host
    assert acc_imap_port == imap_port

    acc_smtp_host, acc_smtp_port = account.smtp_endpoint
    assert acc_smtp_host == smtp_host
    assert acc_smtp_port == smtp_port

    # A future authentication has the `imap_server_host=''
    # and smtp_server_host=''`.
    # This is what happens in the legacy auth flow, since
    # Proposal.imap_server_host and smtp_server_host will be set to u''
    # if not provided.
    db.session.expire(account)
    account = db.session.query(Account).get(id_)
    updated_settings['settings']['imap_server_host'] = u''
    updated_settings['settings']['smtp_server_host'] = u''
    account = handler.update_account(account, updated_settings['settings'])
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    acc_imap_host, acc_imap_port = account.imap_endpoint
    assert acc_imap_host == imap_host
    assert acc_imap_port == imap_port

    acc_smtp_host, acc_smtp_port = account.smtp_endpoint
    assert acc_smtp_host == smtp_host
    assert acc_smtp_port == smtp_port
Exemple #9
0
def generic_account(db):
    from inbox.auth.generic import GenericAuthHandler

    handler = GenericAuthHandler(provider_name='generic')
    acc = handler.create_account(db.session, 'user@generic_email.com', {
        'email': '*****@*****.**',
        'password': '******'
    })
    db.session.add(acc)
    db.session.commit()
    return acc
def test_auth(settings):
    handler = GenericAuthHandler(settings['provider'])

    has_starttls = ('aol' in settings['settings']['imap_server_host'])
    if has_starttls:
        account = _create_account(settings, ssl=True)
        handler.verify_account(account)
    else:
        account = _create_account(settings, ssl=True)
        with pytest.raises(Exception):
            handler.verify_account(account)
        account = _create_account(settings, ssl=False)
        handler.verify_account(account)
def test_double_auth(db):
    settings = {
        'provider': 'yahoo',
        'settings': {
            'name': 'Y.Y!',
            'locale': 'fr',
            'email': '*****@*****.**',
            'password': '******'
        }
    }
    email = settings['settings']['email']
    password = settings['settings']['password']

    handler = GenericAuthHandler(settings['provider'])

    # First authentication, using a valid password, succeeds.
    valid_settings = copy.deepcopy(settings)

    account = handler.create_account(email, valid_settings['settings'])
    assert handler.verify_account(account) is True

    db.session.add(account)
    db.session.commit()
    id_ = account.id
    account = db.session.query(Account).get(id_)
    assert account.email_address == email
    assert account.imap_username == email
    assert account.smtp_username == email
    assert account.password == password
    assert account.imap_password == password
    assert account.smtp_password == password

    # Second auth using an invalid password should fail.
    invalid_settings = copy.deepcopy(settings)
    invalid_settings['settings']['password'] = '******'
    with pytest.raises(ValidationError):
        account = handler.update_account(account, invalid_settings['settings'])
        handler.verify_account(account)

    db.session.expire(account)

    # Ensure original account is unaffected
    account = db.session.query(Account).get(id_)
    assert account.email_address == email
    assert account.imap_username == email
    assert account.smtp_username == email
    assert account.password == password
    assert account.imap_password == password
    assert account.smtp_password == password
Exemple #12
0
def folder_sync_engine(db):
    from inbox.mailsync.backends.imap.generic import FolderSyncEngine
    # setup a dummy FolderSyncEngine - we only need to call a couple
    # methods.
    email = "*****@*****.**"
    account = GenericAuthHandler('fastmail').create_account(
        db.session, email, {"email": email, "password": "******"})
    db.session.add(account)
    db.session.commit()

    engine = None
    engine = FolderSyncEngine(account.id, "Inbox", 0,
                              email, "fastmail",
                              None)
    return engine
def local_smtp_account(db):
    from inbox.auth.generic import GenericAuthHandler

    handler = GenericAuthHandler(provider_name='custom')
    acc = handler.create_account(
        db.session, '*****@*****.**', {
            'email': '*****@*****.**',
            'password': '******',
            'imap_server_host': 'imap-test.nylas.com',
            'imap_server_port': 143,
            'smtp_server_host': SMTP_SERVER_HOST,
            'smtp_server_port': SMTP_SERVER_PORT
        })
    db.session.add(acc)
    db.session.commit()
    return acc
def test_update_account(db):
    handler = GenericAuthHandler()

    # Create an authenticated account
    account = handler.create_account(account_data)
    db.session.add(account)
    db.session.commit()
    id_ = account.id

    # A valid update
    updated_data = attr.evolve(account_data, imap_username="******")
    account = handler.update_account(account, updated_data)
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    assert account.imap_username == "*****@*****.**"
def test_create_account(db):
    email = settings['settings']['email']
    imap_host = settings['settings']['imap_server_host']
    imap_port = settings['settings']['imap_server_port']
    smtp_host = settings['settings']['smtp_server_host']
    smtp_port = settings['settings']['smtp_server_port']

    handler = GenericAuthHandler(settings['provider'])

    # Create an authenticated account
    account = handler.create_account(email, settings['settings'])
    db.session.add(account)
    db.session.commit()
    # Verify its settings
    id_ = account.id
    account = db.session.query(Account).get(id_)
    assert account.imap_endpoint == (imap_host, imap_port)
    assert account.smtp_endpoint == (smtp_host, smtp_port)
def folder_sync_engine(db, monkeypatch):
    # super ugly, but I don't want to have to mock tons of stuff
    import inbox.mailsync.backends.imap.generic
    from inbox.mailsync.backends.imap.generic import FolderSyncEngine
    monkeypatch.setattr(inbox.mailsync.backends.imap.generic,
                        "_pool", lambda(account): True)
    # setup a dummy FolderSyncEngine - we only need to call a couple
    # methods.
    email = "*****@*****.**"
    account = GenericAuthHandler('fastmail').create_account(
        db.session, email, {"email": email, "password": "******"})
    db.session.add(account)
    db.session.commit()

    engine = None
    engine = FolderSyncEngine(account.id, "Inbox", 0,
                              email, "fastmail",
                              3200, None, 20, None)
    return engine
def local_smtp_account(db):
    from inbox.auth.generic import GenericAccountData, GenericAuthHandler

    handler = GenericAuthHandler()
    acc = handler.create_account(
        GenericAccountData(
            email="*****@*****.**",
            imap_username="******",
            smtp_username="******",
            imap_password="******",
            smtp_password="******",
            imap_server_host="imap-test.nylas.com",
            imap_server_port=143,
            smtp_server_host=SMTP_SERVER_HOST,
            smtp_server_port=postel.SMTP_OVER_SSL_TEST_PORT,
            sync_email=True,
        ))
    db.session.add(acc)
    db.session.commit()
    return acc
def test_double_auth(db, mock_imapclient):
    password = "******"
    email = account_data.email
    mock_imapclient._add_login(email, password)

    handler = GenericAuthHandler()

    # First authentication, using a valid password, succeeds.
    valid_settings = attr.evolve(account_data,
                                 imap_password=password,
                                 smtp_password=password)

    account = handler.create_account(valid_settings)
    assert handler.verify_account(account) is True

    db.session.add(account)
    db.session.commit()
    id_ = account.id
    account = db.session.query(Account).get(id_)
    assert account.email_address == email
    assert account.imap_username == email
    assert account.smtp_username == email
    assert account.imap_password == password
    assert account.smtp_password == password

    # Second auth using an invalid password should fail.
    invalid_settings = attr.evolve(account_data,
                                   imap_password="******")
    with pytest.raises(ValidationError):
        account = handler.update_account(account, invalid_settings)
        handler.verify_account(account)

    db.session.expire(account)

    # Ensure original account is unaffected
    account = db.session.query(Account).get(id_)
    assert account.email_address == email
    assert account.imap_username == email
    assert account.smtp_username == email
    assert account.imap_password == password
    assert account.smtp_password == password
def test_create_account(db):
    handler = GenericAuthHandler()

    # Create an authenticated account
    account = handler.create_account(account_data)
    db.session.add(account)
    db.session.commit()
    # Verify its settings
    id_ = account.id
    account = db.session.query(Account).get(id_)
    assert account.imap_endpoint == (
        account_data.imap_server_host,
        account_data.imap_server_port,
    )
    assert account.smtp_endpoint == (
        account_data.smtp_server_host,
        account_data.smtp_server_port,
    )
    # Ensure that the emailed events calendar was created
    assert account._emailed_events_calendar is not None
    assert account._emailed_events_calendar.name == "Emailed events"
def test_create_account(db):
    email = settings['settings']['email']
    imap_host = settings['settings']['imap_server_host']
    imap_port = settings['settings']['imap_server_port']
    smtp_host = settings['settings']['smtp_server_host']
    smtp_port = settings['settings']['smtp_server_port']

    handler = GenericAuthHandler(settings['provider'])

    # Create an authenticated account
    account = handler.create_account(email, settings['settings'])
    db.session.add(account)
    db.session.commit()
    # Verify its settings
    id_ = account.id
    account = db.session.query(Account).get(id_)
    assert account.imap_endpoint == (imap_host, imap_port)
    assert account.smtp_endpoint == (smtp_host, smtp_port)
    # Ensure that the emailed events calendar was created
    assert account._emailed_events_calendar is not None
    assert account._emailed_events_calendar.name == 'Emailed events'
def test_update_account_with_different_subdomain(db, monkeypatch):
    # Check that you can update the server endpoints for an account
    # provided that
    # 1/ they're on a subdomain of the same domain name.
    # 2/ they have the same IP address.
    #
    # To test this we use Microsoft's Office365 setup, which
    # has mail.office365.com and outlook.office365.com point to
    # the same address.
    updated_data = attr.evolve(
        account_data,
        imap_server_host="outlook.office365.com",
        smtp_server_host="outlook.office365.com",
    )

    handler = GenericAuthHandler()

    # Create an authenticated account
    account = handler.create_account(updated_data)
    db.session.add(account)
    db.session.commit()
    id_ = account.id

    def gethostbyname_patch(x):
        return "127.0.0.1"

    monkeypatch.setattr(socket, "gethostbyname", gethostbyname_patch)

    # A valid update
    updated_data = attr.evolve(
        account_data,
        imap_server_host="mail.office365.com",
        smtp_server_host="mail.office365.com",
    )
    account = handler.update_account(account, updated_data)
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    assert account._imap_server_host == "mail.office365.com"
    assert account._smtp_server_host == "mail.office365.com"
def test_update_account_with_different_subdomain(db, monkeypatch):
    # Check that you can update the server endpoints for an account
    # provided that
    # 1/ they're on a subdomain of the same domain name.
    # 2/ they have the same IP address.
    #
    # To test this we use Microsoft's Office365 setup, which
    # has mail.office365.com and outlook.office365.com point to
    # the same address.
    email = settings['settings']['email']
    settings['settings']['imap_server_host'] = 'outlook.office365.com'
    settings['settings']['smtp_server_host'] = 'outlook.office365.com'

    handler = GenericAuthHandler(settings['provider'])

    # Create an authenticated account
    account = handler.create_account(email, settings['settings'])
    db.session.add(account)
    db.session.commit()
    id_ = account.id

    def gethostbyname_patch(x):
        return "127.0.0.1"

    monkeypatch.setattr(socket, 'gethostbyname', gethostbyname_patch)

    # A valid update
    updated_settings = copy.deepcopy(settings)
    updated_settings['settings']['imap_server_host'] = 'mail.office365.com'
    updated_settings['settings']['smtp_server_host'] = 'mail.office365.com'
    updated_settings['settings']['name'] = 'Neu!'
    account = handler.update_account(account, updated_settings['settings'])
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    assert account.name == 'Neu!'
    assert account._imap_server_host == 'mail.office365.com'
    assert account._smtp_server_host == 'mail.office365.com'
Exemple #23
0
def create_account():
    """ Create a new account """
    data = request.get_json(force=True)

    if data["type"] == "generic":
        auth_handler = GenericAuthHandler()
        account_data = _get_account_data_for_generic_account(data)
    elif data["type"] == "gmail":
        auth_handler = GoogleAuthHandler()
        account_data = _get_account_data_for_google_account(data)
    elif data["type"] == "microsoft":
        auth_handler = MicrosoftAuthHandler()
        account_data = _get_account_data_for_microsoft_account(data)
    else:
        raise ValueError("Account type not supported.")

    with global_session_scope() as db_session:
        account = auth_handler.create_account(account_data)
        db_session.add(account)
        db_session.commit()

        encoder = APIEncoder()
        return encoder.jsonify(account.namespace)
def test_update_account(db):
    email = settings['settings']['email']
    imap_host = settings['settings']['imap_server_host']
    imap_port = settings['settings']['imap_server_port']
    smtp_host = settings['settings']['smtp_server_host']
    smtp_port = settings['settings']['smtp_server_port']

    handler = GenericAuthHandler(settings['provider'])

    # Create an authenticated account
    account = handler.create_account(email, settings['settings'])
    db.session.add(account)
    db.session.commit()
    id_ = account.id

    # A valid update
    updated_settings = copy.deepcopy(settings)
    updated_settings['settings']['name'] = 'Neu!'
    account = handler.update_account(account, updated_settings['settings'])
    db.session.add(account)
    db.session.commit()
    account = db.session.query(Account).get(id_)
    assert account.name == 'Neu!'

    # Invalid updates
    for (attr, value, updated_settings) in generate_endpoint_updates(settings):
        assert value in updated_settings['settings'].values()
        with pytest.raises(UserRecoverableConfigError):
            account = handler.update_account(account,
                                             updated_settings['settings'])
        db.session.add(account)
        db.session.commit()

        account = db.session.query(Account).get(id_)
        assert getattr(account, attr) != value
        assert account.imap_endpoint == (imap_host, imap_port)
        assert account.smtp_endpoint == (smtp_host, smtp_port)
Exemple #25
0
def yahoo_account(db):
    account = GenericAuthHandler().create_account(yahoo_account_data)
    db.session.add(account)
    db.session.commit()
    return account