Пример #1
0
 def test_versioned_choice(self):
     field = ChoiceField('foo', field_uri='bar', choices={
         Choice('c1'), Choice('c2', supported_from=EXCHANGE_2010)
     })
     with self.assertRaises(ValueError):
         field.clean('XXX')  # Value must be a valid choice
     field.clean('c2', version=None)
     with self.assertRaises(InvalidChoiceForVersion):
         field.clean('c2', version=Version(EXCHANGE_2007))
     field.clean('c2', version=Version(EXCHANGE_2010))
     field.clean('c2', version=Version(EXCHANGE_2013))
Пример #2
0
    def test_q(self):
        version = Version(build=EXCHANGE_2007)
        account = mock_account(version=version, protocol=mock_protocol(version=version, service_endpoint='example.com'))
        root = Root(account=account)
        tz = zoneinfo.ZoneInfo('Europe/Copenhagen')
        start = datetime.datetime(2020, 9, 26, 8, 0, 0, tzinfo=tz)
        end = datetime.datetime(2020, 9, 26, 11, 0, 0, tzinfo=tz)
        result = '''\
<m:Restriction xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
    <t:And xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
        <t:Or>
            <t:Contains ContainmentMode="Substring" ContainmentComparison="Exact">
                <t:FieldURI FieldURI="item:Categories"/>
                <t:Constant Value="FOO"/>
            </t:Contains>
            <t:Contains ContainmentMode="Substring" ContainmentComparison="Exact">
                <t:FieldURI FieldURI="item:Categories"/>
                <t:Constant Value="BAR"/>
            </t:Contains>
        </t:Or>
        <t:IsGreaterThan>
            <t:FieldURI FieldURI="calendar:End"/>
            <t:FieldURIOrConstant>
                <t:Constant Value="2020-09-26T08:00:00+02:00"/>
            </t:FieldURIOrConstant>
        </t:IsGreaterThan>
        <t:IsLessThan>
            <t:FieldURI FieldURI="calendar:Start"/>
            <t:FieldURIOrConstant>
                <t:Constant Value="2020-09-26T11:00:00+02:00"/>
            </t:FieldURIOrConstant>
        </t:IsLessThan>
    </t:And>
</m:Restriction>'''
        q = Q(Q(categories__contains='FOO') | Q(categories__contains='BAR'), start__lt=end, end__gt=start)
        r = Restriction(q, folders=[Calendar(root=root)], applies_to=Restriction.ITEMS)
        self.assertEqual(str(r), ''.join(s.lstrip() for s in result.split('\n')))
        # Test empty Q
        q = Q()
        self.assertEqual(q.to_xml(folders=[Calendar()], version=version, applies_to=Restriction.ITEMS), None)
        with self.assertRaises(ValueError):
            Restriction(q, folders=[Calendar(root=root)], applies_to=Restriction.ITEMS)
        # Test validation
        with self.assertRaises(ValueError):
            Q(datetime_created__range=(1,))  # Must have exactly 2 args
        with self.assertRaises(ValueError):
            Q(datetime_created__range=(1, 2, 3))  # Must have exactly 2 args
        with self.assertRaises(TypeError):
            Q(datetime_created=Build(15, 1)).clean(version=Version(build=EXCHANGE_2007))  # Must be serializable
        with self.assertRaises(ValueError):
            # Must be a timezone-aware datetime
            Q(datetime_created=datetime.datetime(2017, 1, 1)).clean(version=Version(build=EXCHANGE_2007))
        with self.assertRaises(ValueError):
            Q(categories__contains=[[1, 2], [3, 4]]).clean(version=Version(build=EXCHANGE_2007))  # Must be single value
 def test_versioned_choice(self):
     field = ChoiceField(
         "foo",
         field_uri="bar",
         choices={Choice("c1"),
                  Choice("c2", supported_from=EXCHANGE_2010)})
     with self.assertRaises(ValueError):
         field.clean("XXX")  # Value must be a valid choice
     field.clean("c2", version=None)
     with self.assertRaises(InvalidChoiceForVersion):
         field.clean("c2", version=Version(EXCHANGE_2007))
     field.clean("c2", version=Version(EXCHANGE_2010))
     field.clean("c2", version=Version(EXCHANGE_2013))
Пример #4
0
 def test_find_folders_compat(self):
     account = self.get_account()
     coll = FolderCollection(account=account, folders=[account.root])
     account.version = Version(EXCHANGE_2007)  # Need to set it after the last auto-config of version
     with self.assertRaises(NotImplementedError) as e:
         list(coll.find_folders(offset=1))
     self.assertEqual(e.exception.args[0], "'offset' is only supported for Exchange 2010 servers and later")
Пример #5
0
    def test_invalid_field(self):
        test_field = Item.get_field_by_fieldname(fieldname='text_body')
        self.assertIsInstance(test_field, TextField)
        self.assertEqual(test_field.name, 'text_body')

        with self.assertRaises(InvalidField):
            Item.get_field_by_fieldname(fieldname='xxx')

        Item.validate_field(field=test_field, version=Version(build=EXCHANGE_2013))
        with self.assertRaises(InvalidFieldForVersion) as e:
            Item.validate_field(field=test_field, version=Version(build=EXCHANGE_2010))
        self.assertEqual(
            e.exception.args[0],
            "Field 'text_body' is not supported on server version Build=14.0.0.0, API=Exchange2010, Fullname=Microsoft "
            "Exchange Server 2010 (supported from: 15.0.0.0, deprecated from: None)"
        )
Пример #6
0
 def test_decrease_poolsize(self):
     # Test increasing and decreasing the pool size
     max_connections = 3
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(
             8)),
         auth_type=NTLM,
         version=Version(Build(15, 1)),
         retry_policy=FailFast(),
         max_connections=max_connections,
     ))
     self.assertEqual(protocol._session_pool.qsize(), 0)
     self.assertEqual(protocol.session_pool_size, 0)
     protocol.increase_poolsize()
     protocol.increase_poolsize()
     protocol.increase_poolsize()
     with self.assertRaises(SessionPoolMaxSizeReached):
         protocol.increase_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), max_connections)
     self.assertEqual(protocol.session_pool_size, max_connections)
     protocol.decrease_poolsize()
     protocol.decrease_poolsize()
     with self.assertRaises(SessionPoolMinSizeReached):
         protocol.decrease_poolsize()
     self.assertEqual(protocol._session_pool.qsize(), 1)
Пример #7
0
    def test_protocol_instance_caching(self, m):
        # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials)
        user, password = get_random_string(8), get_random_string(8)
        config = Configuration(service_endpoint='https://example.com/Foo.asmx',
                               credentials=Credentials(user, password),
                               auth_type=NTLM,
                               version=Version(Build(15, 1)),
                               retry_policy=FailFast())

        # Test CachingProtocol.__getitem__
        with self.assertRaises(KeyError):
            _ = Protocol[config]
        base_p = Protocol(config=config)
        self.assertEqual(base_p, Protocol[config][0])

        # Make sure we always return the same item when creating a Protocol with the same endpoint and creds
        for _ in range(10):
            p = Protocol(config=config)
            self.assertEqual(base_p, p)
            self.assertEqual(id(base_p), id(p))
            self.assertEqual(hash(base_p), hash(p))
            self.assertEqual(id(base_p._session_pool), id(p._session_pool))

        # Test CachingProtocol.__delitem__
        del Protocol[config]
        with self.assertRaises(KeyError):
            _ = Protocol[config]

        # Make sure we get a fresh instance after we cleared the cache
        p = Protocol(config=config)
        self.assertNotEqual(base_p, p)

        Protocol.clear_cache()
Пример #8
0
 def test_invalid_version_args(self):
     with self.assertRaises(TypeError) as e:
         Version(build="XXX")
     self.assertEqual(
         e.exception.args[0],
         "'build' 'XXX' must be of type <class 'exchangelib.version.Build'>"
     )
     with self.assertRaises(TypeError) as e:
         Version(build="XXX", api_version="XXX")
     self.assertEqual(
         e.exception.args[0],
         "'build' 'XXX' must be of type <class 'exchangelib.version.Build'>"
     )
     with self.assertRaises(TypeError) as e:
         Version(build=Build(15, 1, 2, 3), api_version=999)
     self.assertEqual(e.exception.args[0],
                      "'api_version' 999 must be of type <class 'str'>")
Пример #9
0
 def test_session(self, m):
     protocol = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(8)),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     session = protocol.create_session()
     new_session = protocol.renew_session(session)
     self.assertNotEqual(id(session), id(new_session))
Пример #10
0
    def test_protocol_instance_caching(self, m):
        # Verify that we get the same Protocol instance for the same combination of (endpoint, credentials)
        user, password = get_random_string(8), get_random_string(8)
        base_p = Protocol(config=Configuration(
            service_endpoint='https://example.com/Foo.asmx', credentials=Credentials(user, password),
            auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
        ))

        for _ in range(10):
            p = Protocol(config=Configuration(
                service_endpoint='https://example.com/Foo.asmx', credentials=Credentials(user, password),
                auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
            ))
            self.assertEqual(base_p, p)
            self.assertEqual(id(base_p), id(p))
            self.assertEqual(hash(base_p), hash(p))
            self.assertEqual(id(base_p._session_pool), id(p._session_pool))
        Protocol.clear_cache()
Пример #11
0
 def test_hardcode_all(self, m):
     # Test that we can hardcode everything without having a working server. This is useful if neither tasting or
     # guessing missing values works.
     Configuration(
         server="example.com",
         credentials=Credentials(get_random_string(8),
                                 get_random_string(8)),
         auth_type=NTLM,
         version=Version(build=Build(15, 1, 2, 3), api_version="foo"),
     )
Пример #12
0
 def test_send_pre_2013(self):
     # Test < Exchange 2013 fallback for attachments and send-only mode
     item = self.get_test_item()
     item.account = self.get_account()
     item.folder = item.account.inbox
     item.attach(
         FileAttachment(name="file_attachment", content=b"file_attachment"))
     item.account.version = Version(EXCHANGE_2010_SP2)
     item.send(save_copy=False)
     self.assertIsNone(item.id)
     self.assertIsNone(item.changekey)
Пример #13
0
 def test_magic(self):
     config = Configuration(
         server="example.com",
         credentials=Credentials(get_random_string(8),
                                 get_random_string(8)),
         auth_type=NTLM,
         version=Version(build=Build(15, 1, 2, 3), api_version="foo"),
     )
     # Just test that these work
     str(config)
     repr(config)
Пример #14
0
 def test_pickle(self):
     # Test that we can pickle, repr and str Protocols
     o = Protocol(config=Configuration(
         service_endpoint='https://example.com/Foo.asmx',
         credentials=Credentials(get_random_string(8), get_random_string(8)),
         auth_type=NTLM, version=Version(Build(15, 1)), retry_policy=FailFast()
     ))
     pickled_o = pickle.dumps(o)
     unpickled_o = pickle.loads(pickled_o)
     self.assertIsInstance(unpickled_o, type(o))
     self.assertEqual(repr(o), repr(unpickled_o))
     self.assertEqual(str(o), str(unpickled_o))
    def test_single_field_indexed_element(self):
        # A SingleFieldIndexedElement must have only one field defined
        class TestField(SingleFieldIndexedElement):
            a = CharField()
            b = CharField()

        with self.assertRaises(ValueError) as e:
            TestField.value_field(version=Version(EXCHANGE_2013))
        self.assertEqual(
            e.exception.args[0],
            "Class <class 'tests.test_field.FieldTest.test_single_field_indexed_element.<locals>.TestField'> "
            "must have only one value field (found ('a', 'b'))",
        )
Пример #16
0
 def get_test_protocol(**kwargs):
     return Protocol(config=Configuration(
         server=kwargs.get("server"),
         service_endpoint=kwargs.get(
             "service_endpoint",
             f"https://{get_random_hostname()}/Foo.asmx"),
         credentials=kwargs.get(
             "credentials",
             Credentials(get_random_string(8), get_random_string(8))),
         auth_type=kwargs.get("auth_type", NTLM),
         version=kwargs.get("version", Version(Build(15, 1))),
         retry_policy=kwargs.get("retry_policy", FailFast()),
         max_connections=kwargs.get("max_connections"),
     ))
Пример #17
0
    def test_close(self):
        # Don't use example.com here - it does not resolve or answer on all ISPs
        proc = psutil.Process()
        ip_addresses = {
            info[4][0]
            for info in
            socket.getaddrinfo('httpbin.org', 80, socket.AF_INET,
                               socket.SOCK_DGRAM, socket.IPPROTO_IP)
        }

        def conn_count():
            return len(
                [p for p in proc.connections() if p.raddr[0] in ip_addresses])

        self.assertGreater(len(ip_addresses), 0)
        protocol = Protocol(config=Configuration(
            service_endpoint='http://httpbin.org',
            credentials=Credentials(get_random_string(8), get_random_string(
                8)),
            auth_type=NOAUTH,
            version=Version(Build(15, 1)),
            retry_policy=FailFast(),
            max_connections=3))
        # Merely getting a session should not create conections
        session = protocol.get_session()
        self.assertEqual(conn_count(), 0)
        # Open one URL - we have 1 connection
        session.get('http://httpbin.org')
        self.assertEqual(conn_count(), 1)
        # Open the same URL - we should still have 1 connection
        session.get('http://httpbin.org')
        self.assertEqual(conn_count(), 1)

        # Open some more connections
        s2 = protocol.get_session()
        s2.get('http://httpbin.org')
        s3 = protocol.get_session()
        s3.get('http://httpbin.org')
        self.assertEqual(conn_count(), 3)

        # Releasing the sessions does not close the connections
        protocol.release_session(session)
        protocol.release_session(s2)
        protocol.release_session(s3)
        self.assertEqual(conn_count(), 3)

        # But closing explicitly does
        protocol.close()
        self.assertEqual(conn_count(), 0)
Пример #18
0
    def test_q_inversion(self):
        version = Version(build=EXCHANGE_2007)
        account = mock_account(version=version,
                               protocol=mock_protocol(
                                   version=version,
                                   service_endpoint='example.com'))
        root = Root(account=account)
        self.assertEqual((~Q(foo=5)).op, Q.NE)
        self.assertEqual((~Q(foo__not=5)).op, Q.EQ)
        self.assertEqual((~Q(foo__lt=5)).op, Q.GTE)
        self.assertEqual((~Q(foo__lte=5)).op, Q.GT)
        self.assertEqual((~Q(foo__gt=5)).op, Q.LTE)
        self.assertEqual((~Q(foo__gte=5)).op, Q.LT)
        # Test not not Q on a non-leaf
        self.assertEqual(Q(foo__contains=('bar', 'baz')).conn_type, Q.AND)
        self.assertEqual((~Q(foo__contains=('bar', 'baz'))).conn_type, Q.NOT)
        self.assertEqual((~~Q(foo__contains=('bar', 'baz'))).conn_type, Q.AND)
        self.assertEqual(Q(foo__contains=('bar', 'baz')),
                         ~~Q(foo__contains=('bar', 'baz')))
        # Test generated XML of 'Not' statement when there is only one child. Skip 't:And' between 't:Not' and 't:Or'.
        result = '''\
<m:Restriction xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
    <t:Not xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
        <t:Or>
            <t:IsEqualTo>
                <t:FieldURI FieldURI="item:Subject"/>
                <t:FieldURIOrConstant>
                    <t:Constant Value="bar"/>
                </t:FieldURIOrConstant>
            </t:IsEqualTo>
            <t:IsEqualTo>
                <t:FieldURI FieldURI="item:Subject"/>
                <t:FieldURIOrConstant>
                    <t:Constant Value="baz"/>
                </t:FieldURIOrConstant>
            </t:IsEqualTo>
        </t:Or>
    </t:Not>
</m:Restriction>'''
        q = ~(Q(subject='bar') | Q(subject='baz'))
        self.assertEqual(
            xml_to_str(
                q.to_xml(folders=[Calendar(root=root)],
                         version=version,
                         applies_to=Restriction.ITEMS)),
            ''.join(s.lstrip() for s in result.split('\n')))
 def test_autodiscover_from_account(self, m):
     # Test that autodiscovery via account creation works
     # 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)
     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,
             version=Version(build=EXCHANGE_2013),
         ),
         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)
Пример #20
0
 def test_versioned_field(self):
     field = TextField('foo', field_uri='bar', supported_from=EXCHANGE_2010)
     with self.assertRaises(InvalidFieldForVersion):
         field.clean('baz', version=Version(EXCHANGE_2007))
     field.clean('baz', version=Version(EXCHANGE_2010))
     field.clean('baz', version=Version(EXCHANGE_2013))
Пример #21
0
 def test_comparison(self):
     self.assertEqual(Version(Build(15, 1, 2, 3)),
                      Version(Build(15, 1, 2, 3)))
     self.assertNotEqual(Version(Build(15, 1, 2, 3)), Version(Build(15, 1)))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), api_version="XXX"),
                         Version(None, api_version="XXX"))
     self.assertNotEqual(Version(None, api_version="XXX"),
                         Version(Build(15, 1, 2), api_version="XXX"))
     self.assertEqual(Version(Build(15, 1, 2, 3), "XXX"),
                      Version(Build(15, 1, 2, 3), "XXX"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(15, 1, 2, 3), "YYY"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(99, 88), "XXX"))
     self.assertNotEqual(Version(Build(15, 1, 2, 3), "XXX"),
                         Version(Build(99, 88), "YYY"))
Пример #22
0
    def test_version_guess(self, m):
        protocol = self.get_test_protocol()
        # Test that we can get the version even on error responses
        m.post(
            protocol.service_endpoint,
            status_code=200,
            content=b"""\
<?xml version='1.0' encoding='utf-8'?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
    MajorVersion="15" MinorVersion="1" MajorBuildNumber="2345" MinorBuildNumber="6789" Version="V2017_07_11"/>
  </s:Header>
  <s:Body>
    <m:ResolveNamesResponse
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:ResolveNamesResponseMessage ResponseClass="Error">
          <m:MessageText>Multiple results were found.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </m:ResolveNamesResponse>
  </s:Body>
</s:Envelope>""",
        )
        Version.guess(protocol)
        self.assertEqual(protocol.version.build, Build(15, 1, 2345, 6789))

        # Test exception when there are no version headers
        m.post(
            protocol.service_endpoint,
            status_code=200,
            content=b"""\
<?xml version='1.0' encoding='utf-8'?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
  </s:Header>
  <s:Body>
    <m:ResolveNamesResponse
    xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
    xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:ResolveNamesResponseMessage ResponseClass="Error">
          <m:MessageText>.</m:MessageText>
          <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode>
          <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey>
        </m:ResolveNamesResponseMessage>
      </m:ResponseMessages>
    </m:ResolveNamesResponse>
  </s:Body>
</s:Envelope>""",
        )
        with self.assertRaises(TransportError) as e:
            Version.guess(protocol)
        self.assertEqual(
            e.exception.args[0],
            "No valid version headers found in response (ErrorNameResolutionMultipleResults('.'))"
        )
Пример #23
0
 def test_resolvenames(self):
     with self.assertRaises(ValueError) as e:
         self.account.protocol.resolve_names(names=[], search_scope="XXX")
     self.assertEqual(
         e.exception.args[0],
         f"'search_scope' 'XXX' must be one of {sorted(SEARCH_SCOPE_CHOICES)}"
     )
     with self.assertRaises(ValueError) as e:
         self.account.protocol.resolve_names(names=[], shape="XXX")
     self.assertEqual(
         e.exception.args[0],
         "'contact_data_shape' 'XXX' must be one of ['AllProperties', 'Default', 'IdOnly']"
     )
     with self.assertRaises(ValueError) as e:
         ResolveNames(protocol=self.account.protocol,
                      chunk_size=500).call(unresolved_entries=None)
     self.assertEqual(
         e.exception.args[0],
         "Chunk size 500 is too high. ResolveNames supports returning at most 100 candidates for a lookup",
     )
     tmp = self.account.protocol.version
     self.account.protocol.config.version = Version(EXCHANGE_2010_SP1)
     with self.assertRaises(NotImplementedError) as e:
         self.account.protocol.resolve_names(names=["*****@*****.**"],
                                             shape="IdOnly")
     self.account.protocol.config.version = tmp
     self.assertEqual(
         e.exception.args[0],
         "'contact_data_shape' is only supported for Exchange 2010 SP2 servers and later"
     )
     self.assertGreaterEqual(
         self.account.protocol.resolve_names(names=["*****@*****.**"]), [])
     self.assertGreaterEqual(
         self.account.protocol.resolve_names(
             names=["*****@*****.**"],
             search_scope="ActiveDirectoryContacts"), [])
     self.assertGreaterEqual(
         self.account.protocol.resolve_names(names=["*****@*****.**"],
                                             shape="AllProperties"), [])
     self.assertGreaterEqual(
         self.account.protocol.resolve_names(
             names=["*****@*****.**"],
             parent_folders=[self.account.contacts]), [])
     self.assertEqual(
         self.account.protocol.resolve_names(
             names=[self.account.primary_smtp_address]),
         [Mailbox(email_address=self.account.primary_smtp_address)],
     )
     # Test something that's not an email
     self.assertEqual(
         self.account.protocol.resolve_names(names=["foo\\bar"]),
         [ErrorNameResolutionNoResults("No results were found.")],
     )
     # Test return_full_contact_data
     mailbox, contact = self.account.protocol.resolve_names(
         names=[self.account.primary_smtp_address],
         return_full_contact_data=True)[0]
     self.assertEqual(
         mailbox, Mailbox(email_address=self.account.primary_smtp_address))
     self.assertListEqual(
         [
             e.email.replace("SMTP:", "")
             for e in contact.email_addresses if e.label == "EmailAddress1"
         ],
         [self.account.primary_smtp_address],
     )
Пример #24
0
 def test_default_api_version(self):
     # Test that a version gets a reasonable api_version value if we don't set one explicitly
     version = Version(build=Build(15, 1, 2, 3))
     self.assertEqual(version.api_version, 'Exchange2016')
Пример #25
0
    def test_delegate(self):
        # The test server does not have any delegate info. Test that account.delegates works, and mock to test parsing
        # of a non-empty response.
        self.assertGreaterEqual(
            len(self.account.delegates),
            0
        )
        self.assertGreaterEqual(
            len(list(GetDelegate(account=self.account).call(user_ids=['*****@*****.**'], include_permissions=True))),
            0
        )

        xml = b'''\
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <m:GetDelegateResponse ResponseClass="Success"
            xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
            xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
      <m:ResponseCode>NoError</m:ResponseCode>
      <m:ResponseMessages>
        <m:DelegateUserResponseMessageType ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:DelegateUser>
              <t:UserId>
                <t:SID>SOME_SID</t:SID>
                <t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>
                <t:DisplayName>Foo Bar</t:DisplayName>
              </t:UserId>
              <t:DelegatePermissions>
                <t:CalendarFolderPermissionLevel>Author</t:CalendarFolderPermissionLevel>
                <t:InboxFolderPermissionLevel>Reviewer</t:ContactsFolderPermissionLevel>
              </t:DelegatePermissions>
              <t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>
            <t:ViewPrivateItems>true</t:ViewPrivateItems>
            </m:DelegateUser>
          </m:DelegateUserResponseMessageType>
      </m:ResponseMessages>
      <m:DeliverMeetingRequests>DelegatesAndMe</m:DeliverMeetingRequests>
      </m:GetDelegateResponse>
  </s:Body>
</s:Envelope>'''

        MockTZ = namedtuple('EWSTimeZone', ['ms_id'])
        MockAccount = namedtuple('Account', ['access_type', 'primary_smtp_address', 'default_timezone', 'protocol'])
        MockProtocol = namedtuple('Protocol', ['version'])
        p = MockProtocol(version=Version(build=EXCHANGE_2007_SP1))
        a = MockAccount(DELEGATE, '*****@*****.**', MockTZ('XXX'), protocol=p)

        ws = GetDelegate(account=a)
        _, body = ws._get_soap_parts(response=MockResponse(xml))
        res = ws._get_elements_in_response(response=ws._get_soap_messages(body=body))
        delegates = [DelegateUser.from_xml(elem=elem, account=a) for elem in res]
        self.assertListEqual(
            delegates,
            [
                DelegateUser(
                    user_id=UserId(sid='SOME_SID', primary_smtp_address='*****@*****.**', display_name='Foo Bar'),
                    delegate_permissions=DelegatePermissions(
                        calendar_folder_permission_level='Author',
                        inbox_folder_permission_level='Reviewer',
                        contacts_folder_permission_level='None',
                        notes_folder_permission_level='None',
                        journal_folder_permission_level='None',
                        tasks_folder_permission_level='None',
                    ),
                    receive_copies_of_meeting_messages=False,
                    view_private_items=True,
                )
            ]
        )
Пример #26
0
 def test_q_failures(self):
     with self.assertRaises(ValueError):
         # Invalid value
         Q(foo=None).clean(version=Version(build=EXCHANGE_2007))
    def test_delegate(self):
        # The test server does not have any delegate info. Test that account.delegates works, and mock to test parsing
        # of a non-empty response.
        self.assertGreaterEqual(len(self.account.delegates), 0)
        with self.assertRaises(ErrorInvalidUserSid):
            list(GetDelegate(account=self.account).call(user_ids=[UserId(sid="XXX")], include_permissions=True))
        with self.assertRaises(ErrorDelegateNoUser):
            list(GetDelegate(account=self.account).call(user_ids=["*****@*****.**"], include_permissions=True))
        with self.assertRaises(ErrorNotDelegate):
            list(
                GetDelegate(account=self.account).call(
                    user_ids=[self.account.primary_smtp_address], include_permissions=True
                )
            )

        xml = b"""\
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <m:GetDelegateResponse ResponseClass="Success"
            xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
            xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
      <m:ResponseCode>NoError</m:ResponseCode>
      <m:ResponseMessages>
        <m:DelegateUserResponseMessageType ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:DelegateUser>
              <t:UserId>
                <t:SID>SOME_SID</t:SID>
                <t:PrimarySmtpAddress>[email protected]</t:PrimarySmtpAddress>
                <t:DisplayName>Foo Bar</t:DisplayName>
              </t:UserId>
              <t:DelegatePermissions>
                <t:CalendarFolderPermissionLevel>Author</t:CalendarFolderPermissionLevel>
                <t:InboxFolderPermissionLevel>Reviewer</t:ContactsFolderPermissionLevel>
              </t:DelegatePermissions>
              <t:ReceiveCopiesOfMeetingMessages>false</t:ReceiveCopiesOfMeetingMessages>
            <t:ViewPrivateItems>true</t:ViewPrivateItems>
            </m:DelegateUser>
          </m:DelegateUserResponseMessageType>
      </m:ResponseMessages>
      <m:DeliverMeetingRequests>DelegatesAndMe</m:DeliverMeetingRequests>
      </m:GetDelegateResponse>
  </s:Body>
</s:Envelope>"""

        MockTZ = namedtuple("EWSTimeZone", ["ms_id"])
        MockAccount = namedtuple("Account", ["access_type", "primary_smtp_address", "default_timezone", "protocol"])
        MockProtocol = namedtuple("Protocol", ["version"])
        p = MockProtocol(version=Version(build=EXCHANGE_2007_SP1))
        a = MockAccount(DELEGATE, "*****@*****.**", MockTZ("XXX"), protocol=p)

        ws = GetDelegate(account=a)
        delegates = list(ws.parse(xml))
        self.assertListEqual(
            delegates,
            [
                DelegateUser(
                    user_id=UserId(sid="SOME_SID", primary_smtp_address="*****@*****.**", display_name="Foo Bar"),
                    delegate_permissions=DelegatePermissions(
                        calendar_folder_permission_level="Author",
                        inbox_folder_permission_level="Reviewer",
                        contacts_folder_permission_level="None",
                        notes_folder_permission_level="None",
                        journal_folder_permission_level="None",
                        tasks_folder_permission_level="None",
                    ),
                    receive_copies_of_meeting_messages=False,
                    view_private_items=True,
                )
            ],
        )
Пример #28
0
    def test_from_response(self, m):
        # Test fallback to suggested api_version value when there is a version mismatch and response version is fishy
        version = Version.from_soap_header(
            'Exchange2007',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="V2016_10_10"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, EXCHANGE_2007.api_version())
        self.assertEqual(version.api_version, 'Exchange2007')
        self.assertEqual(version.build, Build(15, 1, 845, 22))

        # Test that override the suggested version if the response version is not fishy
        version = Version.from_soap_header(
            'Exchange2013',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1" Version="HELLO_FROM_EXCHANGELIB"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'HELLO_FROM_EXCHANGELIB')

        # Test that we override the suggested version with the version deduced from the build number if a version is not
        # present in the response
        version = Version.from_soap_header(
            'Exchange2013',
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'Exchange2016')

        # Test that we use the version deduced from the build number when a version is not present in the response and
        # there was no suggested version.
        version = Version.from_soap_header(
            None,
            to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo
        MajorBuildNumber="845" MajorVersion="15" MinorBuildNumber="22" MinorVersion="1"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertEqual(version.api_version, 'Exchange2016')

        # Test various parse failures
        with self.assertRaises(TransportError) as e:
            Version.from_soap_header(
                'Exchange2013',
                to_xml(b'''\
<s:Header>
    <foo/>
</s:Header>'''))
        self.assertIn('No ServerVersionInfo in header', e.exception.args[0])
        with self.assertRaises(TransportError) as e:
            Version.from_soap_header(
                'Exchange2013',
                to_xml(b'''\
<s:Header>
    <h:ServerVersionInfo MajorBuildNumber="845" MajorVersion="15" Version="V2016_10_10"
        xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"/>
</s:Header>'''))
        self.assertIn('Bad ServerVersionInfo in response', e.exception.args[0])
 def test_versioned_field(self):
     field = TextField("foo", field_uri="bar", supported_from=EXCHANGE_2010)
     with self.assertRaises(InvalidFieldForVersion):
         field.clean("baz", version=Version(EXCHANGE_2007))
     field.clean("baz", version=Version(EXCHANGE_2010))
     field.clean("baz", version=Version(EXCHANGE_2013))