예제 #1
0
 def test_close_autodiscover_connections(self):
     discover(
         email=self.account.primary_smtp_address,
         credentials=self.account.protocol.credentials,
         retry_policy=self.retry_policy,
     )
     close_connections()
예제 #2
0
 def test_autodiscover_direct_gc(self):
     # This is what Python garbage collection does
     from exchangelib.autodiscover import _autodiscover_cache
     discover(
         email=self.account.primary_smtp_address,
         credentials=self.account.protocol.credentials,
         retry_policy=self.retry_policy,
     )
     _autodiscover_cache.__del__()
예제 #3
0
 def test_magic(self):
     # Just test we don't fail
     from exchangelib.autodiscover import _autodiscover_cache
     discover(email=self.account.primary_smtp_address,
              credentials=self.account.protocol.credentials)
     str(_autodiscover_cache)
     repr(_autodiscover_cache)
     for protocol in _autodiscover_cache._protocols.values():
         str(protocol)
         repr(protocol)
예제 #4
0
 def test_autodiscover_failure(self):
     # Empty the cache
     from exchangelib.autodiscover import _autodiscover_cache
     _autodiscover_cache.clear()
     with self.assertRaises(ErrorNonExistentMailbox):
         # Test that error is raised with an empty cache
         discover(email='XXX.' + self.account.primary_smtp_address,
                  credentials=self.account.protocol.credentials)
     with self.assertRaises(ErrorNonExistentMailbox):
         # Test that error is raised with a full cache
         discover(email='XXX.' + self.account.primary_smtp_address,
                  credentials=self.account.protocol.credentials)
예제 #5
0
 def test_autodiscover(self):
     primary_smtp_address, protocol = discover(
         email=self.account.primary_smtp_address,
         credentials=self.account.protocol.credentials)
     self.assertEqual(primary_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_cache(self, m):
        # Empty the cache
        from exchangelib.autodiscover import _autodiscover_cache
        _autodiscover_cache.clear()
        cache_key = (self.account.domain, self.account.protocol.credentials)
        # Not cached
        self.assertNotIn(cache_key, _autodiscover_cache)
        discover(email=self.account.primary_smtp_address,
                 credentials=self.account.protocol.credentials)
        # Now it's cached
        self.assertIn(cache_key, _autodiscover_cache)
        # Make sure the cache can be looked by value, not by id(). This is important for multi-threading/processing
        self.assertIn(
            (self.account.primary_smtp_address.split('@')[1],
             Credentials(self.account.protocol.credentials.username,
                         self.account.protocol.credentials.password), True),
            _autodiscover_cache)
        # Poison the cache. discover() must survive and rebuild the cache
        _autodiscover_cache[cache_key] = AutodiscoverProtocol(
            config=Configuration(
                service_endpoint='https://example.com/blackhole.asmx',
                credentials=Credentials('leet_user', 'cannaguess'),
                auth_type=NTLM,
                retry_policy=FailFast(),
            ))
        m.post('https://example.com/blackhole.asmx', status_code=404)
        discover(email=self.account.primary_smtp_address,
                 credentials=self.account.protocol.credentials)
        self.assertIn(cache_key, _autodiscover_cache)

        # Make sure that the cache is actually used on the second call to discover()
        _orig = exchangelib.autodiscover._try_autodiscover

        def _mock(*args, **kwargs):
            raise NotImplementedError()

        exchangelib.autodiscover._try_autodiscover = _mock
        discover(email=self.account.primary_smtp_address,
                 credentials=self.account.protocol.credentials)
        # Fake that another thread added the cache entry into the persistent storage but we don't have it in our
        # in-memory cache. The cache should work anyway.
        _autodiscover_cache._protocols.clear()
        discover(email=self.account.primary_smtp_address,
                 credentials=self.account.protocol.credentials)
        exchangelib.autodiscover._try_autodiscover = _orig
        # Make sure we can delete cache entries even though we don't have it in our in-memory cache
        _autodiscover_cache._protocols.clear()
        del _autodiscover_cache[cache_key]
        # This should also work if the cache does not contain the entry anymore
        del _autodiscover_cache[cache_key]
예제 #7
0
def autodiscover(verbose):
    """
        Authenticate and go through autodiscover.
    """

    try:
        tbestate.validate(['username', 'password'])
        credentials = Credentials(tbestate.username, tbestate.password)

        if verbose:
            logging.basicConfig(level=logging.DEBUG, handlers=[PrettyXmlHandler()])

        primary_address, protocol = discover(tbestate.username, credentials=credentials)

        click.secho(f'Autodiscover results:', bold=True, fg='yellow')
        click.secho(f'{primary_address.user}', fg='bright_green')
        click.secho(f'{protocol}', fg='bright_green')
    except exchangelib.errors.AutoDiscoverFailed:
        click.secho(f'Autodiscover failed, try with -v for more information:', bold=True, fg='red')
예제 #8
0
    def test_disable_ssl_verification(self):
        if not self.verify_ssl:
            # We can only run this test if we haven't already disabled TLS
            raise self.skipTest('TLS verification already disabled')
        import exchangelib.autodiscover

        default_adapter_cls = BaseProtocol.HTTP_ADAPTER_CLS

        # A normal discover should succeed
        exchangelib.autodiscover._autodiscover_cache.clear()
        discover(
            email=self.account.primary_smtp_address,
            credentials=self.account.protocol.credentials,
            retry_policy=self.retry_policy,
        )

        # Smash TLS verification using an untrusted certificate
        with tempfile.NamedTemporaryFile() as f:
            f.write(b'''\
 -----BEGIN CERTIFICATE-----
MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD
VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs
MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV
BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3
DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy
MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU
MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh
cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ
bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ
GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6
L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg
2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw
AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX
wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n
AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME
GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5
U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm
T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD
1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I
p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO
r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0
-----END CERTIFICATE-----''')
            try:
                os.environ['REQUESTS_CA_BUNDLE'] = f.name

                # Now discover should fail. TLS errors mean we exhaust all autodiscover attempts
                with self.assertRaises(AutoDiscoverFailed):
                    exchangelib.autodiscover._autodiscover_cache.clear()
                    discover(
                        email=self.account.primary_smtp_address,
                        credentials=self.account.protocol.credentials,
                        retry_policy=self.retry_policy,
                    )

                # Disable insecure TLS warnings
                with warnings.catch_warnings():
                    warnings.simplefilter("ignore")
                    # Make sure we can survive TLS validation errors when using the custom adapter
                    exchangelib.autodiscover._autodiscover_cache.clear()
                    BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter
                    discover(
                        email=self.account.primary_smtp_address,
                        credentials=self.account.protocol.credentials,
                        retry_policy=self.retry_policy,
                    )

                    # Test that the custom adapter also works when validation is OK again
                    del os.environ['REQUESTS_CA_BUNDLE']
                    exchangelib.autodiscover._autodiscover_cache.clear()
                    discover(
                        email=self.account.primary_smtp_address,
                        credentials=self.account.protocol.credentials,
                        retry_policy=self.retry_policy,
                    )
            finally:
                # Reset environment
                os.environ.pop('REQUESTS_CA_BUNDLE',
                               None)  # May already have been deleted
                exchangelib.autodiscover._autodiscover_cache.clear()
                BaseProtocol.HTTP_ADAPTER_CLS = default_adapter_cls
예제 #9
0
    def test_autodiscover_redirect(self):
        # Prime the cache
        email, p = discover(
            email=self.account.primary_smtp_address,
            credentials=self.account.protocol.credentials,
            retry_policy=self.retry_policy,
        )

        _orig = exchangelib.autodiscover._autodiscover_quick

        # Test that we can get another address back than the address we're looking up
        def _mock1(*args, **kwargs):
            return '*****@*****.**', p

        exchangelib.autodiscover._autodiscover_quick = _mock1
        test_email, p = discover(
            email=self.account.primary_smtp_address,
            credentials=self.account.protocol.credentials,
            retry_policy=self.retry_policy,
        )

        self.assertEqual(test_email, '*****@*****.**')

        # Test that we can survive being asked to lookup with another address
        def _mock2(*args, **kwargs):
            email = kwargs['email']
            if email == 'xxxxxx@%s' % self.account.domain:
                raise ErrorNonExistentMailbox(email)
            raise AutoDiscoverRedirect(redirect_email='xxxxxx@' +
                                       self.account.domain)

        exchangelib.autodiscover._autodiscover_quick = _mock2
        with self.assertRaises(ErrorNonExistentMailbox):
            discover(
                email=self.account.primary_smtp_address,
                credentials=self.account.protocol.credentials,
                retry_policy=self.retry_policy,
            )

        # Test that we catch circular redirects
        def _mock3(*args, **kwargs):
            raise AutoDiscoverRedirect(
                redirect_email=self.account.primary_smtp_address)

        exchangelib.autodiscover._autodiscover_quick = _mock3
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discover(
                email=self.account.primary_smtp_address,
                credentials=self.account.protocol.credentials,
                retry_policy=self.retry_policy,
            )
        exchangelib.autodiscover._autodiscover_quick = _orig

        # Test that we catch circular redirects when cache is empty. This is a different code path
        _orig = exchangelib.autodiscover._try_autodiscover

        def _mock4(*args, **kwargs):
            raise AutoDiscoverRedirect(
                redirect_email=self.account.primary_smtp_address)

        exchangelib.autodiscover._try_autodiscover = _mock4
        exchangelib.autodiscover._autodiscover_cache.clear()
        with self.assertRaises(AutoDiscoverCircularRedirect):
            discover(
                email=self.account.primary_smtp_address,
                credentials=self.account.protocol.credentials,
                retry_policy=self.retry_policy,
            )
        exchangelib.autodiscover._try_autodiscover = _orig

        # Test that we can survive being asked to lookup with another address, when cache is empty
        def _mock5(*args, **kwargs):
            email = kwargs['email']
            if email == 'xxxxxx@%s' % self.account.domain:
                raise ErrorNonExistentMailbox(email)
            raise AutoDiscoverRedirect(redirect_email='xxxxxx@' +
                                       self.account.domain)

        exchangelib.autodiscover._try_autodiscover = _mock5
        exchangelib.autodiscover._autodiscover_cache.clear()
        with self.assertRaises(ErrorNonExistentMailbox):
            discover(
                email=self.account.primary_smtp_address,
                credentials=self.account.protocol.credentials,
                retry_policy=self.retry_policy,
            )
        exchangelib.autodiscover._try_autodiscover = _orig
예제 #10
0
 def test_autodiscover_gc(self):
     # This is what Python garbage collection does
     from exchangelib.autodiscover import _autodiscover_cache
     discover(email=self.account.primary_smtp_address,
              credentials=self.account.protocol.credentials)
     del _autodiscover_cache