Пример #1
0
    def setUp(self):
        super().setUp()

        # Enable retries, to make tests more robust
        Autodiscovery.INITIAL_RETRY_POLICY = FaultTolerance(max_wait=5)
        Autodiscovery.RETRY_WAIT = 5

        # Each test should start with a clean autodiscover cache
        clear_cache()

        # Some mocking helpers
        self.domain = get_domain(self.account.primary_smtp_address)
        self.dummy_ad_endpoint = 'https://%s/Autodiscover/Autodiscover.xml' % self.domain
        self.dummy_ews_endpoint = 'https://expr.example.com/EWS/Exchange.asmx'
        self.dummy_ad_response = b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <User>
            <AutoDiscoverSMTPAddress>%s</AutoDiscoverSMTPAddress>
        </User>
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>EXPR</Type>
                <EwsUrl>%s</EwsUrl>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>''' % (self.account.primary_smtp_address.encode(),
                      self.dummy_ews_endpoint.encode())
        self.dummy_ews_response = b'''\
    def test_autodiscover_path_1_5_valid_redirect_url_invalid_response(self, m):
        # Test steps 1 -> -> 5 -> Invalid response from redirect URL
        clear_cache()
        d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials)
        redirect_url = "https://httpbin.org/Autodiscover/Autodiscover.xml"
        m.post(self.dummy_ad_endpoint, status_code=200, content=self.redirect_url_xml(redirect_url))
        m.head(redirect_url, status_code=501)
        m.post(redirect_url, status_code=501)

        with self.assertRaises(AutoDiscoverFailed):
            # Fails in step 5 with invalid response
            ad_response, _ = d.discover()
Пример #3
0
 def test_failed_login_via_account(self):
     Autodiscovery.INITIAL_RETRY_POLICY = FaultTolerance(max_wait=10)
     clear_cache()
     with self.assertRaises(AutoDiscoverFailed):
         Account(
             primary_smtp_address=self.account.primary_smtp_address,
             access_type=DELEGATE,
             credentials=Credentials(
                 self.account.protocol.credentials.username,
                 'WRONG_PASSWORD'),
             autodiscover=True,
             locale='da_DK',
         )
    def test_autodiscover_path_1_5_invalid_redirect_url(self, m):
        # Test steps 1 -> -> 5 -> Invalid redirect URL
        clear_cache()
        d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials)
        m.post(
            self.dummy_ad_endpoint,
            status_code=200,
            content=self.redirect_url_xml(f"https://{get_random_hostname()}/EWS/Exchange.asmx"),
        )

        with self.assertRaises(AutoDiscoverFailed):
            # Fails in step 5 with invalid redirect URL
            ad_response, _ = d.discover()
Пример #5
0
 def test_autodiscover_empty_cache(self):
     # A live test of the entire process with an empty cache
     clear_cache()
     ad_response, protocol = exchangelib.autodiscover.discovery.discover(
         email=self.account.primary_smtp_address,
         credentials=self.account.protocol.credentials,
         retry_policy=self.retry_policy,
     )
     self.assertEqual(ad_response.autodiscover_smtp_address,
                      self.account.primary_smtp_address)
     self.assertEqual(protocol.service_endpoint.lower(),
                      self.account.protocol.service_endpoint.lower())
     self.assertEqual(protocol.version.build,
                      self.account.protocol.version.build)
Пример #6
0
 def test_autodiscover_direct_gc(self, m):
     # Test garbage collection of the autodiscover cache
     clear_cache()
     c = Credentials('leet_user', 'cannaguess')
     autodiscover_cache[('example.com', c)] = AutodiscoverProtocol(
         config=Configuration(
             service_endpoint=
             'https://example.com/Autodiscover/Autodiscover.xml',
             credentials=c,
             auth_type=NTLM,
             retry_policy=FailFast(),
         ))
     self.assertEqual(len(autodiscover_cache), 1)
     autodiscover_cache.__del__()
Пример #7
0
 def test_close_autodiscover_connections(self, m):
     # A live test that we can close TCP connections
     clear_cache()
     c = Credentials('leet_user', 'cannaguess')
     autodiscover_cache[('example.com', c)] = AutodiscoverProtocol(
         config=Configuration(
             service_endpoint=
             'https://example.com/Autodiscover/Autodiscover.xml',
             credentials=c,
             auth_type=NTLM,
             retry_policy=FailFast(),
         ))
     self.assertEqual(len(autodiscover_cache), 1)
     close_connections()
    def test_autodiscover_path_1_5_valid_redirect_url_valid_response(self, m):
        # Test steps 1 -> -> 5 -> Valid response from redirect URL -> 5
        clear_cache()
        d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials)
        redirect_hostname = "httpbin.org"
        redirect_url = f"https://{redirect_hostname}/Autodiscover/Autodiscover.xml"
        ews_url = f"https://{redirect_hostname}/EWS/Exchange.asmx"
        email = f"john@redirected.{redirect_hostname}"
        m.post(self.dummy_ad_endpoint, status_code=200, content=self.redirect_url_xml(redirect_url))
        m.head(redirect_url, status_code=200)
        m.post(redirect_url, status_code=200, content=self.settings_xml(email, ews_url))

        ad_response, _ = d.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address, email)
        self.assertEqual(ad_response.protocol.ews_url, ews_url)
    def test_autodiscover_path_1_2_3_invalid301_4(self, m):
        # Test steps 1 -> 2 -> 3 -> invalid 301 URL -> 4
        clear_cache()
        d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials)
        m.post(self.dummy_ad_endpoint, status_code=501)
        m.post(f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=501)
        m.get(
            f"http://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml",
            status_code=301,
            headers=dict(location="XXX"),
        )

        with self.assertRaises(AutoDiscoverFailed):
            # Fails in step 4 with invalid SRV entry
            ad_response, _ = d.discover()
 def test_autodiscover_path_1_2_5(self, m):
     # Test steps 1 -> 2 -> 5
     clear_cache()
     d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials)
     ews_url = f"https://xxx.{self.domain}/EWS/Exchange.asmx"
     email = f"xxxd@{self.domain}"
     m.post(self.dummy_ad_endpoint, status_code=501)
     m.post(
         f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml",
         status_code=200,
         content=self.settings_xml(email, ews_url),
     )
     ad_response, _ = d.discover()
     self.assertEqual(ad_response.autodiscover_smtp_address, email)
     self.assertEqual(ad_response.protocol.ews_url, ews_url)
    def setUp(self):
        super().setUp()

        # Enable retries, to make tests more robust
        Autodiscovery.INITIAL_RETRY_POLICY = FaultTolerance(max_wait=5)
        Autodiscovery.RETRY_WAIT = 5

        # Each test should start with a clean autodiscover cache
        clear_cache()

        # Some mocking helpers
        self.domain = get_domain(self.account.primary_smtp_address)
        self.dummy_ad_endpoint = f"https://{self.domain}/Autodiscover/Autodiscover.xml"
        self.dummy_ews_endpoint = "https://expr.example.com/EWS/Exchange.asmx"
        self.dummy_ad_response = self.settings_xml(self.account.primary_smtp_address, self.dummy_ews_endpoint)
Пример #12
0
 def test_autodiscover_from_account(self, m):
     # Test that autodiscovery via account creation works
     clear_cache()
     # Mock the default endpoint that we test in step 1 of autodiscovery
     m.post(self.dummy_ad_endpoint,
            status_code=200,
            content=self.dummy_ad_response)
     # Also mock the EWS URL. We try to guess its auth method as part of autodiscovery
     m.post(self.dummy_ews_endpoint,
            status_code=200,
            content=self.dummy_ews_response)
     self.assertEqual(len(autodiscover_cache), 0)
     account = Account(
         primary_smtp_address=self.account.primary_smtp_address,
         config=Configuration(
             credentials=self.account.protocol.credentials,
             retry_policy=self.retry_policy,
         ),
         autodiscover=True,
         locale='da_DK',
     )
     self.assertEqual(account.primary_smtp_address,
                      self.account.primary_smtp_address)
     self.assertEqual(account.protocol.service_endpoint.lower(),
                      self.dummy_ews_endpoint.lower())
     # Make sure cache is full
     self.assertEqual(len(autodiscover_cache), 1)
     self.assertTrue((account.domain, self.account.protocol.credentials,
                      True) in autodiscover_cache)
     # Test that autodiscover works with a full cache
     account = Account(
         primary_smtp_address=self.account.primary_smtp_address,
         config=Configuration(
             credentials=self.account.protocol.credentials,
             retry_policy=self.retry_policy,
         ),
         autodiscover=True,
         locale='da_DK',
     )
     self.assertEqual(account.primary_smtp_address,
                      self.account.primary_smtp_address)
     # Test cache manipulation
     key = (account.domain, self.account.protocol.credentials, True)
     self.assertTrue(key in autodiscover_cache)
     del autodiscover_cache[key]
     self.assertFalse(key in autodiscover_cache)
Пример #13
0
 def test_magic(self, m):
     # Just test we don't fail when calling repr() and str(). Insert a dummy cache entry for testing
     clear_cache()
     c = Credentials('leet_user', 'cannaguess')
     autodiscover_cache[('example.com', c)] = AutodiscoverProtocol(
         config=Configuration(
             service_endpoint=
             'https://example.com/Autodiscover/Autodiscover.xml',
             credentials=c,
             auth_type=NTLM,
             retry_policy=FailFast(),
         ))
     self.assertEqual(len(autodiscover_cache), 1)
     str(autodiscover_cache)
     repr(autodiscover_cache)
     for protocol in autodiscover_cache._protocols.values():
         str(protocol)
         repr(protocol)
Пример #14
0
    def test_autodiscover_redirect(self, m):
        # Test various aspects of autodiscover redirection. Mock all HTTP responses because we can't force a live server
        # to send us into the correct code paths.
        # Mock the default endpoint that we test in step 1 of autodiscovery
        m.post(self.dummy_ad_endpoint,
               status_code=200,
               content=self.dummy_ad_response)
        # Also mock the EWS URL. We try to guess its auth method as part of autodiscovery
        m.post(self.dummy_ews_endpoint, status_code=200)
        discovery = Autodiscovery(
            email=self.account.primary_smtp_address,
            credentials=self.account.protocol.credentials,
            retry_policy=self.retry_policy,
        )
        discovery.discover()

        # Make sure we discover a different return address
        m.post(self.dummy_ad_endpoint,
               status_code=200,
               content=b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <User>
            <AutoDiscoverSMTPAddress>[email protected]</AutoDiscoverSMTPAddress>
        </User>
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>EXPR</Type>
                <EwsUrl>https://expr.example.com/EWS/Exchange.asmx</EwsUrl>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>''')
        # Also mock the EWS URL. We try to guess its auth method as part of autodiscovery
        m.post('https://expr.example.com/EWS/Exchange.asmx', status_code=200)
        ad_response, p = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address,
                         '*****@*****.**')

        # Make sure we discover an address redirect to the same domain. We have to mock the same URL with two different
        # responses. We do that with a response list.
        redirect_addr_content = b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <Action>redirectAddr</Action>
            <RedirectAddr>redirect_me@%s</RedirectAddr>
        </Account>
    </Response>
</Autodiscover>''' % self.domain.encode()
        settings_content = b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <User>
            <AutoDiscoverSMTPAddress>redirected@%s</AutoDiscoverSMTPAddress>
        </User>
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>EXPR</Type>
                <EwsUrl>https://redirected.%s/EWS/Exchange.asmx</EwsUrl>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>''' % (self.domain.encode(), self.domain.encode())
        # Also mock the EWS URL. We try to guess its auth method as part of autodiscovery
        m.post('https://redirected.%s/EWS/Exchange.asmx' % self.domain,
               status_code=200)

        m.post(self.dummy_ad_endpoint, [
            dict(status_code=200, content=redirect_addr_content),
            dict(status_code=200, content=settings_content),
        ])
        ad_response, p = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address,
                         'redirected@%s' % self.domain)
        self.assertEqual(
            ad_response.ews_url,
            'https://redirected.%s/EWS/Exchange.asmx' % self.domain)

        # Test that we catch circular redirects on the same domain with a primed cache. Just mock the endpoint to
        # return the same redirect response on every request.
        self.assertEqual(len(autodiscover_cache), 1)
        m.post(self.dummy_ad_endpoint,
               status_code=200,
               content=b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <Action>redirectAddr</Action>
            <RedirectAddr>foo@%s</RedirectAddr>
        </Account>
    </Response>
</Autodiscover>''' % self.domain.encode())
        self.assertEqual(len(autodiscover_cache), 1)
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discovery.discover()

        # Test that we also catch circular redirects when cache is empty
        clear_cache()
        self.assertEqual(len(autodiscover_cache), 0)
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discovery.discover()

        # Test that we can handle being asked to redirect to an address on a different domain
        m.post(self.dummy_ad_endpoint,
               status_code=200,
               content=b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <Account>
            <Action>redirectAddr</Action>
            <RedirectAddr>[email protected]</RedirectAddr>
        </Account>
    </Response>
</Autodiscover>''')
        m.post('https://example.com/Autodiscover/Autodiscover.xml',
               status_code=200,
               content=b'''\
<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
    <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
        <User>
            <AutoDiscoverSMTPAddress>[email protected]</AutoDiscoverSMTPAddress>
        </User>
        <Account>
            <AccountType>email</AccountType>
            <Action>settings</Action>
            <Protocol>
                <Type>EXPR</Type>
                <EwsUrl>https://redirected.example.com/EWS/Exchange.asmx</EwsUrl>
            </Protocol>
        </Account>
    </Response>
</Autodiscover>''')
        # Also mock the EWS URL. We try to guess its auth method as part of autodiscovery
        m.post('https://redirected.example.com/EWS/Exchange.asmx',
               status_code=200)
        ad_response, p = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address,
                         '*****@*****.**')
        self.assertEqual(ad_response.ews_url,
                         'https://redirected.example.com/EWS/Exchange.asmx')
    def test_autodiscover_redirect(self, m):
        # Test various aspects of autodiscover redirection. Mock all HTTP responses because we can't force a live server
        # to send us into the correct code paths.
        # Mock the default endpoint that we test in step 1 of autodiscovery
        m.post(self.dummy_ad_endpoint, status_code=200, content=self.dummy_ad_response)
        discovery = Autodiscovery(
            email=self.account.primary_smtp_address,
            credentials=self.account.protocol.credentials,
        )
        discovery.discover()

        # Make sure we discover a different return address
        m.post(
            self.dummy_ad_endpoint,
            status_code=200,
            content=self.settings_xml("*****@*****.**", "https://expr.example.com/EWS/Exchange.asmx"),
        )
        ad_response, _ = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address, "*****@*****.**")

        # Make sure we discover an address redirect to the same domain. We have to mock the same URL with two different
        # responses. We do that with a response list.
        m.post(
            self.dummy_ad_endpoint,
            [
                dict(status_code=200, content=self.redirect_address_xml(f"redirect_me@{self.domain}")),
                dict(
                    status_code=200,
                    content=self.settings_xml(
                        f"redirected@{self.domain}", f"https://redirected.{self.domain}/EWS/Exchange.asmx"
                    ),
                ),
            ],
        )
        ad_response, _ = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address, f"redirected@{self.domain}")
        self.assertEqual(ad_response.protocol.ews_url, f"https://redirected.{self.domain}/EWS/Exchange.asmx")

        # Test that we catch circular redirects on the same domain with a primed cache. Just mock the endpoint to
        # return the same redirect response on every request.
        self.assertEqual(len(autodiscover_cache), 1)
        m.post(self.dummy_ad_endpoint, status_code=200, content=self.redirect_address_xml(f"foo@{self.domain}"))
        self.assertEqual(len(autodiscover_cache), 1)
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discovery.discover()

        # Test that we also catch circular redirects when cache is empty
        clear_cache()
        self.assertEqual(len(autodiscover_cache), 0)
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discovery.discover()

        # Test that we can handle being asked to redirect to an address on a different domain
        # Don't use example.com to redirect - it does not resolve or answer on all ISPs
        ews_hostname = "httpbin.org"
        redirect_email = f"john@redirected.{ews_hostname}"
        ews_url = f"https://{ews_hostname}/EWS/Exchange.asmx"
        m.post(self.dummy_ad_endpoint, status_code=200, content=self.redirect_address_xml(f"john@{ews_hostname}"))
        m.post(
            f"https://{ews_hostname}/Autodiscover/Autodiscover.xml",
            status_code=200,
            content=self.settings_xml(redirect_email, ews_url),
        )
        ad_response, _ = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address, redirect_email)
        self.assertEqual(ad_response.protocol.ews_url, ews_url)

        # Test redirect via HTTP 301
        clear_cache()
        redirect_url = f"https://{ews_hostname}/OtherPath/Autodiscover.xml"
        redirect_email = f"john@otherpath.{ews_hostname}"
        ews_url = f"https://xxx.{ews_hostname}/EWS/Exchange.asmx"
        discovery.email = self.account.primary_smtp_address
        m.post(self.dummy_ad_endpoint, status_code=301, headers=dict(location=redirect_url))
        m.post(redirect_url, status_code=200, content=self.settings_xml(redirect_email, ews_url))
        m.head(redirect_url, status_code=200)
        ad_response, _ = discovery.discover()
        self.assertEqual(ad_response.autodiscover_smtp_address, redirect_email)
        self.assertEqual(ad_response.protocol.ews_url, ews_url)