New upstream version 4.7.6
Ileana Dumitrescu
1 year, 8 months ago
49 | 49 | # Only repo owners have access to the secret. PRs will run only the unit tests |
50 | 50 | if: env.AES_256_CBC_PASS != '' |
51 | 51 | run: | |
52 | openssl aes-256-cbc -d -in settings.yml.ghenc -out settings.yml -pass env:AES_256_CBC_PASS | |
52 | openssl aes-256-cbc -d -md sha256 -in settings.yml.ghenc -out settings.yml -pass env:AES_256_CBC_PASS | |
53 | 53 | |
54 | 54 | - name: Upgrade pip |
55 | 55 | run: | |
76 | 76 | env: |
77 | 77 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
78 | 78 | run: | |
79 | black --check exchangelib tests | |
80 | isort --check exchangelib tests | |
79 | black --check --diff exchangelib tests scripts setup.py | |
80 | isort --check --diff exchangelib tests scripts setup.py | |
81 | flake8 exchangelib tests scripts setup.py | |
81 | 82 | unittest-parallel -j 4 --class-fixtures --coverage --coverage-source exchangelib |
82 | 83 | coveralls --service=github |
83 | 84 | |
101 | 102 | # Only repo owners have access to the secret. PRs will run only the unit tests |
102 | 103 | if: env.AES_256_CBC_PASS != '' |
103 | 104 | run: | |
104 | openssl aes-256-cbc -d -in settings.yml.ghenc -out settings.yml -pass env:AES_256_CBC_PASS | |
105 | openssl aes-256-cbc -d -md sha256 -in settings.yml.ghenc -out settings.yml -pass env:AES_256_CBC_PASS | |
105 | 106 | |
106 | 107 | - name: Upgrade pip |
107 | 108 | run: | |
0 | # See https://pre-commit.com for more information | |
1 | # See https://pre-commit.com/hooks.html for more hooks | |
2 | repos: | |
3 | - repo: https://github.com/pre-commit/pre-commit-hooks | |
4 | rev: v3.2.0 | |
5 | hooks: | |
6 | - id: trailing-whitespace | |
7 | - id: end-of-file-fixer | |
8 | - id: check-yaml | |
9 | - id: check-added-large-files | |
10 | - repo: https://github.com/compilerla/conventional-pre-commit | |
11 | rev: v1.2.0 | |
12 | hooks: | |
13 | - id: conventional-pre-commit | |
14 | stages: [ commit-msg ] | |
15 | args: [ ] # optional: list of Conventional Commits types to allow | |
16 | - repo: local | |
17 | hooks: | |
18 | - id: black | |
19 | name: black | |
20 | stages: [ commit ] | |
21 | entry: black --check --diff | |
22 | language: system | |
23 | types: [ python ] | |
24 | - id: isort | |
25 | name: isort | |
26 | stages: [ commit ] | |
27 | entry: isort --check --diff | |
28 | types: [ python ] | |
29 | language: system | |
30 | always_run: true | |
31 | - id: flake8 | |
32 | name: flake8 | |
33 | stages: [ commit ] | |
34 | entry: flake8 | |
35 | types: [ python ] | |
36 | language: system | |
37 | always_run: true |
2 | 2 | |
3 | 3 | HEAD |
4 | 4 | ---- |
5 | ||
6 | ||
7 | 4.7.6 | |
8 | ----- | |
9 | - Fixed token refresh bug with OAuth2 authentication, again | |
10 | ||
11 | ||
12 | 4.7.5 | |
13 | ----- | |
14 | - Fixed `Protocol.get_free_busy_info()` when called with +100 accounts. | |
15 | - Allowed configuring DNS timeout for a single nameserver | |
16 | (`Autodiscovery.DNS_RESOLVER_ATTRS["timeout""]`) and the total query lifetime | |
17 | (`Autodiscovery.DNS_RESOLVER_LIFETIME`) separately. | |
18 | - Fixed token refresh bug with OAuth2 authentication | |
19 | ||
20 | ||
21 | 4.7.4 | |
22 | ----- | |
23 | - Bugfix release | |
24 | ||
25 | ||
26 | 4.7.3 | |
27 | ----- | |
28 | - Bugfix release | |
5 | 29 | |
6 | 30 | |
7 | 31 | 4.7.2 |
835 | 859 | --- |
836 | 860 | |
837 | 861 | - Initial import |
838 |
Binary diff not shown
Binary diff not shown
Binary diff not shown
53 | 53 | |
54 | 54 | log = logging.getLogger(__name__) |
55 | 55 | |
56 | DNS_LOOKUP_ERRORS = ( | |
57 | dns.name.EmptyLabel, | |
58 | dns.resolver.NXDOMAIN, | |
59 | dns.resolver.NoAnswer, | |
60 | dns.resolver.NoNameservers, | |
61 | ) | |
62 | ||
56 | 63 | |
57 | 64 | def discover(email, credentials=None, auth_type=None, retry_policy=None): |
58 | 65 | ad_response, protocol = Autodiscovery(email=email, credentials=credentials).discover() |
108 | 115 | MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up |
109 | 116 | DNS_RESOLVER_KWARGS = {} |
110 | 117 | DNS_RESOLVER_ATTRS = { |
111 | "timeout": AutodiscoverProtocol.TIMEOUT, | |
118 | "timeout": AutodiscoverProtocol.TIMEOUT / 2.5, # Timeout for query to a single nameserver | |
112 | 119 | } |
120 | DNS_RESOLVER_LIFETIME = AutodiscoverProtocol.TIMEOUT # Total timeout for a query in case of multiple nameservers | |
113 | 121 | |
114 | 122 | def __init__(self, email, credentials=None): |
115 | 123 | """ |
384 | 392 | def _is_valid_hostname(self, hostname): |
385 | 393 | log.debug("Checking if %s can be looked up in DNS", hostname) |
386 | 394 | try: |
387 | self.resolver.resolve(hostname) | |
388 | except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.name.EmptyLabel): | |
395 | self.resolver.resolve(f"{hostname}.", "A", lifetime=self.DNS_RESOLVER_LIFETIME) | |
396 | except DNS_LOOKUP_ERRORS as e: | |
397 | log.debug("DNS A lookup failure: %s", e) | |
389 | 398 | return False |
390 | 399 | return True |
391 | 400 | |
405 | 414 | log.debug("Attempting to get SRV records for %s", hostname) |
406 | 415 | records = [] |
407 | 416 | try: |
408 | answers = self.resolver.resolve(f"{hostname}.", "SRV") | |
409 | except (dns.resolver.NoNameservers, dns.resolver.NoAnswer, dns.resolver.NXDOMAIN) as e: | |
410 | log.debug("DNS lookup failure: %s", e) | |
417 | answers = self.resolver.resolve(f"{hostname}.", "SRV", lifetime=self.DNS_RESOLVER_LIFETIME) | |
418 | except DNS_LOOKUP_ERRORS as e: | |
419 | log.debug("DNS SRV lookup failure: %s", e) | |
411 | 420 | return records |
412 | 421 | for rdata in answers: |
413 | 422 | try: |
682 | 691 | MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up |
683 | 692 | DNS_RESOLVER_KWARGS = {} |
684 | 693 | DNS_RESOLVER_ATTRS = { |
685 | "timeout": AutodiscoverProtocol.TIMEOUT, | |
694 | "timeout": AutodiscoverProtocol.TIMEOUT / 2.5, # Timeout for query to a single nameserver | |
686 | 695 | } |
696 | DNS_RESOLVER_LIFETIME = AutodiscoverProtocol.TIMEOUT # Total timeout for a query in case of multiple nameservers | |
687 | 697 | |
688 | 698 | def __init__(self, email, credentials=None): |
689 | 699 | """ |
958 | 968 | def _is_valid_hostname(self, hostname): |
959 | 969 | log.debug("Checking if %s can be looked up in DNS", hostname) |
960 | 970 | try: |
961 | self.resolver.resolve(hostname) | |
962 | except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.name.EmptyLabel): | |
971 | self.resolver.resolve(f"{hostname}.", "A", lifetime=self.DNS_RESOLVER_LIFETIME) | |
972 | except DNS_LOOKUP_ERRORS as e: | |
973 | log.debug("DNS A lookup failure: %s", e) | |
963 | 974 | return False |
964 | 975 | return True |
965 | 976 | |
979 | 990 | log.debug("Attempting to get SRV records for %s", hostname) |
980 | 991 | records = [] |
981 | 992 | try: |
982 | answers = self.resolver.resolve(f"{hostname}.", "SRV") | |
983 | except (dns.resolver.NoNameservers, dns.resolver.NoAnswer, dns.resolver.NXDOMAIN) as e: | |
984 | log.debug("DNS lookup failure: %s", e) | |
993 | answers = self.resolver.resolve(f"{hostname}.", "SRV", lifetime=self.DNS_RESOLVER_LIFETIME) | |
994 | except DNS_LOOKUP_ERRORS as e: | |
995 | log.debug("DNS SRV lookup failure: %s", e) | |
985 | 996 | return records |
986 | 997 | for rdata in answers: |
987 | 998 | try: |
1153 | 1164 | <div class="desc"></div> |
1154 | 1165 | </dd> |
1155 | 1166 | <dt id="exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_KWARGS"><code class="name">var <span class="ident">DNS_RESOLVER_KWARGS</span></code></dt> |
1167 | <dd> | |
1168 | <div class="desc"></div> | |
1169 | </dd> | |
1170 | <dt id="exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_LIFETIME"><code class="name">var <span class="ident">DNS_RESOLVER_LIFETIME</span></code></dt> | |
1156 | 1171 | <dd> |
1157 | 1172 | <div class="desc"></div> |
1158 | 1173 | </dd> |
1313 | 1328 | <ul class=""> |
1314 | 1329 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_ATTRS" href="#exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_ATTRS">DNS_RESOLVER_ATTRS</a></code></li> |
1315 | 1330 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_KWARGS" href="#exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_KWARGS">DNS_RESOLVER_KWARGS</a></code></li> |
1331 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_LIFETIME" href="#exchangelib.autodiscover.discovery.Autodiscovery.DNS_RESOLVER_LIFETIME">DNS_RESOLVER_LIFETIME</a></code></li> | |
1316 | 1332 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.INITIAL_RETRY_POLICY" href="#exchangelib.autodiscover.discovery.Autodiscovery.INITIAL_RETRY_POLICY">INITIAL_RETRY_POLICY</a></code></li> |
1317 | 1333 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.MAX_REDIRECTS" href="#exchangelib.autodiscover.discovery.Autodiscovery.MAX_REDIRECTS">MAX_REDIRECTS</a></code></li> |
1318 | 1334 | <li><code><a title="exchangelib.autodiscover.discovery.Autodiscovery.RETRY_WAIT" href="#exchangelib.autodiscover.discovery.Autodiscovery.RETRY_WAIT">RETRY_WAIT</a></code></li> |
388 | 388 | MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up |
389 | 389 | DNS_RESOLVER_KWARGS = {} |
390 | 390 | DNS_RESOLVER_ATTRS = { |
391 | "timeout": AutodiscoverProtocol.TIMEOUT, | |
391 | "timeout": AutodiscoverProtocol.TIMEOUT / 2.5, # Timeout for query to a single nameserver | |
392 | 392 | } |
393 | DNS_RESOLVER_LIFETIME = AutodiscoverProtocol.TIMEOUT # Total timeout for a query in case of multiple nameservers | |
393 | 394 | |
394 | 395 | def __init__(self, email, credentials=None): |
395 | 396 | """ |
664 | 665 | def _is_valid_hostname(self, hostname): |
665 | 666 | log.debug("Checking if %s can be looked up in DNS", hostname) |
666 | 667 | try: |
667 | self.resolver.resolve(hostname) | |
668 | except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.name.EmptyLabel): | |
668 | self.resolver.resolve(f"{hostname}.", "A", lifetime=self.DNS_RESOLVER_LIFETIME) | |
669 | except DNS_LOOKUP_ERRORS as e: | |
670 | log.debug("DNS A lookup failure: %s", e) | |
669 | 671 | return False |
670 | 672 | return True |
671 | 673 | |
685 | 687 | log.debug("Attempting to get SRV records for %s", hostname) |
686 | 688 | records = [] |
687 | 689 | try: |
688 | answers = self.resolver.resolve(f"{hostname}.", "SRV") | |
689 | except (dns.resolver.NoNameservers, dns.resolver.NoAnswer, dns.resolver.NXDOMAIN) as e: | |
690 | log.debug("DNS lookup failure: %s", e) | |
690 | answers = self.resolver.resolve(f"{hostname}.", "SRV", lifetime=self.DNS_RESOLVER_LIFETIME) | |
691 | except DNS_LOOKUP_ERRORS as e: | |
692 | log.debug("DNS SRV lookup failure: %s", e) | |
691 | 693 | return records |
692 | 694 | for rdata in answers: |
693 | 695 | try: |
859 | 861 | <div class="desc"></div> |
860 | 862 | </dd> |
861 | 863 | <dt id="exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_KWARGS"><code class="name">var <span class="ident">DNS_RESOLVER_KWARGS</span></code></dt> |
864 | <dd> | |
865 | <div class="desc"></div> | |
866 | </dd> | |
867 | <dt id="exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_LIFETIME"><code class="name">var <span class="ident">DNS_RESOLVER_LIFETIME</span></code></dt> | |
862 | 868 | <dd> |
863 | 869 | <div class="desc"></div> |
864 | 870 | </dd> |
1019 | 1025 | <ul class=""> |
1020 | 1026 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_ATTRS" href="#exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_ATTRS">DNS_RESOLVER_ATTRS</a></code></li> |
1021 | 1027 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_KWARGS" href="#exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_KWARGS">DNS_RESOLVER_KWARGS</a></code></li> |
1028 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_LIFETIME" href="#exchangelib.autodiscover.Autodiscovery.DNS_RESOLVER_LIFETIME">DNS_RESOLVER_LIFETIME</a></code></li> | |
1022 | 1029 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.INITIAL_RETRY_POLICY" href="#exchangelib.autodiscover.Autodiscovery.INITIAL_RETRY_POLICY">INITIAL_RETRY_POLICY</a></code></li> |
1023 | 1030 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.MAX_REDIRECTS" href="#exchangelib.autodiscover.Autodiscovery.MAX_REDIRECTS">MAX_REDIRECTS</a></code></li> |
1024 | 1031 | <li><code><a title="exchangelib.autodiscover.Autodiscovery.RETRY_WAIT" href="#exchangelib.autodiscover.Autodiscovery.RETRY_WAIT">RETRY_WAIT</a></code></li> |
88 | 88 | if auth_type is None: |
89 | 89 | # Set a default auth type for the credentials where this makes sense |
90 | 90 | auth_type = DEFAULT_AUTH_TYPE.get(type(credentials)) |
91 | elif credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
91 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
92 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
93 | if credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
92 | 94 | raise ValueError(f"Auth type {auth_type!r} was detected but no credentials were provided") |
93 | 95 | if server and service_endpoint: |
94 | 96 | raise AttributeError("Only one of 'server' or 'service_endpoint' must be provided") |
95 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
96 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
97 | 97 | if not retry_policy: |
98 | 98 | retry_policy = FailFast() |
99 | 99 | if not isinstance(version, (Version, type(None))): |
211 | 211 | if auth_type is None: |
212 | 212 | # Set a default auth type for the credentials where this makes sense |
213 | 213 | auth_type = DEFAULT_AUTH_TYPE.get(type(credentials)) |
214 | elif credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
214 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
215 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
216 | if credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
215 | 217 | raise ValueError(f"Auth type {auth_type!r} was detected but no credentials were provided") |
216 | 218 | if server and service_endpoint: |
217 | 219 | raise AttributeError("Only one of 'server' or 'service_endpoint' must be provided") |
218 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
219 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
220 | 220 | if not retry_policy: |
221 | 221 | retry_policy = FailFast() |
222 | 222 | if not isinstance(version, (Version, type(None))): |
140 | 140 | the associated auth code grant type for multi-tenant applications. |
141 | 141 | """ |
142 | 142 | |
143 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None): | |
143 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None, access_token=None): | |
144 | 144 | """ |
145 | 145 | |
146 | 146 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
147 | 147 | :param client_secret: Secret associated with the OAuth application |
148 | 148 | :param tenant_id: Microsoft tenant ID of the account to access |
149 | 149 | :param identity: An Identity object representing the account that these credentials are connected to. |
150 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token | |
150 | 151 | """ |
151 | 152 | super().__init__() |
152 | 153 | self.client_id = client_id |
153 | 154 | self.client_secret = client_secret |
154 | 155 | self.tenant_id = tenant_id |
155 | 156 | self.identity = identity |
156 | # When set, access_token is a dict (or an oauthlib.oauth2.OAuth2Token, which is also a dict) | |
157 | self.access_token = None | |
157 | self.access_token = access_token | |
158 | 158 | |
159 | 159 | def refresh(self, session): |
160 | 160 | # Creating a new session gets a new access token, so there's no work here to refresh the credentials. This |
194 | 194 | res.append(getattr(self, k)) |
195 | 195 | return hash(tuple(res)) |
196 | 196 | |
197 | @property | |
198 | def token_url(self): | |
199 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token" | |
200 | ||
201 | @property | |
202 | def scope(self): | |
203 | return ["https://outlook.office365.com/.default"] | |
204 | ||
197 | 205 | def __repr__(self): |
198 | 206 | return self.__class__.__name__ + repr((self.client_id, "********")) |
199 | 207 | |
206 | 214 | several ways: |
207 | 215 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
208 | 216 | supplied with a refresh token. |
209 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
210 | expires and then refresh it as needed. | |
217 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
218 | refresh it as needed. | |
211 | 219 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
212 | 220 | refresh tokens itself by subclassing and implementing refresh(). |
213 | 221 | |
216 | 224 | tenant. |
217 | 225 | """ |
218 | 226 | |
219 | def __init__(self, authorization_code=None, access_token=None, **kwargs): | |
227 | def __init__(self, authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs): | |
220 | 228 | """ |
221 | 229 | |
222 | 230 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
228 | 236 | :param access_token: Previously-obtained access token. If a token exists and the application will handle |
229 | 237 | refreshing by itself (or opts not to handle it), this parameter alone is sufficient. |
230 | 238 | """ |
231 | super().__init__(**kwargs) | |
239 | super().__init__(client_id=client_id, client_secret=client_secret, **kwargs) | |
232 | 240 | self.authorization_code = authorization_code |
233 | 241 | if access_token is not None and not isinstance(access_token, dict): |
234 | 242 | raise InvalidTypeError("access_token", access_token, OAuth2Token) |
235 | 243 | self.access_token = access_token |
244 | ||
245 | @property | |
246 | def token_url(self): | |
247 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
248 | # tenant for the provided authorization code or refresh token. | |
249 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
250 | ||
251 | @property | |
252 | def scope(self): | |
253 | res = super().scope | |
254 | res.append("offline_access") | |
255 | return res | |
236 | 256 | |
237 | 257 | def __repr__(self): |
238 | 258 | return self.__class__.__name__ + repr( |
441 | 461 | </dd> |
442 | 462 | <dt id="exchangelib.credentials.OAuth2AuthorizationCodeCredentials"><code class="flex name class"> |
443 | 463 | <span>class <span class="ident">OAuth2AuthorizationCodeCredentials</span></span> |
444 | <span>(</span><span>authorization_code=None, access_token=None, **kwargs)</span> | |
464 | <span>(</span><span>authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs)</span> | |
445 | 465 | </code></dt> |
446 | 466 | <dd> |
447 | 467 | <div class="desc"><p>Login info for OAuth 2.0 authentication using the authorization code grant type. This can be used in one of |
448 | 468 | several ways: |
449 | 469 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
450 | 470 | supplied with a refresh token. |
451 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
452 | expires and then refresh it as needed. | |
471 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
472 | refresh it as needed. | |
453 | 473 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
454 | 474 | refresh tokens itself by subclassing and implementing refresh().</p> |
455 | 475 | <p>Unlike the base (client credentials) grant, authorization code credentials don't require a Microsoft tenant ID |
472 | 492 | several ways: |
473 | 493 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
474 | 494 | supplied with a refresh token. |
475 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
476 | expires and then refresh it as needed. | |
495 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
496 | refresh it as needed. | |
477 | 497 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
478 | 498 | refresh tokens itself by subclassing and implementing refresh(). |
479 | 499 | |
482 | 502 | tenant. |
483 | 503 | """ |
484 | 504 | |
485 | def __init__(self, authorization_code=None, access_token=None, **kwargs): | |
505 | def __init__(self, authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs): | |
486 | 506 | """ |
487 | 507 | |
488 | 508 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
494 | 514 | :param access_token: Previously-obtained access token. If a token exists and the application will handle |
495 | 515 | refreshing by itself (or opts not to handle it), this parameter alone is sufficient. |
496 | 516 | """ |
497 | super().__init__(**kwargs) | |
517 | super().__init__(client_id=client_id, client_secret=client_secret, **kwargs) | |
498 | 518 | self.authorization_code = authorization_code |
499 | 519 | if access_token is not None and not isinstance(access_token, dict): |
500 | 520 | raise InvalidTypeError("access_token", access_token, OAuth2Token) |
501 | 521 | self.access_token = access_token |
522 | ||
523 | @property | |
524 | def token_url(self): | |
525 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
526 | # tenant for the provided authorization code or refresh token. | |
527 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
528 | ||
529 | @property | |
530 | def scope(self): | |
531 | res = super().scope | |
532 | res.append("offline_access") | |
533 | return res | |
502 | 534 | |
503 | 535 | def __repr__(self): |
504 | 536 | return self.__class__.__name__ + repr( |
520 | 552 | <li><a title="exchangelib.credentials.OAuth2Credentials" href="#exchangelib.credentials.OAuth2Credentials">OAuth2Credentials</a></li> |
521 | 553 | <li><a title="exchangelib.credentials.BaseCredentials" href="#exchangelib.credentials.BaseCredentials">BaseCredentials</a></li> |
522 | 554 | </ul> |
555 | <h3>Instance variables</h3> | |
556 | <dl> | |
557 | <dt id="exchangelib.credentials.OAuth2AuthorizationCodeCredentials.scope"><code class="name">var <span class="ident">scope</span></code></dt> | |
558 | <dd> | |
559 | <div class="desc"></div> | |
560 | <details class="source"> | |
561 | <summary> | |
562 | <span>Expand source code</span> | |
563 | </summary> | |
564 | <pre><code class="python">@property | |
565 | def scope(self): | |
566 | res = super().scope | |
567 | res.append("offline_access") | |
568 | return res</code></pre> | |
569 | </details> | |
570 | </dd> | |
571 | <dt id="exchangelib.credentials.OAuth2AuthorizationCodeCredentials.token_url"><code class="name">var <span class="ident">token_url</span></code></dt> | |
572 | <dd> | |
573 | <div class="desc"></div> | |
574 | <details class="source"> | |
575 | <summary> | |
576 | <span>Expand source code</span> | |
577 | </summary> | |
578 | <pre><code class="python">@property | |
579 | def token_url(self): | |
580 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
581 | # tenant for the provided authorization code or refresh token. | |
582 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec</code></pre> | |
583 | </details> | |
584 | </dd> | |
585 | </dl> | |
523 | 586 | <h3>Inherited members</h3> |
524 | 587 | <ul class="hlist"> |
525 | 588 | <li><code><b><a title="exchangelib.credentials.OAuth2Credentials" href="#exchangelib.credentials.OAuth2Credentials">OAuth2Credentials</a></b></code>: |
532 | 595 | </dd> |
533 | 596 | <dt id="exchangelib.credentials.OAuth2Credentials"><code class="flex name class"> |
534 | 597 | <span>class <span class="ident">OAuth2Credentials</span></span> |
535 | <span>(</span><span>client_id, client_secret, tenant_id=None, identity=None)</span> | |
598 | <span>(</span><span>client_id, client_secret, tenant_id=None, identity=None, access_token=None)</span> | |
536 | 599 | </code></dt> |
537 | 600 | <dd> |
538 | 601 | <div class="desc"><p>Login info for OAuth 2.0 client credentials authentication, as well as a base for other OAuth 2.0 grant types.</p> |
543 | 606 | <p>:param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
544 | 607 | :param client_secret: Secret associated with the OAuth application |
545 | 608 | :param tenant_id: Microsoft tenant ID of the account to access |
546 | :param identity: An Identity object representing the account that these credentials are connected to.</p></div> | |
609 | :param identity: An Identity object representing the account that these credentials are connected to. | |
610 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token</p></div> | |
547 | 611 | <details class="source"> |
548 | 612 | <summary> |
549 | 613 | <span>Expand source code</span> |
557 | 621 | the associated auth code grant type for multi-tenant applications. |
558 | 622 | """ |
559 | 623 | |
560 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None): | |
624 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None, access_token=None): | |
561 | 625 | """ |
562 | 626 | |
563 | 627 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
564 | 628 | :param client_secret: Secret associated with the OAuth application |
565 | 629 | :param tenant_id: Microsoft tenant ID of the account to access |
566 | 630 | :param identity: An Identity object representing the account that these credentials are connected to. |
631 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token | |
567 | 632 | """ |
568 | 633 | super().__init__() |
569 | 634 | self.client_id = client_id |
570 | 635 | self.client_secret = client_secret |
571 | 636 | self.tenant_id = tenant_id |
572 | 637 | self.identity = identity |
573 | # When set, access_token is a dict (or an oauthlib.oauth2.OAuth2Token, which is also a dict) | |
574 | self.access_token = None | |
638 | self.access_token = access_token | |
575 | 639 | |
576 | 640 | def refresh(self, session): |
577 | 641 | # Creating a new session gets a new access token, so there's no work here to refresh the credentials. This |
611 | 675 | res.append(getattr(self, k)) |
612 | 676 | return hash(tuple(res)) |
613 | 677 | |
678 | @property | |
679 | def token_url(self): | |
680 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token" | |
681 | ||
682 | @property | |
683 | def scope(self): | |
684 | return ["https://outlook.office365.com/.default"] | |
685 | ||
614 | 686 | def __repr__(self): |
615 | 687 | return self.__class__.__name__ + repr((self.client_id, "********")) |
616 | 688 | |
625 | 697 | <ul class="hlist"> |
626 | 698 | <li><a title="exchangelib.credentials.OAuth2AuthorizationCodeCredentials" href="#exchangelib.credentials.OAuth2AuthorizationCodeCredentials">OAuth2AuthorizationCodeCredentials</a></li> |
627 | 699 | </ul> |
700 | <h3>Instance variables</h3> | |
701 | <dl> | |
702 | <dt id="exchangelib.credentials.OAuth2Credentials.scope"><code class="name">var <span class="ident">scope</span></code></dt> | |
703 | <dd> | |
704 | <div class="desc"></div> | |
705 | <details class="source"> | |
706 | <summary> | |
707 | <span>Expand source code</span> | |
708 | </summary> | |
709 | <pre><code class="python">@property | |
710 | def scope(self): | |
711 | return ["https://outlook.office365.com/.default"]</code></pre> | |
712 | </details> | |
713 | </dd> | |
714 | <dt id="exchangelib.credentials.OAuth2Credentials.token_url"><code class="name">var <span class="ident">token_url</span></code></dt> | |
715 | <dd> | |
716 | <div class="desc"></div> | |
717 | <details class="source"> | |
718 | <summary> | |
719 | <span>Expand source code</span> | |
720 | </summary> | |
721 | <pre><code class="python">@property | |
722 | def token_url(self): | |
723 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"</code></pre> | |
724 | </details> | |
725 | </dd> | |
726 | </dl> | |
628 | 727 | <h3>Methods</h3> |
629 | 728 | <dl> |
630 | 729 | <dt id="exchangelib.credentials.OAuth2Credentials.on_token_auto_refreshed"><code class="name flex"> |
722 | 821 | </li> |
723 | 822 | <li> |
724 | 823 | <h4><code><a title="exchangelib.credentials.OAuth2AuthorizationCodeCredentials" href="#exchangelib.credentials.OAuth2AuthorizationCodeCredentials">OAuth2AuthorizationCodeCredentials</a></code></h4> |
824 | <ul class=""> | |
825 | <li><code><a title="exchangelib.credentials.OAuth2AuthorizationCodeCredentials.scope" href="#exchangelib.credentials.OAuth2AuthorizationCodeCredentials.scope">scope</a></code></li> | |
826 | <li><code><a title="exchangelib.credentials.OAuth2AuthorizationCodeCredentials.token_url" href="#exchangelib.credentials.OAuth2AuthorizationCodeCredentials.token_url">token_url</a></code></li> | |
827 | </ul> | |
725 | 828 | </li> |
726 | 829 | <li> |
727 | 830 | <h4><code><a title="exchangelib.credentials.OAuth2Credentials" href="#exchangelib.credentials.OAuth2Credentials">OAuth2Credentials</a></code></h4> |
728 | 831 | <ul class=""> |
729 | 832 | <li><code><a title="exchangelib.credentials.OAuth2Credentials.on_token_auto_refreshed" href="#exchangelib.credentials.OAuth2Credentials.on_token_auto_refreshed">on_token_auto_refreshed</a></code></li> |
833 | <li><code><a title="exchangelib.credentials.OAuth2Credentials.scope" href="#exchangelib.credentials.OAuth2Credentials.scope">scope</a></code></li> | |
730 | 834 | <li><code><a title="exchangelib.credentials.OAuth2Credentials.sig" href="#exchangelib.credentials.OAuth2Credentials.sig">sig</a></code></li> |
835 | <li><code><a title="exchangelib.credentials.OAuth2Credentials.token_url" href="#exchangelib.credentials.OAuth2Credentials.token_url">token_url</a></code></li> | |
731 | 836 | </ul> |
732 | 837 | </li> |
733 | 838 | </ul> |
73 | 73 | def __eq__(self, other): |
74 | 74 | return repr(self) == repr(other) |
75 | 75 | |
76 | def __hash__(self): | |
77 | return hash(str(self)) | |
78 | ||
76 | 79 | |
77 | 80 | # Warnings |
78 | 81 | class EWSWarning(EWSError): |
148 | 151 | pass |
149 | 152 | |
150 | 153 | |
151 | class TimezoneDefinitionInvalidForYear(EWSError): | |
152 | pass | |
153 | ||
154 | ||
155 | 154 | class SessionPoolMinSizeReached(EWSError): |
156 | 155 | pass |
157 | 156 | |
1445 | 1444 | pass |
1446 | 1445 | |
1447 | 1446 | |
1447 | class ErrorRecoverableItemsAccessDenied(ResponseMessageError): | |
1448 | pass | |
1449 | ||
1450 | ||
1448 | 1451 | class ErrorRecurrenceEndDateTooBig(ResponseMessageError): |
1449 | 1452 | pass |
1450 | 1453 | |
1719 | 1722 | pass |
1720 | 1723 | |
1721 | 1724 | |
1722 | # Microsoft recommends to cache the autodiscover data around 24 hours and perform autodiscover | |
1725 | # Microsoft recommends caching the autodiscover data around 24 hours and perform autodiscover | |
1723 | 1726 | # immediately following certain error responses from EWS. See more at |
1724 | 1727 | # http://blogs.msdn.com/b/mstehle/archive/2010/11/09/ews-best-practices-use-autodiscover.aspx |
1725 | 1728 | |
1889 | 1892 | return str(self.value) |
1890 | 1893 | |
1891 | 1894 | def __eq__(self, other): |
1892 | return repr(self) == repr(other)</code></pre> | |
1895 | return repr(self) == repr(other) | |
1896 | ||
1897 | def __hash__(self): | |
1898 | return hash(str(self))</code></pre> | |
1893 | 1899 | </details> |
1894 | 1900 | <h3>Ancestors</h3> |
1895 | 1901 | <ul class="hlist"> |
1902 | 1908 | <li><a title="exchangelib.errors.EWSWarning" href="#exchangelib.errors.EWSWarning">EWSWarning</a></li> |
1903 | 1909 | <li><a title="exchangelib.errors.SessionPoolMaxSizeReached" href="#exchangelib.errors.SessionPoolMaxSizeReached">SessionPoolMaxSizeReached</a></li> |
1904 | 1910 | <li><a title="exchangelib.errors.SessionPoolMinSizeReached" href="#exchangelib.errors.SessionPoolMinSizeReached">SessionPoolMinSizeReached</a></li> |
1905 | <li><a title="exchangelib.errors.TimezoneDefinitionInvalidForYear" href="#exchangelib.errors.TimezoneDefinitionInvalidForYear">TimezoneDefinitionInvalidForYear</a></li> | |
1906 | 1911 | <li><a title="exchangelib.errors.TransportError" href="#exchangelib.errors.TransportError">TransportError</a></li> |
1907 | 1912 | <li><a title="exchangelib.errors.UnauthorizedError" href="#exchangelib.errors.UnauthorizedError">UnauthorizedError</a></li> |
1908 | 1913 | <li><a title="exchangelib.errors.UnknownTimeZone" href="#exchangelib.errors.UnknownTimeZone">UnknownTimeZone</a></li> |
8869 | 8874 | <span>Expand source code</span> |
8870 | 8875 | </summary> |
8871 | 8876 | <pre><code class="python">class ErrorReadReceiptNotPending(ResponseMessageError): |
8877 | pass</code></pre> | |
8878 | </details> | |
8879 | <h3>Ancestors</h3> | |
8880 | <ul class="hlist"> | |
8881 | <li><a title="exchangelib.errors.ResponseMessageError" href="#exchangelib.errors.ResponseMessageError">ResponseMessageError</a></li> | |
8882 | <li><a title="exchangelib.errors.TransportError" href="#exchangelib.errors.TransportError">TransportError</a></li> | |
8883 | <li><a title="exchangelib.errors.EWSError" href="#exchangelib.errors.EWSError">EWSError</a></li> | |
8884 | <li>builtins.Exception</li> | |
8885 | <li>builtins.BaseException</li> | |
8886 | </ul> | |
8887 | </dd> | |
8888 | <dt id="exchangelib.errors.ErrorRecoverableItemsAccessDenied"><code class="flex name class"> | |
8889 | <span>class <span class="ident">ErrorRecoverableItemsAccessDenied</span></span> | |
8890 | <span>(</span><span>value)</span> | |
8891 | </code></dt> | |
8892 | <dd> | |
8893 | <div class="desc"><p>Global error type within this module.</p></div> | |
8894 | <details class="source"> | |
8895 | <summary> | |
8896 | <span>Expand source code</span> | |
8897 | </summary> | |
8898 | <pre><code class="python">class ErrorRecoverableItemsAccessDenied(ResponseMessageError): | |
8872 | 8899 | pass</code></pre> |
8873 | 8900 | </details> |
8874 | 8901 | <h3>Ancestors</h3> |
10913 | 10940 | <li><a title="exchangelib.errors.ErrorQuotaExceeded" href="#exchangelib.errors.ErrorQuotaExceeded">ErrorQuotaExceeded</a></li> |
10914 | 10941 | <li><a title="exchangelib.errors.ErrorReadEventsFailed" href="#exchangelib.errors.ErrorReadEventsFailed">ErrorReadEventsFailed</a></li> |
10915 | 10942 | <li><a title="exchangelib.errors.ErrorReadReceiptNotPending" href="#exchangelib.errors.ErrorReadReceiptNotPending">ErrorReadReceiptNotPending</a></li> |
10943 | <li><a title="exchangelib.errors.ErrorRecoverableItemsAccessDenied" href="#exchangelib.errors.ErrorRecoverableItemsAccessDenied">ErrorRecoverableItemsAccessDenied</a></li> | |
10916 | 10944 | <li><a title="exchangelib.errors.ErrorRecurrenceEndDateTooBig" href="#exchangelib.errors.ErrorRecurrenceEndDateTooBig">ErrorRecurrenceEndDateTooBig</a></li> |
10917 | 10945 | <li><a title="exchangelib.errors.ErrorRecurrenceHasNoOccurrence" href="#exchangelib.errors.ErrorRecurrenceHasNoOccurrence">ErrorRecurrenceHasNoOccurrence</a></li> |
10918 | 10946 | <li><a title="exchangelib.errors.ErrorRemoveDelegatesFailed" href="#exchangelib.errors.ErrorRemoveDelegatesFailed">ErrorRemoveDelegatesFailed</a></li> |
11044 | 11072 | <li>builtins.BaseException</li> |
11045 | 11073 | </ul> |
11046 | 11074 | </dd> |
11047 | <dt id="exchangelib.errors.TimezoneDefinitionInvalidForYear"><code class="flex name class"> | |
11048 | <span>class <span class="ident">TimezoneDefinitionInvalidForYear</span></span> | |
11049 | <span>(</span><span>value)</span> | |
11050 | </code></dt> | |
11051 | <dd> | |
11052 | <div class="desc"><p>Global error type within this module.</p></div> | |
11053 | <details class="source"> | |
11054 | <summary> | |
11055 | <span>Expand source code</span> | |
11056 | </summary> | |
11057 | <pre><code class="python">class TimezoneDefinitionInvalidForYear(EWSError): | |
11058 | pass</code></pre> | |
11059 | </details> | |
11060 | <h3>Ancestors</h3> | |
11061 | <ul class="hlist"> | |
11062 | <li><a title="exchangelib.errors.EWSError" href="#exchangelib.errors.EWSError">EWSError</a></li> | |
11063 | <li>builtins.Exception</li> | |
11064 | <li>builtins.BaseException</li> | |
11065 | </ul> | |
11066 | </dd> | |
11067 | 11075 | <dt id="exchangelib.errors.TransportError"><code class="flex name class"> |
11068 | 11076 | <span>class <span class="ident">TransportError</span></span> |
11069 | 11077 | <span>(</span><span>value)</span> |
12120 | 12128 | <h4><code><a title="exchangelib.errors.ErrorReadReceiptNotPending" href="#exchangelib.errors.ErrorReadReceiptNotPending">ErrorReadReceiptNotPending</a></code></h4> |
12121 | 12129 | </li> |
12122 | 12130 | <li> |
12131 | <h4><code><a title="exchangelib.errors.ErrorRecoverableItemsAccessDenied" href="#exchangelib.errors.ErrorRecoverableItemsAccessDenied">ErrorRecoverableItemsAccessDenied</a></code></h4> | |
12132 | </li> | |
12133 | <li> | |
12123 | 12134 | <h4><code><a title="exchangelib.errors.ErrorRecurrenceEndDateTooBig" href="#exchangelib.errors.ErrorRecurrenceEndDateTooBig">ErrorRecurrenceEndDateTooBig</a></code></h4> |
12124 | 12135 | </li> |
12125 | 12136 | <li> |
12358 | 12369 | </li> |
12359 | 12370 | <li> |
12360 | 12371 | <h4><code><a title="exchangelib.errors.SessionPoolMinSizeReached" href="#exchangelib.errors.SessionPoolMinSizeReached">SessionPoolMinSizeReached</a></code></h4> |
12361 | </li> | |
12362 | <li> | |
12363 | <h4><code><a title="exchangelib.errors.TimezoneDefinitionInvalidForYear" href="#exchangelib.errors.TimezoneDefinitionInvalidForYear">TimezoneDefinitionInvalidForYear</a></code></h4> | |
12364 | 12372 | </li> |
12365 | 12373 | <li> |
12366 | 12374 | <h4><code><a title="exchangelib.errors.TransportError" href="#exchangelib.errors.TransportError">TransportError</a></code></h4> |
952 | 952 | </details> |
953 | 953 | <h3>Ancestors</h3> |
954 | 954 | <ul class="hlist"> |
955 | <li>backports.zoneinfo.ZoneInfo</li> | |
955 | <li>zoneinfo.ZoneInfo</li> | |
956 | 956 | <li>datetime.tzinfo</li> |
957 | 957 | </ul> |
958 | 958 | <h3>Class variables</h3> |
6610 | 6610 | <dl> |
6611 | 6611 | <dt id="exchangelib.fields.TimeDeltaField.value_cls"><code class="name">var <span class="ident">value_cls</span></code></dt> |
6612 | 6612 | <dd> |
6613 | <div class="desc"><p>Difference between two datetime values.</p></div> | |
6613 | <div class="desc"><p>Difference between two datetime values.</p> | |
6614 | <p>timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)</p> | |
6615 | <p>All arguments are optional and default to 0. | |
6616 | Arguments may be integers or floats, and may be positive or negative.</p></div> | |
6614 | 6617 | </dd> |
6615 | 6618 | </dl> |
6616 | 6619 | <h3>Methods</h3> |
37 | 37 | ErrorDeleteDistinguishedFolder, |
38 | 38 | ErrorFolderNotFound, |
39 | 39 | ErrorItemNotFound, |
40 | ErrorRecoverableItemsAccessDenied, | |
40 | 41 | InvalidTypeError, |
41 | 42 | ) |
42 | 43 | from ..fields import ( |
74 | 75 | |
75 | 76 | log = logging.getLogger(__name__) |
76 | 77 | |
78 | DELETE_FOLDER_ERRORS = ( | |
79 | ErrorAccessDenied, | |
80 | ErrorCannotDeleteObject, | |
81 | ErrorCannotEmptyFolder, | |
82 | ErrorItemNotFound, | |
83 | ) | |
84 | ||
77 | 85 | |
78 | 86 | class BaseFolder(RegisterMixIn, SearchableMixIn, metaclass=EWSMeta): |
79 | 87 | """Base class for all classes that implement a folder.""" |
256 | 264 | :return: |
257 | 265 | """ |
258 | 266 | from .known_folders import ( |
267 | ApplicationData, | |
259 | 268 | Calendar, |
260 | 269 | Contacts, |
261 | 270 | ConversationSettings, |
271 | CrawlerData, | |
272 | DlpPolicyEvaluation, | |
273 | FreeBusyCache, | |
262 | 274 | GALContacts, |
263 | 275 | Messages, |
264 | 276 | RecipientCache, |
277 | RecoveryPoints, | |
265 | 278 | Reminders, |
266 | 279 | RSSFeeds, |
280 | Signal, | |
281 | SwssItems, | |
267 | 282 | Tasks, |
268 | 283 | ) |
269 | 284 | |
270 | 285 | for folder_cls in ( |
286 | ApplicationData, | |
287 | Calendar, | |
288 | Contacts, | |
289 | ConversationSettings, | |
290 | CrawlerData, | |
291 | DlpPolicyEvaluation, | |
292 | FreeBusyCache, | |
293 | GALContacts, | |
271 | 294 | Messages, |
295 | RSSFeeds, | |
296 | RecipientCache, | |
297 | RecoveryPoints, | |
298 | Reminders, | |
299 | Signal, | |
300 | SwssItems, | |
272 | 301 | Tasks, |
273 | Calendar, | |
274 | ConversationSettings, | |
275 | Contacts, | |
276 | GALContacts, | |
277 | Reminders, | |
278 | RecipientCache, | |
279 | RSSFeeds, | |
280 | 302 | ): |
281 | 303 | if folder_cls.CONTAINER_CLASS == container_class: |
282 | 304 | return folder_cls |
429 | 451 | def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
430 | 452 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
431 | 453 | # distinguished folders from being deleted. Use with caution! |
454 | from .known_folders import Audits | |
455 | ||
432 | 456 | _seen = _seen or set() |
433 | 457 | if self.id in _seen: |
434 | 458 | raise RecursionError(f"We already tried to wipe {self}") |
435 | 459 | if _level > 16: |
436 | 460 | raise RecursionError(f"Max recursion level reached: {_level}") |
437 | 461 | _seen.add(self.id) |
462 | if isinstance(self, Audits): | |
463 | # Shortcircuit because this folder can have many items that are all non-deletable | |
464 | log.warning("Cannot wipe audits folder %s", self) | |
465 | return | |
466 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
467 | log.warning("Cannot wipe recoverable items folder %s", self) | |
468 | return | |
438 | 469 | log.warning("Wiping %s", self) |
439 | 470 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
440 | 471 | try: |
442 | 473 | self.empty(delete_sub_folders=False) |
443 | 474 | else: |
444 | 475 | self.empty(delete_sub_folders=True) |
445 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
476 | except ErrorRecoverableItemsAccessDenied: | |
477 | log.warning("Access denied to %s. Skipping", self) | |
478 | return | |
479 | except DELETE_FOLDER_ERRORS: | |
446 | 480 | try: |
447 | 481 | if has_distinguished_subfolders: |
448 | 482 | raise # We already tried this |
449 | 483 | self.empty(delete_sub_folders=False) |
450 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
484 | except DELETE_FOLDER_ERRORS: | |
451 | 485 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
452 | 486 | kwargs = {} |
453 | 487 | if page_size is not None: |
456 | 490 | kwargs["chunk_size"] = chunk_size |
457 | 491 | try: |
458 | 492 | self.all().delete(**kwargs) |
459 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
493 | except DELETE_FOLDER_ERRORS: | |
460 | 494 | log.warning("Not allowed to delete items in %s", self) |
461 | 495 | _level += 1 |
462 | 496 | for f in self.children: |
1126 | 1160 | :return: |
1127 | 1161 | """ |
1128 | 1162 | from .known_folders import ( |
1163 | ApplicationData, | |
1129 | 1164 | Calendar, |
1130 | 1165 | Contacts, |
1131 | 1166 | ConversationSettings, |
1167 | CrawlerData, | |
1168 | DlpPolicyEvaluation, | |
1169 | FreeBusyCache, | |
1132 | 1170 | GALContacts, |
1133 | 1171 | Messages, |
1134 | 1172 | RecipientCache, |
1173 | RecoveryPoints, | |
1135 | 1174 | Reminders, |
1136 | 1175 | RSSFeeds, |
1176 | Signal, | |
1177 | SwssItems, | |
1137 | 1178 | Tasks, |
1138 | 1179 | ) |
1139 | 1180 | |
1140 | 1181 | for folder_cls in ( |
1182 | ApplicationData, | |
1183 | Calendar, | |
1184 | Contacts, | |
1185 | ConversationSettings, | |
1186 | CrawlerData, | |
1187 | DlpPolicyEvaluation, | |
1188 | FreeBusyCache, | |
1189 | GALContacts, | |
1141 | 1190 | Messages, |
1191 | RSSFeeds, | |
1192 | RecipientCache, | |
1193 | RecoveryPoints, | |
1194 | Reminders, | |
1195 | Signal, | |
1196 | SwssItems, | |
1142 | 1197 | Tasks, |
1143 | Calendar, | |
1144 | ConversationSettings, | |
1145 | Contacts, | |
1146 | GALContacts, | |
1147 | Reminders, | |
1148 | RecipientCache, | |
1149 | RSSFeeds, | |
1150 | 1198 | ): |
1151 | 1199 | if folder_cls.CONTAINER_CLASS == container_class: |
1152 | 1200 | return folder_cls |
1299 | 1347 | def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
1300 | 1348 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
1301 | 1349 | # distinguished folders from being deleted. Use with caution! |
1350 | from .known_folders import Audits | |
1351 | ||
1302 | 1352 | _seen = _seen or set() |
1303 | 1353 | if self.id in _seen: |
1304 | 1354 | raise RecursionError(f"We already tried to wipe {self}") |
1305 | 1355 | if _level > 16: |
1306 | 1356 | raise RecursionError(f"Max recursion level reached: {_level}") |
1307 | 1357 | _seen.add(self.id) |
1358 | if isinstance(self, Audits): | |
1359 | # Shortcircuit because this folder can have many items that are all non-deletable | |
1360 | log.warning("Cannot wipe audits folder %s", self) | |
1361 | return | |
1362 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
1363 | log.warning("Cannot wipe recoverable items folder %s", self) | |
1364 | return | |
1308 | 1365 | log.warning("Wiping %s", self) |
1309 | 1366 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
1310 | 1367 | try: |
1312 | 1369 | self.empty(delete_sub_folders=False) |
1313 | 1370 | else: |
1314 | 1371 | self.empty(delete_sub_folders=True) |
1315 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
1372 | except ErrorRecoverableItemsAccessDenied: | |
1373 | log.warning("Access denied to %s. Skipping", self) | |
1374 | return | |
1375 | except DELETE_FOLDER_ERRORS: | |
1316 | 1376 | try: |
1317 | 1377 | if has_distinguished_subfolders: |
1318 | 1378 | raise # We already tried this |
1319 | 1379 | self.empty(delete_sub_folders=False) |
1320 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
1380 | except DELETE_FOLDER_ERRORS: | |
1321 | 1381 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
1322 | 1382 | kwargs = {} |
1323 | 1383 | if page_size is not None: |
1326 | 1386 | kwargs["chunk_size"] = chunk_size |
1327 | 1387 | try: |
1328 | 1388 | self.all().delete(**kwargs) |
1329 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
1389 | except DELETE_FOLDER_ERRORS: | |
1330 | 1390 | log.warning("Not allowed to delete items in %s", self) |
1331 | 1391 | _level += 1 |
1332 | 1392 | for f in self.children: |
1776 | 1836 | :return: |
1777 | 1837 | """ |
1778 | 1838 | from .known_folders import ( |
1839 | ApplicationData, | |
1779 | 1840 | Calendar, |
1780 | 1841 | Contacts, |
1781 | 1842 | ConversationSettings, |
1843 | CrawlerData, | |
1844 | DlpPolicyEvaluation, | |
1845 | FreeBusyCache, | |
1782 | 1846 | GALContacts, |
1783 | 1847 | Messages, |
1784 | 1848 | RecipientCache, |
1849 | RecoveryPoints, | |
1785 | 1850 | Reminders, |
1786 | 1851 | RSSFeeds, |
1852 | Signal, | |
1853 | SwssItems, | |
1787 | 1854 | Tasks, |
1788 | 1855 | ) |
1789 | 1856 | |
1790 | 1857 | for folder_cls in ( |
1858 | ApplicationData, | |
1859 | Calendar, | |
1860 | Contacts, | |
1861 | ConversationSettings, | |
1862 | CrawlerData, | |
1863 | DlpPolicyEvaluation, | |
1864 | FreeBusyCache, | |
1865 | GALContacts, | |
1791 | 1866 | Messages, |
1867 | RSSFeeds, | |
1868 | RecipientCache, | |
1869 | RecoveryPoints, | |
1870 | Reminders, | |
1871 | Signal, | |
1872 | SwssItems, | |
1792 | 1873 | Tasks, |
1793 | Calendar, | |
1794 | ConversationSettings, | |
1795 | Contacts, | |
1796 | GALContacts, | |
1797 | Reminders, | |
1798 | RecipientCache, | |
1799 | RSSFeeds, | |
1800 | 1874 | ): |
1801 | 1875 | if folder_cls.CONTAINER_CLASS == container_class: |
1802 | 1876 | return folder_cls |
2787 | 2861 | <pre><code class="python">def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
2788 | 2862 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
2789 | 2863 | # distinguished folders from being deleted. Use with caution! |
2864 | from .known_folders import Audits | |
2865 | ||
2790 | 2866 | _seen = _seen or set() |
2791 | 2867 | if self.id in _seen: |
2792 | 2868 | raise RecursionError(f"We already tried to wipe {self}") |
2793 | 2869 | if _level > 16: |
2794 | 2870 | raise RecursionError(f"Max recursion level reached: {_level}") |
2795 | 2871 | _seen.add(self.id) |
2872 | if isinstance(self, Audits): | |
2873 | # Shortcircuit because this folder can have many items that are all non-deletable | |
2874 | log.warning("Cannot wipe audits folder %s", self) | |
2875 | return | |
2876 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
2877 | log.warning("Cannot wipe recoverable items folder %s", self) | |
2878 | return | |
2796 | 2879 | log.warning("Wiping %s", self) |
2797 | 2880 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
2798 | 2881 | try: |
2800 | 2883 | self.empty(delete_sub_folders=False) |
2801 | 2884 | else: |
2802 | 2885 | self.empty(delete_sub_folders=True) |
2803 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
2886 | except ErrorRecoverableItemsAccessDenied: | |
2887 | log.warning("Access denied to %s. Skipping", self) | |
2888 | return | |
2889 | except DELETE_FOLDER_ERRORS: | |
2804 | 2890 | try: |
2805 | 2891 | if has_distinguished_subfolders: |
2806 | 2892 | raise # We already tried this |
2807 | 2893 | self.empty(delete_sub_folders=False) |
2808 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
2894 | except DELETE_FOLDER_ERRORS: | |
2809 | 2895 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
2810 | 2896 | kwargs = {} |
2811 | 2897 | if page_size is not None: |
2814 | 2900 | kwargs["chunk_size"] = chunk_size |
2815 | 2901 | try: |
2816 | 2902 | self.all().delete(**kwargs) |
2817 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
2903 | except DELETE_FOLDER_ERRORS: | |
2818 | 2904 | log.warning("Not allowed to delete items in %s", self) |
2819 | 2905 | _level += 1 |
2820 | 2906 | for f in self.children: |
3004 | 3090 | <h3>Subclasses</h3> |
3005 | 3091 | <ul class="hlist"> |
3006 | 3092 | <li><a title="exchangelib.folders.known_folders.AllItems" href="known_folders.html#exchangelib.folders.known_folders.AllItems">AllItems</a></li> |
3093 | <li><a title="exchangelib.folders.known_folders.ApplicationData" href="known_folders.html#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></li> | |
3007 | 3094 | <li><a title="exchangelib.folders.known_folders.Audits" href="known_folders.html#exchangelib.folders.known_folders.Audits">Audits</a></li> |
3095 | <li><a title="exchangelib.folders.known_folders.Birthdays" href="known_folders.html#exchangelib.folders.known_folders.Birthdays">Birthdays</a></li> | |
3008 | 3096 | <li><a title="exchangelib.folders.known_folders.Calendar" href="known_folders.html#exchangelib.folders.known_folders.Calendar">Calendar</a></li> |
3009 | 3097 | <li><a title="exchangelib.folders.known_folders.CalendarLogging" href="known_folders.html#exchangelib.folders.known_folders.CalendarLogging">CalendarLogging</a></li> |
3010 | 3098 | <li><a title="exchangelib.folders.known_folders.CommonViews" href="known_folders.html#exchangelib.folders.known_folders.CommonViews">CommonViews</a></li> |
3011 | 3099 | <li><a title="exchangelib.folders.known_folders.Contacts" href="known_folders.html#exchangelib.folders.known_folders.Contacts">Contacts</a></li> |
3012 | 3100 | <li><a title="exchangelib.folders.known_folders.ConversationSettings" href="known_folders.html#exchangelib.folders.known_folders.ConversationSettings">ConversationSettings</a></li> |
3101 | <li><a title="exchangelib.folders.known_folders.CrawlerData" href="known_folders.html#exchangelib.folders.known_folders.CrawlerData">CrawlerData</a></li> | |
3013 | 3102 | <li><a title="exchangelib.folders.known_folders.DefaultFoldersChangeHistory" href="known_folders.html#exchangelib.folders.known_folders.DefaultFoldersChangeHistory">DefaultFoldersChangeHistory</a></li> |
3014 | 3103 | <li><a title="exchangelib.folders.known_folders.DeferredAction" href="known_folders.html#exchangelib.folders.known_folders.DeferredAction">DeferredAction</a></li> |
3015 | 3104 | <li><a title="exchangelib.folders.known_folders.DeletedItems" href="known_folders.html#exchangelib.folders.known_folders.DeletedItems">DeletedItems</a></li> |
3105 | <li><a title="exchangelib.folders.known_folders.DlpPolicyEvaluation" href="known_folders.html#exchangelib.folders.known_folders.DlpPolicyEvaluation">DlpPolicyEvaluation</a></li> | |
3016 | 3106 | <li><a title="exchangelib.folders.known_folders.ExchangeSyncData" href="known_folders.html#exchangelib.folders.known_folders.ExchangeSyncData">ExchangeSyncData</a></li> |
3017 | 3107 | <li><a title="exchangelib.folders.known_folders.Files" href="known_folders.html#exchangelib.folders.known_folders.Files">Files</a></li> |
3108 | <li><a title="exchangelib.folders.known_folders.FreeBusyCache" href="known_folders.html#exchangelib.folders.known_folders.FreeBusyCache">FreeBusyCache</a></li> | |
3018 | 3109 | <li><a title="exchangelib.folders.known_folders.FreebusyData" href="known_folders.html#exchangelib.folders.known_folders.FreebusyData">FreebusyData</a></li> |
3019 | 3110 | <li><a title="exchangelib.folders.known_folders.GraphAnalytics" href="known_folders.html#exchangelib.folders.known_folders.GraphAnalytics">GraphAnalytics</a></li> |
3020 | 3111 | <li><a title="exchangelib.folders.known_folders.Location" href="known_folders.html#exchangelib.folders.known_folders.Location">Location</a></li> |
3024 | 3115 | <li><a title="exchangelib.folders.known_folders.PassThroughSearchResults" href="known_folders.html#exchangelib.folders.known_folders.PassThroughSearchResults">PassThroughSearchResults</a></li> |
3025 | 3116 | <li><a title="exchangelib.folders.known_folders.PdpProfileV2Secured" href="known_folders.html#exchangelib.folders.known_folders.PdpProfileV2Secured">PdpProfileV2Secured</a></li> |
3026 | 3117 | <li><a title="exchangelib.folders.known_folders.RSSFeeds" href="known_folders.html#exchangelib.folders.known_folders.RSSFeeds">RSSFeeds</a></li> |
3118 | <li><a title="exchangelib.folders.known_folders.RecoveryPoints" href="known_folders.html#exchangelib.folders.known_folders.RecoveryPoints">RecoveryPoints</a></li> | |
3027 | 3119 | <li><a title="exchangelib.folders.known_folders.Reminders" href="known_folders.html#exchangelib.folders.known_folders.Reminders">Reminders</a></li> |
3028 | 3120 | <li><a title="exchangelib.folders.known_folders.Schedule" href="known_folders.html#exchangelib.folders.known_folders.Schedule">Schedule</a></li> |
3029 | 3121 | <li><a title="exchangelib.folders.known_folders.Sharing" href="known_folders.html#exchangelib.folders.known_folders.Sharing">Sharing</a></li> |
3030 | 3122 | <li><a title="exchangelib.folders.known_folders.Shortcuts" href="known_folders.html#exchangelib.folders.known_folders.Shortcuts">Shortcuts</a></li> |
3031 | 3123 | <li><a title="exchangelib.folders.known_folders.Signal" href="known_folders.html#exchangelib.folders.known_folders.Signal">Signal</a></li> |
3124 | <li><a title="exchangelib.folders.known_folders.SkypeTeamsMessages" href="known_folders.html#exchangelib.folders.known_folders.SkypeTeamsMessages">SkypeTeamsMessages</a></li> | |
3032 | 3125 | <li><a title="exchangelib.folders.known_folders.SmsAndChatsSync" href="known_folders.html#exchangelib.folders.known_folders.SmsAndChatsSync">SmsAndChatsSync</a></li> |
3033 | 3126 | <li><a title="exchangelib.folders.known_folders.SpoolerQueue" href="known_folders.html#exchangelib.folders.known_folders.SpoolerQueue">SpoolerQueue</a></li> |
3127 | <li><a title="exchangelib.folders.known_folders.SwssItems" href="known_folders.html#exchangelib.folders.known_folders.SwssItems">SwssItems</a></li> | |
3034 | 3128 | <li><a title="exchangelib.folders.known_folders.System" href="known_folders.html#exchangelib.folders.known_folders.System">System</a></li> |
3035 | 3129 | <li><a title="exchangelib.folders.known_folders.System1" href="known_folders.html#exchangelib.folders.known_folders.System1">System1</a></li> |
3036 | 3130 | <li><a title="exchangelib.folders.known_folders.Tasks" href="known_folders.html#exchangelib.folders.known_folders.Tasks">Tasks</a></li> |
33 | 33 | AdminAuditLogs, |
34 | 34 | AllContacts, |
35 | 35 | AllItems, |
36 | ApplicationData, | |
36 | 37 | ArchiveDeletedItems, |
37 | 38 | ArchiveInbox, |
38 | 39 | ArchiveMsgFolderRoot, |
41 | 42 | ArchiveRecoverableItemsRoot, |
42 | 43 | ArchiveRecoverableItemsVersions, |
43 | 44 | Audits, |
45 | Birthdays, | |
44 | 46 | Calendar, |
45 | 47 | CalendarLogging, |
46 | 48 | CommonViews, |
49 | 51 | Contacts, |
50 | 52 | ConversationHistory, |
51 | 53 | ConversationSettings, |
54 | CrawlerData, | |
52 | 55 | DefaultFoldersChangeHistory, |
53 | 56 | DeferredAction, |
54 | 57 | DeletedItems, |
55 | 58 | Directory, |
59 | DlpPolicyEvaluation, | |
56 | 60 | Drafts, |
57 | 61 | ExchangeSyncData, |
58 | 62 | Favorites, |
59 | 63 | Files, |
64 | FreeBusyCache, | |
60 | 65 | FreebusyData, |
61 | 66 | Friends, |
62 | 67 | GALContacts, |
87 | 92 | RecoverableItemsPurges, |
88 | 93 | RecoverableItemsRoot, |
89 | 94 | RecoverableItemsVersions, |
95 | RecoveryPoints, | |
90 | 96 | Reminders, |
91 | 97 | RSSFeeds, |
92 | 98 | Schedule, |
96 | 102 | Sharing, |
97 | 103 | Shortcuts, |
98 | 104 | Signal, |
105 | SkypeTeamsMessages, | |
99 | 106 | SmsAndChatsSync, |
100 | 107 | SpoolerQueue, |
108 | SwssItems, | |
101 | 109 | SyncIssues, |
102 | 110 | System, |
103 | 111 | Tasks, |
112 | 120 | from .roots import ArchiveRoot, PublicFoldersRoot, Root, RootOfHierarchy |
113 | 121 | |
114 | 122 | __all__ = [ |
115 | "FolderId", | |
116 | "DistinguishedFolderId", | |
117 | "FolderCollection", | |
118 | "BaseFolder", | |
119 | "Folder", | |
120 | 123 | "AdminAuditLogs", |
121 | 124 | "AllContacts", |
122 | 125 | "AllItems", |
126 | "ApplicationData", | |
123 | 127 | "ArchiveDeletedItems", |
124 | 128 | "ArchiveInbox", |
125 | 129 | "ArchiveMsgFolderRoot", |
127 | 131 | "ArchiveRecoverableItemsPurges", |
128 | 132 | "ArchiveRecoverableItemsRoot", |
129 | 133 | "ArchiveRecoverableItemsVersions", |
134 | "ArchiveRoot", | |
130 | 135 | "Audits", |
136 | "BaseFolder", | |
137 | "Birthdays", | |
131 | 138 | "Calendar", |
132 | 139 | "CalendarLogging", |
133 | 140 | "CommonViews", |
141 | "Companies", | |
134 | 142 | "Conflicts", |
135 | 143 | "Contacts", |
136 | 144 | "ConversationHistory", |
137 | 145 | "ConversationSettings", |
146 | "CrawlerData", | |
147 | "DEEP", | |
138 | 148 | "DefaultFoldersChangeHistory", |
139 | 149 | "DeferredAction", |
140 | 150 | "DeletedItems", |
141 | 151 | "Directory", |
152 | "DistinguishedFolderId", | |
153 | "DlpPolicyEvaluation", | |
142 | 154 | "Drafts", |
143 | 155 | "ExchangeSyncData", |
156 | "FOLDER_TRAVERSAL_CHOICES", | |
144 | 157 | "Favorites", |
145 | 158 | "Files", |
159 | "Folder", | |
160 | "FolderCollection", | |
161 | "FolderId", | |
162 | "FolderQuerySet", | |
163 | "FreeBusyCache", | |
146 | 164 | "FreebusyData", |
147 | 165 | "Friends", |
148 | 166 | "GALContacts", |
158 | 176 | "MsgFolderRoot", |
159 | 177 | "MyContacts", |
160 | 178 | "MyContactsExtended", |
179 | "NON_DELETABLE_FOLDERS", | |
161 | 180 | "NonDeletableFolderMixin", |
162 | 181 | "Notes", |
182 | "OrganizationalContacts", | |
163 | 183 | "Outbox", |
164 | 184 | "ParkedMessages", |
165 | 185 | "PassThroughSearchResults", |
166 | 186 | "PdpProfileV2Secured", |
187 | "PeopleCentricConversationBuddies", | |
167 | 188 | "PeopleConnect", |
189 | "PublicFoldersRoot", | |
168 | 190 | "QuickContacts", |
169 | 191 | "RSSFeeds", |
170 | 192 | "RecipientCache", |
172 | 194 | "RecoverableItemsPurges", |
173 | 195 | "RecoverableItemsRoot", |
174 | 196 | "RecoverableItemsVersions", |
197 | "RecoveryPoints", | |
175 | 198 | "Reminders", |
199 | "Root", | |
200 | "RootOfHierarchy", | |
201 | "SHALLOW", | |
202 | "SOFT_DELETED", | |
176 | 203 | "Schedule", |
177 | 204 | "SearchFolders", |
178 | 205 | "SentItems", |
180 | 207 | "Sharing", |
181 | 208 | "Shortcuts", |
182 | 209 | "Signal", |
210 | "SingleFolderQuerySet", | |
211 | "SkypeTeamsMessages", | |
183 | 212 | "SmsAndChatsSync", |
184 | 213 | "SpoolerQueue", |
214 | "SwssItems", | |
185 | 215 | "SyncIssues", |
186 | 216 | "System", |
187 | 217 | "Tasks", |
191 | 221 | "VoiceMail", |
192 | 222 | "WellknownFolder", |
193 | 223 | "WorkingSet", |
194 | "Companies", | |
195 | "OrganizationalContacts", | |
196 | "PeopleCentricConversationBuddies", | |
197 | "NON_DELETABLE_FOLDERS", | |
198 | "FolderQuerySet", | |
199 | "SingleFolderQuerySet", | |
200 | "FOLDER_TRAVERSAL_CHOICES", | |
201 | "SHALLOW", | |
202 | "DEEP", | |
203 | "SOFT_DELETED", | |
204 | "Root", | |
205 | "ArchiveRoot", | |
206 | "PublicFoldersRoot", | |
207 | "RootOfHierarchy", | |
208 | 224 | ]</code></pre> |
209 | 225 | </details> |
210 | 226 | </section> |
431 | 447 | <div class="desc"></div> |
432 | 448 | </dd> |
433 | 449 | <dt id="exchangelib.folders.AllItems.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> |
450 | <dd> | |
451 | <div class="desc"></div> | |
452 | </dd> | |
453 | </dl> | |
454 | <h3>Inherited members</h3> | |
455 | <ul class="hlist"> | |
456 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
457 | <ul class="hlist"> | |
458 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
459 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
460 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
461 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
462 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
463 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
464 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
465 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
466 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
467 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
468 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
469 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
470 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
471 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
472 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
473 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
474 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
475 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
476 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
477 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
478 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
479 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
480 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
481 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
482 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
483 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
484 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
485 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
486 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
487 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
488 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
489 | </ul> | |
490 | </li> | |
491 | </ul> | |
492 | </dd> | |
493 | <dt id="exchangelib.folders.ApplicationData"><code class="flex name class"> | |
494 | <span>class <span class="ident">ApplicationData</span></span> | |
495 | <span>(</span><span>**kwargs)</span> | |
496 | </code></dt> | |
497 | <dd> | |
498 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
499 | <details class="source"> | |
500 | <summary> | |
501 | <span>Expand source code</span> | |
502 | </summary> | |
503 | <pre><code class="python">class ApplicationData(NonDeletableFolderMixin, Folder): | |
504 | CONTAINER_CLASS = "IPM.ApplicationData"</code></pre> | |
505 | </details> | |
506 | <h3>Ancestors</h3> | |
507 | <ul class="hlist"> | |
508 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
509 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
510 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
511 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
512 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
513 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
514 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
515 | </ul> | |
516 | <h3>Class variables</h3> | |
517 | <dl> | |
518 | <dt id="exchangelib.folders.ApplicationData.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
434 | 519 | <dd> |
435 | 520 | <div class="desc"></div> |
436 | 521 | </dd> |
1341 | 1426 | :return: |
1342 | 1427 | """ |
1343 | 1428 | from .known_folders import ( |
1429 | ApplicationData, | |
1344 | 1430 | Calendar, |
1345 | 1431 | Contacts, |
1346 | 1432 | ConversationSettings, |
1433 | CrawlerData, | |
1434 | DlpPolicyEvaluation, | |
1435 | FreeBusyCache, | |
1347 | 1436 | GALContacts, |
1348 | 1437 | Messages, |
1349 | 1438 | RecipientCache, |
1439 | RecoveryPoints, | |
1350 | 1440 | Reminders, |
1351 | 1441 | RSSFeeds, |
1442 | Signal, | |
1443 | SwssItems, | |
1352 | 1444 | Tasks, |
1353 | 1445 | ) |
1354 | 1446 | |
1355 | 1447 | for folder_cls in ( |
1448 | ApplicationData, | |
1449 | Calendar, | |
1450 | Contacts, | |
1451 | ConversationSettings, | |
1452 | CrawlerData, | |
1453 | DlpPolicyEvaluation, | |
1454 | FreeBusyCache, | |
1455 | GALContacts, | |
1356 | 1456 | Messages, |
1457 | RSSFeeds, | |
1458 | RecipientCache, | |
1459 | RecoveryPoints, | |
1460 | Reminders, | |
1461 | Signal, | |
1462 | SwssItems, | |
1357 | 1463 | Tasks, |
1358 | Calendar, | |
1359 | ConversationSettings, | |
1360 | Contacts, | |
1361 | GALContacts, | |
1362 | Reminders, | |
1363 | RecipientCache, | |
1364 | RSSFeeds, | |
1365 | 1464 | ): |
1366 | 1465 | if folder_cls.CONTAINER_CLASS == container_class: |
1367 | 1466 | return folder_cls |
1514 | 1613 | def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
1515 | 1614 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
1516 | 1615 | # distinguished folders from being deleted. Use with caution! |
1616 | from .known_folders import Audits | |
1617 | ||
1517 | 1618 | _seen = _seen or set() |
1518 | 1619 | if self.id in _seen: |
1519 | 1620 | raise RecursionError(f"We already tried to wipe {self}") |
1520 | 1621 | if _level > 16: |
1521 | 1622 | raise RecursionError(f"Max recursion level reached: {_level}") |
1522 | 1623 | _seen.add(self.id) |
1624 | if isinstance(self, Audits): | |
1625 | # Shortcircuit because this folder can have many items that are all non-deletable | |
1626 | log.warning("Cannot wipe audits folder %s", self) | |
1627 | return | |
1628 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
1629 | log.warning("Cannot wipe recoverable items folder %s", self) | |
1630 | return | |
1523 | 1631 | log.warning("Wiping %s", self) |
1524 | 1632 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
1525 | 1633 | try: |
1527 | 1635 | self.empty(delete_sub_folders=False) |
1528 | 1636 | else: |
1529 | 1637 | self.empty(delete_sub_folders=True) |
1530 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
1638 | except ErrorRecoverableItemsAccessDenied: | |
1639 | log.warning("Access denied to %s. Skipping", self) | |
1640 | return | |
1641 | except DELETE_FOLDER_ERRORS: | |
1531 | 1642 | try: |
1532 | 1643 | if has_distinguished_subfolders: |
1533 | 1644 | raise # We already tried this |
1534 | 1645 | self.empty(delete_sub_folders=False) |
1535 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
1646 | except DELETE_FOLDER_ERRORS: | |
1536 | 1647 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
1537 | 1648 | kwargs = {} |
1538 | 1649 | if page_size is not None: |
1541 | 1652 | kwargs["chunk_size"] = chunk_size |
1542 | 1653 | try: |
1543 | 1654 | self.all().delete(**kwargs) |
1544 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
1655 | except DELETE_FOLDER_ERRORS: | |
1545 | 1656 | log.warning("Not allowed to delete items in %s", self) |
1546 | 1657 | _level += 1 |
1547 | 1658 | for f in self.children: |
1991 | 2102 | :return: |
1992 | 2103 | """ |
1993 | 2104 | from .known_folders import ( |
2105 | ApplicationData, | |
1994 | 2106 | Calendar, |
1995 | 2107 | Contacts, |
1996 | 2108 | ConversationSettings, |
2109 | CrawlerData, | |
2110 | DlpPolicyEvaluation, | |
2111 | FreeBusyCache, | |
1997 | 2112 | GALContacts, |
1998 | 2113 | Messages, |
1999 | 2114 | RecipientCache, |
2115 | RecoveryPoints, | |
2000 | 2116 | Reminders, |
2001 | 2117 | RSSFeeds, |
2118 | Signal, | |
2119 | SwssItems, | |
2002 | 2120 | Tasks, |
2003 | 2121 | ) |
2004 | 2122 | |
2005 | 2123 | for folder_cls in ( |
2124 | ApplicationData, | |
2125 | Calendar, | |
2126 | Contacts, | |
2127 | ConversationSettings, | |
2128 | CrawlerData, | |
2129 | DlpPolicyEvaluation, | |
2130 | FreeBusyCache, | |
2131 | GALContacts, | |
2006 | 2132 | Messages, |
2133 | RSSFeeds, | |
2134 | RecipientCache, | |
2135 | RecoveryPoints, | |
2136 | Reminders, | |
2137 | Signal, | |
2138 | SwssItems, | |
2007 | 2139 | Tasks, |
2008 | Calendar, | |
2009 | ConversationSettings, | |
2010 | Contacts, | |
2011 | GALContacts, | |
2012 | Reminders, | |
2013 | RecipientCache, | |
2014 | RSSFeeds, | |
2015 | 2140 | ): |
2016 | 2141 | if folder_cls.CONTAINER_CLASS == container_class: |
2017 | 2142 | return folder_cls |
3002 | 3127 | <pre><code class="python">def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
3003 | 3128 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
3004 | 3129 | # distinguished folders from being deleted. Use with caution! |
3130 | from .known_folders import Audits | |
3131 | ||
3005 | 3132 | _seen = _seen or set() |
3006 | 3133 | if self.id in _seen: |
3007 | 3134 | raise RecursionError(f"We already tried to wipe {self}") |
3008 | 3135 | if _level > 16: |
3009 | 3136 | raise RecursionError(f"Max recursion level reached: {_level}") |
3010 | 3137 | _seen.add(self.id) |
3138 | if isinstance(self, Audits): | |
3139 | # Shortcircuit because this folder can have many items that are all non-deletable | |
3140 | log.warning("Cannot wipe audits folder %s", self) | |
3141 | return | |
3142 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
3143 | log.warning("Cannot wipe recoverable items folder %s", self) | |
3144 | return | |
3011 | 3145 | log.warning("Wiping %s", self) |
3012 | 3146 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
3013 | 3147 | try: |
3015 | 3149 | self.empty(delete_sub_folders=False) |
3016 | 3150 | else: |
3017 | 3151 | self.empty(delete_sub_folders=True) |
3018 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
3152 | except ErrorRecoverableItemsAccessDenied: | |
3153 | log.warning("Access denied to %s. Skipping", self) | |
3154 | return | |
3155 | except DELETE_FOLDER_ERRORS: | |
3019 | 3156 | try: |
3020 | 3157 | if has_distinguished_subfolders: |
3021 | 3158 | raise # We already tried this |
3022 | 3159 | self.empty(delete_sub_folders=False) |
3023 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
3160 | except DELETE_FOLDER_ERRORS: | |
3024 | 3161 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
3025 | 3162 | kwargs = {} |
3026 | 3163 | if page_size is not None: |
3029 | 3166 | kwargs["chunk_size"] = chunk_size |
3030 | 3167 | try: |
3031 | 3168 | self.all().delete(**kwargs) |
3032 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
3169 | except DELETE_FOLDER_ERRORS: | |
3033 | 3170 | log.warning("Not allowed to delete items in %s", self) |
3034 | 3171 | _level += 1 |
3035 | 3172 | for f in self.children: |
3068 | 3205 | </li> |
3069 | 3206 | </ul> |
3070 | 3207 | </dd> |
3071 | <dt id="exchangelib.folders.Calendar"><code class="flex name class"> | |
3072 | <span>class <span class="ident">Calendar</span></span> | |
3208 | <dt id="exchangelib.folders.Birthdays"><code class="flex name class"> | |
3209 | <span>class <span class="ident">Birthdays</span></span> | |
3073 | 3210 | <span>(</span><span>**kwargs)</span> |
3074 | 3211 | </code></dt> |
3075 | 3212 | <dd> |
3076 | <div class="desc"><p>An interface for the Exchange calendar.</p></div> | |
3077 | <details class="source"> | |
3078 | <summary> | |
3079 | <span>Expand source code</span> | |
3080 | </summary> | |
3081 | <pre><code class="python">class Calendar(Folder): | |
3082 | """An interface for the Exchange calendar.""" | |
3083 | ||
3084 | DISTINGUISHED_FOLDER_ID = "calendar" | |
3085 | CONTAINER_CLASS = "IPF.Appointment" | |
3086 | supported_item_models = (CalendarItem,) | |
3087 | ||
3213 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
3214 | <details class="source"> | |
3215 | <summary> | |
3216 | <span>Expand source code</span> | |
3217 | </summary> | |
3218 | <pre><code class="python">class Birthdays(Folder): | |
3219 | CONTAINER_CLASS = "IPF.Appointment.Birthday" | |
3088 | 3220 | LOCALIZED_NAMES = { |
3089 | "da_DK": ("Kalender",), | |
3090 | "de_DE": ("Kalender",), | |
3091 | "en_US": ("Calendar",), | |
3092 | "es_ES": ("Calendario",), | |
3093 | "fr_CA": ("Calendrier",), | |
3094 | "nl_NL": ("Agenda",), | |
3095 | "ru_RU": ("Календарь",), | |
3096 | "sv_SE": ("Kalender",), | |
3097 | "zh_CN": ("日历",), | |
3098 | } | |
3099 | ||
3100 | def view(self, *args, **kwargs): | |
3101 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
3221 | None: ("Birthdays",), | |
3222 | "da_DK": ("Fødselsdage",), | |
3223 | }</code></pre> | |
3102 | 3224 | </details> |
3103 | 3225 | <h3>Ancestors</h3> |
3104 | 3226 | <ul class="hlist"> |
3111 | 3233 | </ul> |
3112 | 3234 | <h3>Class variables</h3> |
3113 | 3235 | <dl> |
3114 | <dt id="exchangelib.folders.Calendar.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3115 | <dd> | |
3116 | <div class="desc"></div> | |
3117 | </dd> | |
3118 | <dt id="exchangelib.folders.Calendar.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
3119 | <dd> | |
3120 | <div class="desc"></div> | |
3121 | </dd> | |
3122 | <dt id="exchangelib.folders.Calendar.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3123 | <dd> | |
3124 | <div class="desc"></div> | |
3125 | </dd> | |
3126 | <dt id="exchangelib.folders.Calendar.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
3127 | <dd> | |
3128 | <div class="desc"></div> | |
3129 | </dd> | |
3130 | </dl> | |
3131 | <h3>Methods</h3> | |
3132 | <dl> | |
3133 | <dt id="exchangelib.folders.Calendar.view"><code class="name flex"> | |
3134 | <span>def <span class="ident">view</span></span>(<span>self, *args, **kwargs)</span> | |
3135 | </code></dt> | |
3136 | <dd> | |
3137 | <div class="desc"></div> | |
3138 | <details class="source"> | |
3139 | <summary> | |
3140 | <span>Expand source code</span> | |
3141 | </summary> | |
3142 | <pre><code class="python">def view(self, *args, **kwargs): | |
3143 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
3144 | </details> | |
3236 | <dt id="exchangelib.folders.Birthdays.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3237 | <dd> | |
3238 | <div class="desc"></div> | |
3239 | </dd> | |
3240 | <dt id="exchangelib.folders.Birthdays.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3241 | <dd> | |
3242 | <div class="desc"></div> | |
3145 | 3243 | </dd> |
3146 | 3244 | </dl> |
3147 | 3245 | <h3>Inherited members</h3> |
3183 | 3281 | </li> |
3184 | 3282 | </ul> |
3185 | 3283 | </dd> |
3186 | <dt id="exchangelib.folders.CalendarLogging"><code class="flex name class"> | |
3187 | <span>class <span class="ident">CalendarLogging</span></span> | |
3284 | <dt id="exchangelib.folders.Calendar"><code class="flex name class"> | |
3285 | <span>class <span class="ident">Calendar</span></span> | |
3188 | 3286 | <span>(</span><span>**kwargs)</span> |
3189 | 3287 | </code></dt> |
3190 | 3288 | <dd> |
3191 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
3192 | <details class="source"> | |
3193 | <summary> | |
3194 | <span>Expand source code</span> | |
3195 | </summary> | |
3196 | <pre><code class="python">class CalendarLogging(NonDeletableFolderMixin, Folder): | |
3289 | <div class="desc"><p>An interface for the Exchange calendar.</p></div> | |
3290 | <details class="source"> | |
3291 | <summary> | |
3292 | <span>Expand source code</span> | |
3293 | </summary> | |
3294 | <pre><code class="python">class Calendar(Folder): | |
3295 | """An interface for the Exchange calendar.""" | |
3296 | ||
3297 | DISTINGUISHED_FOLDER_ID = "calendar" | |
3298 | CONTAINER_CLASS = "IPF.Appointment" | |
3299 | supported_item_models = (CalendarItem,) | |
3300 | ||
3197 | 3301 | LOCALIZED_NAMES = { |
3198 | None: ("Calendar Logging",), | |
3199 | }</code></pre> | |
3302 | "da_DK": ("Kalender",), | |
3303 | "de_DE": ("Kalender",), | |
3304 | "en_US": ("Calendar",), | |
3305 | "es_ES": ("Calendario",), | |
3306 | "fr_CA": ("Calendrier",), | |
3307 | "nl_NL": ("Agenda",), | |
3308 | "ru_RU": ("Календарь",), | |
3309 | "sv_SE": ("Kalender",), | |
3310 | "zh_CN": ("日历",), | |
3311 | } | |
3312 | ||
3313 | def view(self, *args, **kwargs): | |
3314 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
3200 | 3315 | </details> |
3201 | 3316 | <h3>Ancestors</h3> |
3202 | 3317 | <ul class="hlist"> |
3203 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
3204 | 3318 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> |
3205 | 3319 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> |
3206 | 3320 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> |
3210 | 3324 | </ul> |
3211 | 3325 | <h3>Class variables</h3> |
3212 | 3326 | <dl> |
3213 | <dt id="exchangelib.folders.CalendarLogging.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3214 | <dd> | |
3215 | <div class="desc"></div> | |
3327 | <dt id="exchangelib.folders.Calendar.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3328 | <dd> | |
3329 | <div class="desc"></div> | |
3330 | </dd> | |
3331 | <dt id="exchangelib.folders.Calendar.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
3332 | <dd> | |
3333 | <div class="desc"></div> | |
3334 | </dd> | |
3335 | <dt id="exchangelib.folders.Calendar.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3336 | <dd> | |
3337 | <div class="desc"></div> | |
3338 | </dd> | |
3339 | <dt id="exchangelib.folders.Calendar.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
3340 | <dd> | |
3341 | <div class="desc"></div> | |
3342 | </dd> | |
3343 | </dl> | |
3344 | <h3>Methods</h3> | |
3345 | <dl> | |
3346 | <dt id="exchangelib.folders.Calendar.view"><code class="name flex"> | |
3347 | <span>def <span class="ident">view</span></span>(<span>self, *args, **kwargs)</span> | |
3348 | </code></dt> | |
3349 | <dd> | |
3350 | <div class="desc"></div> | |
3351 | <details class="source"> | |
3352 | <summary> | |
3353 | <span>Expand source code</span> | |
3354 | </summary> | |
3355 | <pre><code class="python">def view(self, *args, **kwargs): | |
3356 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
3357 | </details> | |
3216 | 3358 | </dd> |
3217 | 3359 | </dl> |
3218 | 3360 | <h3>Inherited members</h3> |
3254 | 3396 | </li> |
3255 | 3397 | </ul> |
3256 | 3398 | </dd> |
3257 | <dt id="exchangelib.folders.CommonViews"><code class="flex name class"> | |
3258 | <span>class <span class="ident">CommonViews</span></span> | |
3399 | <dt id="exchangelib.folders.CalendarLogging"><code class="flex name class"> | |
3400 | <span>class <span class="ident">CalendarLogging</span></span> | |
3259 | 3401 | <span>(</span><span>**kwargs)</span> |
3260 | 3402 | </code></dt> |
3261 | 3403 | <dd> |
3264 | 3406 | <summary> |
3265 | 3407 | <span>Expand source code</span> |
3266 | 3408 | </summary> |
3267 | <pre><code class="python">class CommonViews(NonDeletableFolderMixin, Folder): | |
3268 | DEFAULT_ITEM_TRAVERSAL_DEPTH = ASSOCIATED | |
3409 | <pre><code class="python">class CalendarLogging(NonDeletableFolderMixin, Folder): | |
3269 | 3410 | LOCALIZED_NAMES = { |
3270 | None: ("Common Views",), | |
3411 | None: ("Calendar Logging",), | |
3271 | 3412 | }</code></pre> |
3272 | 3413 | </details> |
3273 | 3414 | <h3>Ancestors</h3> |
3282 | 3423 | </ul> |
3283 | 3424 | <h3>Class variables</h3> |
3284 | 3425 | <dl> |
3285 | <dt id="exchangelib.folders.CommonViews.DEFAULT_ITEM_TRAVERSAL_DEPTH"><code class="name">var <span class="ident">DEFAULT_ITEM_TRAVERSAL_DEPTH</span></code></dt> | |
3286 | <dd> | |
3287 | <div class="desc"></div> | |
3288 | </dd> | |
3289 | <dt id="exchangelib.folders.CommonViews.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3426 | <dt id="exchangelib.folders.CalendarLogging.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3290 | 3427 | <dd> |
3291 | 3428 | <div class="desc"></div> |
3292 | 3429 | </dd> |
3330 | 3467 | </li> |
3331 | 3468 | </ul> |
3332 | 3469 | </dd> |
3470 | <dt id="exchangelib.folders.CommonViews"><code class="flex name class"> | |
3471 | <span>class <span class="ident">CommonViews</span></span> | |
3472 | <span>(</span><span>**kwargs)</span> | |
3473 | </code></dt> | |
3474 | <dd> | |
3475 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
3476 | <details class="source"> | |
3477 | <summary> | |
3478 | <span>Expand source code</span> | |
3479 | </summary> | |
3480 | <pre><code class="python">class CommonViews(NonDeletableFolderMixin, Folder): | |
3481 | DEFAULT_ITEM_TRAVERSAL_DEPTH = ASSOCIATED | |
3482 | LOCALIZED_NAMES = { | |
3483 | None: ("Common Views",), | |
3484 | }</code></pre> | |
3485 | </details> | |
3486 | <h3>Ancestors</h3> | |
3487 | <ul class="hlist"> | |
3488 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
3489 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
3490 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
3491 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
3492 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
3493 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
3494 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
3495 | </ul> | |
3496 | <h3>Class variables</h3> | |
3497 | <dl> | |
3498 | <dt id="exchangelib.folders.CommonViews.DEFAULT_ITEM_TRAVERSAL_DEPTH"><code class="name">var <span class="ident">DEFAULT_ITEM_TRAVERSAL_DEPTH</span></code></dt> | |
3499 | <dd> | |
3500 | <div class="desc"></div> | |
3501 | </dd> | |
3502 | <dt id="exchangelib.folders.CommonViews.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3503 | <dd> | |
3504 | <div class="desc"></div> | |
3505 | </dd> | |
3506 | </dl> | |
3507 | <h3>Inherited members</h3> | |
3508 | <ul class="hlist"> | |
3509 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
3510 | <ul class="hlist"> | |
3511 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
3512 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
3513 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
3514 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
3515 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
3516 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
3517 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
3518 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
3519 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
3520 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
3521 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
3522 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
3523 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
3524 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
3525 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
3526 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
3527 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
3528 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
3529 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
3530 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
3531 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
3532 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
3533 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
3534 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
3535 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
3536 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
3537 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
3538 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
3539 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
3540 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
3541 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
3542 | </ul> | |
3543 | </li> | |
3544 | </ul> | |
3545 | </dd> | |
3333 | 3546 | <dt id="exchangelib.folders.Companies"><code class="flex name class"> |
3334 | 3547 | <span>class <span class="ident">Companies</span></span> |
3335 | 3548 | <span>(</span><span>**kwargs)</span> |
3345 | 3558 | CONTAINTER_CLASS = "IPF.Contact.Company" |
3346 | 3559 | LOCALIZED_NAMES = { |
3347 | 3560 | None: ("Companies",), |
3561 | "da_DK": ("Firmaer",), | |
3348 | 3562 | }</code></pre> |
3349 | 3563 | </details> |
3350 | 3564 | <h3>Ancestors</h3> |
3741 | 3955 | </li> |
3742 | 3956 | </ul> |
3743 | 3957 | </dd> |
3744 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory"><code class="flex name class"> | |
3745 | <span>class <span class="ident">DefaultFoldersChangeHistory</span></span> | |
3958 | <dt id="exchangelib.folders.CrawlerData"><code class="flex name class"> | |
3959 | <span>class <span class="ident">CrawlerData</span></span> | |
3746 | 3960 | <span>(</span><span>**kwargs)</span> |
3747 | 3961 | </code></dt> |
3748 | 3962 | <dd> |
3749 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
3750 | <details class="source"> | |
3751 | <summary> | |
3752 | <span>Expand source code</span> | |
3753 | </summary> | |
3754 | <pre><code class="python">class DefaultFoldersChangeHistory(NonDeletableFolderMixin, Folder): | |
3755 | CONTAINER_CLASS = "IPM.DefaultFolderHistoryItem" | |
3756 | LOCALIZED_NAMES = { | |
3757 | None: ("DefaultFoldersChangeHistory",), | |
3758 | }</code></pre> | |
3963 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
3964 | <details class="source"> | |
3965 | <summary> | |
3966 | <span>Expand source code</span> | |
3967 | </summary> | |
3968 | <pre><code class="python">class CrawlerData(Folder): | |
3969 | CONTAINER_CLASS = "IPF.StoreItem.CrawlerData"</code></pre> | |
3759 | 3970 | </details> |
3760 | 3971 | <h3>Ancestors</h3> |
3761 | 3972 | <ul class="hlist"> |
3762 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
3763 | 3973 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> |
3764 | 3974 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> |
3765 | 3975 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> |
3769 | 3979 | </ul> |
3770 | 3980 | <h3>Class variables</h3> |
3771 | 3981 | <dl> |
3772 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3773 | <dd> | |
3774 | <div class="desc"></div> | |
3775 | </dd> | |
3776 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3982 | <dt id="exchangelib.folders.CrawlerData.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3777 | 3983 | <dd> |
3778 | 3984 | <div class="desc"></div> |
3779 | 3985 | </dd> |
3817 | 4023 | </li> |
3818 | 4024 | </ul> |
3819 | 4025 | </dd> |
3820 | <dt id="exchangelib.folders.DeferredAction"><code class="flex name class"> | |
3821 | <span>class <span class="ident">DeferredAction</span></span> | |
4026 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory"><code class="flex name class"> | |
4027 | <span>class <span class="ident">DefaultFoldersChangeHistory</span></span> | |
3822 | 4028 | <span>(</span><span>**kwargs)</span> |
3823 | 4029 | </code></dt> |
3824 | 4030 | <dd> |
3827 | 4033 | <summary> |
3828 | 4034 | <span>Expand source code</span> |
3829 | 4035 | </summary> |
3830 | <pre><code class="python">class DeferredAction(NonDeletableFolderMixin, Folder): | |
4036 | <pre><code class="python">class DefaultFoldersChangeHistory(NonDeletableFolderMixin, Folder): | |
4037 | CONTAINER_CLASS = "IPM.DefaultFolderHistoryItem" | |
3831 | 4038 | LOCALIZED_NAMES = { |
3832 | None: ("Deferred Action",), | |
4039 | None: ("DefaultFoldersChangeHistory",), | |
3833 | 4040 | }</code></pre> |
3834 | 4041 | </details> |
3835 | 4042 | <h3>Ancestors</h3> |
3844 | 4051 | </ul> |
3845 | 4052 | <h3>Class variables</h3> |
3846 | 4053 | <dl> |
3847 | <dt id="exchangelib.folders.DeferredAction.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
4054 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
4055 | <dd> | |
4056 | <div class="desc"></div> | |
4057 | </dd> | |
4058 | <dt id="exchangelib.folders.DefaultFoldersChangeHistory.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3848 | 4059 | <dd> |
3849 | 4060 | <div class="desc"></div> |
3850 | 4061 | </dd> |
3888 | 4099 | </li> |
3889 | 4100 | </ul> |
3890 | 4101 | </dd> |
3891 | <dt id="exchangelib.folders.DeletedItems"><code class="flex name class"> | |
3892 | <span>class <span class="ident">DeletedItems</span></span> | |
4102 | <dt id="exchangelib.folders.DeferredAction"><code class="flex name class"> | |
4103 | <span>class <span class="ident">DeferredAction</span></span> | |
3893 | 4104 | <span>(</span><span>**kwargs)</span> |
3894 | 4105 | </code></dt> |
3895 | 4106 | <dd> |
3896 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
3897 | <details class="source"> | |
3898 | <summary> | |
3899 | <span>Expand source code</span> | |
3900 | </summary> | |
3901 | <pre><code class="python">class DeletedItems(Folder): | |
3902 | DISTINGUISHED_FOLDER_ID = "deleteditems" | |
3903 | CONTAINER_CLASS = "IPF.Note" | |
3904 | supported_item_models = ITEM_CLASSES | |
3905 | ||
4107 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
4108 | <details class="source"> | |
4109 | <summary> | |
4110 | <span>Expand source code</span> | |
4111 | </summary> | |
4112 | <pre><code class="python">class DeferredAction(NonDeletableFolderMixin, Folder): | |
3906 | 4113 | LOCALIZED_NAMES = { |
3907 | "da_DK": ("Slettet post",), | |
3908 | "de_DE": ("Gelöschte Elemente",), | |
3909 | "en_US": ("Deleted Items",), | |
3910 | "es_ES": ("Elementos eliminados",), | |
3911 | "fr_CA": ("Éléments supprimés",), | |
3912 | "nl_NL": ("Verwijderde items",), | |
3913 | "ru_RU": ("Удаленные",), | |
3914 | "sv_SE": ("Borttaget",), | |
3915 | "zh_CN": ("已删除邮件",), | |
4114 | None: ("Deferred Action",), | |
3916 | 4115 | }</code></pre> |
3917 | 4116 | </details> |
3918 | 4117 | <h3>Ancestors</h3> |
3919 | 4118 | <ul class="hlist"> |
4119 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
3920 | 4120 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> |
3921 | 4121 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> |
3922 | 4122 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> |
3926 | 4126 | </ul> |
3927 | 4127 | <h3>Class variables</h3> |
3928 | 4128 | <dl> |
3929 | <dt id="exchangelib.folders.DeletedItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
3930 | <dd> | |
3931 | <div class="desc"></div> | |
3932 | </dd> | |
3933 | <dt id="exchangelib.folders.DeletedItems.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
3934 | <dd> | |
3935 | <div class="desc"></div> | |
3936 | </dd> | |
3937 | <dt id="exchangelib.folders.DeletedItems.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3938 | <dd> | |
3939 | <div class="desc"></div> | |
3940 | </dd> | |
3941 | <dt id="exchangelib.folders.DeletedItems.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
4129 | <dt id="exchangelib.folders.DeferredAction.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3942 | 4130 | <dd> |
3943 | 4131 | <div class="desc"></div> |
3944 | 4132 | </dd> |
3982 | 4170 | </li> |
3983 | 4171 | </ul> |
3984 | 4172 | </dd> |
4173 | <dt id="exchangelib.folders.DeletedItems"><code class="flex name class"> | |
4174 | <span>class <span class="ident">DeletedItems</span></span> | |
4175 | <span>(</span><span>**kwargs)</span> | |
4176 | </code></dt> | |
4177 | <dd> | |
4178 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
4179 | <details class="source"> | |
4180 | <summary> | |
4181 | <span>Expand source code</span> | |
4182 | </summary> | |
4183 | <pre><code class="python">class DeletedItems(Folder): | |
4184 | DISTINGUISHED_FOLDER_ID = "deleteditems" | |
4185 | CONTAINER_CLASS = "IPF.Note" | |
4186 | supported_item_models = ITEM_CLASSES | |
4187 | ||
4188 | LOCALIZED_NAMES = { | |
4189 | "da_DK": ("Slettet post",), | |
4190 | "de_DE": ("Gelöschte Elemente",), | |
4191 | "en_US": ("Deleted Items",), | |
4192 | "es_ES": ("Elementos eliminados",), | |
4193 | "fr_CA": ("Éléments supprimés",), | |
4194 | "nl_NL": ("Verwijderde items",), | |
4195 | "ru_RU": ("Удаленные",), | |
4196 | "sv_SE": ("Borttaget",), | |
4197 | "zh_CN": ("已删除邮件",), | |
4198 | }</code></pre> | |
4199 | </details> | |
4200 | <h3>Ancestors</h3> | |
4201 | <ul class="hlist"> | |
4202 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
4203 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
4204 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
4205 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
4206 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
4207 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
4208 | </ul> | |
4209 | <h3>Class variables</h3> | |
4210 | <dl> | |
4211 | <dt id="exchangelib.folders.DeletedItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
4212 | <dd> | |
4213 | <div class="desc"></div> | |
4214 | </dd> | |
4215 | <dt id="exchangelib.folders.DeletedItems.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
4216 | <dd> | |
4217 | <div class="desc"></div> | |
4218 | </dd> | |
4219 | <dt id="exchangelib.folders.DeletedItems.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
4220 | <dd> | |
4221 | <div class="desc"></div> | |
4222 | </dd> | |
4223 | <dt id="exchangelib.folders.DeletedItems.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
4224 | <dd> | |
4225 | <div class="desc"></div> | |
4226 | </dd> | |
4227 | </dl> | |
4228 | <h3>Inherited members</h3> | |
4229 | <ul class="hlist"> | |
4230 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
4231 | <ul class="hlist"> | |
4232 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
4233 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
4234 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
4235 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
4236 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
4237 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
4238 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
4239 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
4240 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
4241 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
4242 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
4243 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
4244 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
4245 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
4246 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
4247 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
4248 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
4249 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
4250 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
4251 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
4252 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
4253 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
4254 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
4255 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
4256 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
4257 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
4258 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
4259 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
4260 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
4261 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
4262 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
4263 | </ul> | |
4264 | </li> | |
4265 | </ul> | |
4266 | </dd> | |
3985 | 4267 | <dt id="exchangelib.folders.Directory"><code class="flex name class"> |
3986 | 4268 | <span>class <span class="ident">Directory</span></span> |
3987 | 4269 | <span>(</span><span>**kwargs)</span> |
4135 | 4417 | <li><code><a title="exchangelib.properties.FolderId.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> |
4136 | 4418 | <li><code><a title="exchangelib.properties.FolderId.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> |
4137 | 4419 | <li><code><a title="exchangelib.properties.FolderId.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> |
4420 | </ul> | |
4421 | </li> | |
4422 | </ul> | |
4423 | </dd> | |
4424 | <dt id="exchangelib.folders.DlpPolicyEvaluation"><code class="flex name class"> | |
4425 | <span>class <span class="ident">DlpPolicyEvaluation</span></span> | |
4426 | <span>(</span><span>**kwargs)</span> | |
4427 | </code></dt> | |
4428 | <dd> | |
4429 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
4430 | <details class="source"> | |
4431 | <summary> | |
4432 | <span>Expand source code</span> | |
4433 | </summary> | |
4434 | <pre><code class="python">class DlpPolicyEvaluation(Folder): | |
4435 | CONTAINER_CLASS = "IPF.StoreItem.DlpPolicyEvaluation"</code></pre> | |
4436 | </details> | |
4437 | <h3>Ancestors</h3> | |
4438 | <ul class="hlist"> | |
4439 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
4440 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
4441 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
4442 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
4443 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
4444 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
4445 | </ul> | |
4446 | <h3>Class variables</h3> | |
4447 | <dl> | |
4448 | <dt id="exchangelib.folders.DlpPolicyEvaluation.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
4449 | <dd> | |
4450 | <div class="desc"></div> | |
4451 | </dd> | |
4452 | </dl> | |
4453 | <h3>Inherited members</h3> | |
4454 | <ul class="hlist"> | |
4455 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
4456 | <ul class="hlist"> | |
4457 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
4458 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
4459 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
4460 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
4461 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
4462 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
4463 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
4464 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
4465 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
4466 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
4467 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
4468 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
4469 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
4470 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
4471 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
4472 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
4473 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
4474 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
4475 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
4476 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
4477 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
4478 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
4479 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
4480 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
4481 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
4482 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
4483 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
4484 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
4485 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
4486 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
4487 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
4138 | 4488 | </ul> |
4139 | 4489 | </li> |
4140 | 4490 | </ul> |
4602 | 4952 | <h3>Subclasses</h3> |
4603 | 4953 | <ul class="hlist"> |
4604 | 4954 | <li><a title="exchangelib.folders.known_folders.AllItems" href="known_folders.html#exchangelib.folders.known_folders.AllItems">AllItems</a></li> |
4955 | <li><a title="exchangelib.folders.known_folders.ApplicationData" href="known_folders.html#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></li> | |
4605 | 4956 | <li><a title="exchangelib.folders.known_folders.Audits" href="known_folders.html#exchangelib.folders.known_folders.Audits">Audits</a></li> |
4957 | <li><a title="exchangelib.folders.known_folders.Birthdays" href="known_folders.html#exchangelib.folders.known_folders.Birthdays">Birthdays</a></li> | |
4606 | 4958 | <li><a title="exchangelib.folders.known_folders.Calendar" href="known_folders.html#exchangelib.folders.known_folders.Calendar">Calendar</a></li> |
4607 | 4959 | <li><a title="exchangelib.folders.known_folders.CalendarLogging" href="known_folders.html#exchangelib.folders.known_folders.CalendarLogging">CalendarLogging</a></li> |
4608 | 4960 | <li><a title="exchangelib.folders.known_folders.CommonViews" href="known_folders.html#exchangelib.folders.known_folders.CommonViews">CommonViews</a></li> |
4609 | 4961 | <li><a title="exchangelib.folders.known_folders.Contacts" href="known_folders.html#exchangelib.folders.known_folders.Contacts">Contacts</a></li> |
4610 | 4962 | <li><a title="exchangelib.folders.known_folders.ConversationSettings" href="known_folders.html#exchangelib.folders.known_folders.ConversationSettings">ConversationSettings</a></li> |
4963 | <li><a title="exchangelib.folders.known_folders.CrawlerData" href="known_folders.html#exchangelib.folders.known_folders.CrawlerData">CrawlerData</a></li> | |
4611 | 4964 | <li><a title="exchangelib.folders.known_folders.DefaultFoldersChangeHistory" href="known_folders.html#exchangelib.folders.known_folders.DefaultFoldersChangeHistory">DefaultFoldersChangeHistory</a></li> |
4612 | 4965 | <li><a title="exchangelib.folders.known_folders.DeferredAction" href="known_folders.html#exchangelib.folders.known_folders.DeferredAction">DeferredAction</a></li> |
4613 | 4966 | <li><a title="exchangelib.folders.known_folders.DeletedItems" href="known_folders.html#exchangelib.folders.known_folders.DeletedItems">DeletedItems</a></li> |
4967 | <li><a title="exchangelib.folders.known_folders.DlpPolicyEvaluation" href="known_folders.html#exchangelib.folders.known_folders.DlpPolicyEvaluation">DlpPolicyEvaluation</a></li> | |
4614 | 4968 | <li><a title="exchangelib.folders.known_folders.ExchangeSyncData" href="known_folders.html#exchangelib.folders.known_folders.ExchangeSyncData">ExchangeSyncData</a></li> |
4615 | 4969 | <li><a title="exchangelib.folders.known_folders.Files" href="known_folders.html#exchangelib.folders.known_folders.Files">Files</a></li> |
4970 | <li><a title="exchangelib.folders.known_folders.FreeBusyCache" href="known_folders.html#exchangelib.folders.known_folders.FreeBusyCache">FreeBusyCache</a></li> | |
4616 | 4971 | <li><a title="exchangelib.folders.known_folders.FreebusyData" href="known_folders.html#exchangelib.folders.known_folders.FreebusyData">FreebusyData</a></li> |
4617 | 4972 | <li><a title="exchangelib.folders.known_folders.GraphAnalytics" href="known_folders.html#exchangelib.folders.known_folders.GraphAnalytics">GraphAnalytics</a></li> |
4618 | 4973 | <li><a title="exchangelib.folders.known_folders.Location" href="known_folders.html#exchangelib.folders.known_folders.Location">Location</a></li> |
4622 | 4977 | <li><a title="exchangelib.folders.known_folders.PassThroughSearchResults" href="known_folders.html#exchangelib.folders.known_folders.PassThroughSearchResults">PassThroughSearchResults</a></li> |
4623 | 4978 | <li><a title="exchangelib.folders.known_folders.PdpProfileV2Secured" href="known_folders.html#exchangelib.folders.known_folders.PdpProfileV2Secured">PdpProfileV2Secured</a></li> |
4624 | 4979 | <li><a title="exchangelib.folders.known_folders.RSSFeeds" href="known_folders.html#exchangelib.folders.known_folders.RSSFeeds">RSSFeeds</a></li> |
4980 | <li><a title="exchangelib.folders.known_folders.RecoveryPoints" href="known_folders.html#exchangelib.folders.known_folders.RecoveryPoints">RecoveryPoints</a></li> | |
4625 | 4981 | <li><a title="exchangelib.folders.known_folders.Reminders" href="known_folders.html#exchangelib.folders.known_folders.Reminders">Reminders</a></li> |
4626 | 4982 | <li><a title="exchangelib.folders.known_folders.Schedule" href="known_folders.html#exchangelib.folders.known_folders.Schedule">Schedule</a></li> |
4627 | 4983 | <li><a title="exchangelib.folders.known_folders.Sharing" href="known_folders.html#exchangelib.folders.known_folders.Sharing">Sharing</a></li> |
4628 | 4984 | <li><a title="exchangelib.folders.known_folders.Shortcuts" href="known_folders.html#exchangelib.folders.known_folders.Shortcuts">Shortcuts</a></li> |
4629 | 4985 | <li><a title="exchangelib.folders.known_folders.Signal" href="known_folders.html#exchangelib.folders.known_folders.Signal">Signal</a></li> |
4986 | <li><a title="exchangelib.folders.known_folders.SkypeTeamsMessages" href="known_folders.html#exchangelib.folders.known_folders.SkypeTeamsMessages">SkypeTeamsMessages</a></li> | |
4630 | 4987 | <li><a title="exchangelib.folders.known_folders.SmsAndChatsSync" href="known_folders.html#exchangelib.folders.known_folders.SmsAndChatsSync">SmsAndChatsSync</a></li> |
4631 | 4988 | <li><a title="exchangelib.folders.known_folders.SpoolerQueue" href="known_folders.html#exchangelib.folders.known_folders.SpoolerQueue">SpoolerQueue</a></li> |
4989 | <li><a title="exchangelib.folders.known_folders.SwssItems" href="known_folders.html#exchangelib.folders.known_folders.SwssItems">SwssItems</a></li> | |
4632 | 4990 | <li><a title="exchangelib.folders.known_folders.System" href="known_folders.html#exchangelib.folders.known_folders.System">System</a></li> |
4633 | 4991 | <li><a title="exchangelib.folders.known_folders.System1" href="known_folders.html#exchangelib.folders.known_folders.System1">System1</a></li> |
4634 | 4992 | <li><a title="exchangelib.folders.known_folders.Tasks" href="known_folders.html#exchangelib.folders.known_folders.Tasks">Tasks</a></li> |
6060 | 6418 | <h3>Subclasses</h3> |
6061 | 6419 | <ul class="hlist"> |
6062 | 6420 | <li><a title="exchangelib.properties.DistinguishedFolderId" href="../properties.html#exchangelib.properties.DistinguishedFolderId">DistinguishedFolderId</a></li> |
6421 | <li><a title="exchangelib.properties.OldFolderId" href="../properties.html#exchangelib.properties.OldFolderId">OldFolderId</a></li> | |
6063 | 6422 | </ul> |
6064 | 6423 | <h3>Class variables</h3> |
6065 | 6424 | <dl> |
6353 | 6712 | </dd> |
6354 | 6713 | </dl> |
6355 | 6714 | </dd> |
6356 | <dt id="exchangelib.folders.FreebusyData"><code class="flex name class"> | |
6357 | <span>class <span class="ident">FreebusyData</span></span> | |
6715 | <dt id="exchangelib.folders.FreeBusyCache"><code class="flex name class"> | |
6716 | <span>class <span class="ident">FreeBusyCache</span></span> | |
6358 | 6717 | <span>(</span><span>**kwargs)</span> |
6359 | 6718 | </code></dt> |
6360 | 6719 | <dd> |
6361 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
6362 | <details class="source"> | |
6363 | <summary> | |
6364 | <span>Expand source code</span> | |
6365 | </summary> | |
6366 | <pre><code class="python">class FreebusyData(NonDeletableFolderMixin, Folder): | |
6367 | LOCALIZED_NAMES = { | |
6368 | None: ("Freebusy Data",), | |
6369 | }</code></pre> | |
6720 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
6721 | <details class="source"> | |
6722 | <summary> | |
6723 | <span>Expand source code</span> | |
6724 | </summary> | |
6725 | <pre><code class="python">class FreeBusyCache(Folder): | |
6726 | CONTAINER_CLASS = "IPF.StoreItem.FreeBusyCache"</code></pre> | |
6370 | 6727 | </details> |
6371 | 6728 | <h3>Ancestors</h3> |
6372 | 6729 | <ul class="hlist"> |
6373 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
6374 | 6730 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> |
6375 | 6731 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> |
6376 | 6732 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> |
6380 | 6736 | </ul> |
6381 | 6737 | <h3>Class variables</h3> |
6382 | 6738 | <dl> |
6383 | <dt id="exchangelib.folders.FreebusyData.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
6739 | <dt id="exchangelib.folders.FreeBusyCache.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
6384 | 6740 | <dd> |
6385 | 6741 | <div class="desc"></div> |
6386 | 6742 | </dd> |
6424 | 6780 | </li> |
6425 | 6781 | </ul> |
6426 | 6782 | </dd> |
6783 | <dt id="exchangelib.folders.FreebusyData"><code class="flex name class"> | |
6784 | <span>class <span class="ident">FreebusyData</span></span> | |
6785 | <span>(</span><span>**kwargs)</span> | |
6786 | </code></dt> | |
6787 | <dd> | |
6788 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
6789 | <details class="source"> | |
6790 | <summary> | |
6791 | <span>Expand source code</span> | |
6792 | </summary> | |
6793 | <pre><code class="python">class FreebusyData(NonDeletableFolderMixin, Folder): | |
6794 | LOCALIZED_NAMES = { | |
6795 | None: ("Freebusy Data",), | |
6796 | }</code></pre> | |
6797 | </details> | |
6798 | <h3>Ancestors</h3> | |
6799 | <ul class="hlist"> | |
6800 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
6801 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
6802 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
6803 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
6804 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
6805 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6806 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
6807 | </ul> | |
6808 | <h3>Class variables</h3> | |
6809 | <dl> | |
6810 | <dt id="exchangelib.folders.FreebusyData.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
6811 | <dd> | |
6812 | <div class="desc"></div> | |
6813 | </dd> | |
6814 | </dl> | |
6815 | <h3>Inherited members</h3> | |
6816 | <ul class="hlist"> | |
6817 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
6818 | <ul class="hlist"> | |
6819 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
6820 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
6821 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6822 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
6823 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
6824 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
6825 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
6826 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
6827 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
6828 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
6829 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
6830 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
6831 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
6832 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
6833 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
6834 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
6835 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
6836 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
6837 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
6838 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6839 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
6840 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
6841 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
6842 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
6843 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6844 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
6845 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
6846 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
6847 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
6848 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
6849 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6850 | </ul> | |
6851 | </li> | |
6852 | </ul> | |
6853 | </dd> | |
6427 | 6854 | <dt id="exchangelib.folders.Friends"><code class="flex name class"> |
6428 | 6855 | <span>class <span class="ident">Friends</span></span> |
6429 | 6856 | <span>(</span><span>**kwargs)</span> |
7296 | 7723 | |
7297 | 7724 | DISTINGUISHED_FOLDER_ID = "msgfolderroot" |
7298 | 7725 | LOCALIZED_NAMES = { |
7726 | None: ("Top of Information Store",), | |
7727 | "da_DK": ("Informationslagerets øverste niveau",), | |
7299 | 7728 | "zh_CN": ("信息存储顶部",), |
7300 | 7729 | }</code></pre> |
7301 | 7730 | </details> |
7535 | 7964 | <ul class="hlist"> |
7536 | 7965 | <li><a title="exchangelib.folders.known_folders.AllContacts" href="known_folders.html#exchangelib.folders.known_folders.AllContacts">AllContacts</a></li> |
7537 | 7966 | <li><a title="exchangelib.folders.known_folders.AllItems" href="known_folders.html#exchangelib.folders.known_folders.AllItems">AllItems</a></li> |
7967 | <li><a title="exchangelib.folders.known_folders.ApplicationData" href="known_folders.html#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></li> | |
7538 | 7968 | <li><a title="exchangelib.folders.known_folders.Audits" href="known_folders.html#exchangelib.folders.known_folders.Audits">Audits</a></li> |
7539 | 7969 | <li><a title="exchangelib.folders.known_folders.CalendarLogging" href="known_folders.html#exchangelib.folders.known_folders.CalendarLogging">CalendarLogging</a></li> |
7540 | 7970 | <li><a title="exchangelib.folders.known_folders.CommonViews" href="known_folders.html#exchangelib.folders.known_folders.CommonViews">CommonViews</a></li> |
7767 | 8197 | "de_DE": ("Postausgang",), |
7768 | 8198 | "en_US": ("Outbox",), |
7769 | 8199 | "es_ES": ("Bandeja de salida",), |
7770 | "fr_CA": (u"Boîte d'envoi",), | |
8200 | "fr_CA": ("Boîte d'envoi",), | |
7771 | 8201 | "nl_NL": ("Postvak UIT",), |
7772 | 8202 | "ru_RU": ("Исходящие",), |
7773 | 8203 | "sv_SE": ("Utkorgen",), |
8923 | 9353 | <li><code><a title="exchangelib.folders.known_folders.WellknownFolder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> |
8924 | 9354 | <li><code><a title="exchangelib.folders.known_folders.WellknownFolder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> |
8925 | 9355 | <li><code><a title="exchangelib.folders.known_folders.WellknownFolder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> |
9356 | </ul> | |
9357 | </li> | |
9358 | </ul> | |
9359 | </dd> | |
9360 | <dt id="exchangelib.folders.RecoveryPoints"><code class="flex name class"> | |
9361 | <span>class <span class="ident">RecoveryPoints</span></span> | |
9362 | <span>(</span><span>**kwargs)</span> | |
9363 | </code></dt> | |
9364 | <dd> | |
9365 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
9366 | <details class="source"> | |
9367 | <summary> | |
9368 | <span>Expand source code</span> | |
9369 | </summary> | |
9370 | <pre><code class="python">class RecoveryPoints(Folder): | |
9371 | CONTAINER_CLASS = "IPF.StoreItem.RecoveryPoints"</code></pre> | |
9372 | </details> | |
9373 | <h3>Ancestors</h3> | |
9374 | <ul class="hlist"> | |
9375 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
9376 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
9377 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
9378 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
9379 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
9380 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
9381 | </ul> | |
9382 | <h3>Class variables</h3> | |
9383 | <dl> | |
9384 | <dt id="exchangelib.folders.RecoveryPoints.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
9385 | <dd> | |
9386 | <div class="desc"></div> | |
9387 | </dd> | |
9388 | </dl> | |
9389 | <h3>Inherited members</h3> | |
9390 | <ul class="hlist"> | |
9391 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
9392 | <ul class="hlist"> | |
9393 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
9394 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
9395 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
9396 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
9397 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
9398 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
9399 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
9400 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
9401 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
9402 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
9403 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
9404 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
9405 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
9406 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
9407 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
9408 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
9409 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
9410 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
9411 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
9412 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
9413 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
9414 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
9415 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
9416 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
9417 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
9418 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
9419 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
9420 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
9421 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
9422 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
9423 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
8926 | 9424 | </ul> |
8927 | 9425 | </li> |
8928 | 9426 | </ul> |
9350 | 9848 | :param folder_name: |
9351 | 9849 | :param locale: a string, e.g. 'da_DK' |
9352 | 9850 | """ |
9353 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
9851 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
9354 | 9852 | if folder_name.lower() in folder_cls.localized_names(locale): |
9355 | 9853 | return folder_cls |
9356 | 9854 | raise KeyError() |
9416 | 9914 | :param folder_name: |
9417 | 9915 | :param locale: a string, e.g. 'da_DK' |
9418 | 9916 | """ |
9419 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
9917 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
9420 | 9918 | if folder_name.lower() in folder_cls.localized_names(locale): |
9421 | 9919 | return folder_cls |
9422 | 9920 | raise KeyError()</code></pre> |
10225 | 10723 | </li> |
10226 | 10724 | </ul> |
10227 | 10725 | </dd> |
10228 | <dt id="exchangelib.folders.SmsAndChatsSync"><code class="flex name class"> | |
10229 | <span>class <span class="ident">SmsAndChatsSync</span></span> | |
10726 | <dt id="exchangelib.folders.SkypeTeamsMessages"><code class="flex name class"> | |
10727 | <span>class <span class="ident">SkypeTeamsMessages</span></span> | |
10230 | 10728 | <span>(</span><span>**kwargs)</span> |
10231 | 10729 | </code></dt> |
10232 | 10730 | <dd> |
10233 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
10234 | <details class="source"> | |
10235 | <summary> | |
10236 | <span>Expand source code</span> | |
10237 | </summary> | |
10238 | <pre><code class="python">class SmsAndChatsSync(NonDeletableFolderMixin, Folder): | |
10239 | CONTAINER_CLASS = "IPF.SmsAndChatsSync" | |
10731 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
10732 | <details class="source"> | |
10733 | <summary> | |
10734 | <span>Expand source code</span> | |
10735 | </summary> | |
10736 | <pre><code class="python">class SkypeTeamsMessages(Folder): | |
10737 | CONTAINER_CLASS = "IPF.SkypeTeams.Message" | |
10240 | 10738 | LOCALIZED_NAMES = { |
10241 | None: ("SmsAndChatsSync",), | |
10739 | None: ("Team-chat",), | |
10242 | 10740 | }</code></pre> |
10243 | 10741 | </details> |
10244 | 10742 | <h3>Ancestors</h3> |
10245 | 10743 | <ul class="hlist"> |
10246 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
10247 | 10744 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> |
10248 | 10745 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> |
10249 | 10746 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> |
10253 | 10750 | </ul> |
10254 | 10751 | <h3>Class variables</h3> |
10255 | 10752 | <dl> |
10256 | <dt id="exchangelib.folders.SmsAndChatsSync.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
10257 | <dd> | |
10258 | <div class="desc"></div> | |
10259 | </dd> | |
10260 | <dt id="exchangelib.folders.SmsAndChatsSync.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
10753 | <dt id="exchangelib.folders.SkypeTeamsMessages.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
10754 | <dd> | |
10755 | <div class="desc"></div> | |
10756 | </dd> | |
10757 | <dt id="exchangelib.folders.SkypeTeamsMessages.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
10261 | 10758 | <dd> |
10262 | 10759 | <div class="desc"></div> |
10263 | 10760 | </dd> |
10301 | 10798 | </li> |
10302 | 10799 | </ul> |
10303 | 10800 | </dd> |
10304 | <dt id="exchangelib.folders.SpoolerQueue"><code class="flex name class"> | |
10305 | <span>class <span class="ident">SpoolerQueue</span></span> | |
10801 | <dt id="exchangelib.folders.SmsAndChatsSync"><code class="flex name class"> | |
10802 | <span>class <span class="ident">SmsAndChatsSync</span></span> | |
10306 | 10803 | <span>(</span><span>**kwargs)</span> |
10307 | 10804 | </code></dt> |
10308 | 10805 | <dd> |
10311 | 10808 | <summary> |
10312 | 10809 | <span>Expand source code</span> |
10313 | 10810 | </summary> |
10314 | <pre><code class="python">class SpoolerQueue(NonDeletableFolderMixin, Folder): | |
10811 | <pre><code class="python">class SmsAndChatsSync(NonDeletableFolderMixin, Folder): | |
10812 | CONTAINER_CLASS = "IPF.SmsAndChatsSync" | |
10315 | 10813 | LOCALIZED_NAMES = { |
10316 | None: ("Spooler Queue",), | |
10814 | None: ("SmsAndChatsSync",), | |
10317 | 10815 | }</code></pre> |
10318 | 10816 | </details> |
10319 | 10817 | <h3>Ancestors</h3> |
10328 | 10826 | </ul> |
10329 | 10827 | <h3>Class variables</h3> |
10330 | 10828 | <dl> |
10331 | <dt id="exchangelib.folders.SpoolerQueue.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
10829 | <dt id="exchangelib.folders.SmsAndChatsSync.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
10830 | <dd> | |
10831 | <div class="desc"></div> | |
10832 | </dd> | |
10833 | <dt id="exchangelib.folders.SmsAndChatsSync.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
10332 | 10834 | <dd> |
10333 | 10835 | <div class="desc"></div> |
10334 | 10836 | </dd> |
10372 | 10874 | </li> |
10373 | 10875 | </ul> |
10374 | 10876 | </dd> |
10877 | <dt id="exchangelib.folders.SpoolerQueue"><code class="flex name class"> | |
10878 | <span>class <span class="ident">SpoolerQueue</span></span> | |
10879 | <span>(</span><span>**kwargs)</span> | |
10880 | </code></dt> | |
10881 | <dd> | |
10882 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
10883 | <details class="source"> | |
10884 | <summary> | |
10885 | <span>Expand source code</span> | |
10886 | </summary> | |
10887 | <pre><code class="python">class SpoolerQueue(NonDeletableFolderMixin, Folder): | |
10888 | LOCALIZED_NAMES = { | |
10889 | None: ("Spooler Queue",), | |
10890 | }</code></pre> | |
10891 | </details> | |
10892 | <h3>Ancestors</h3> | |
10893 | <ul class="hlist"> | |
10894 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="known_folders.html#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
10895 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
10896 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
10897 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
10898 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
10899 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
10900 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
10901 | </ul> | |
10902 | <h3>Class variables</h3> | |
10903 | <dl> | |
10904 | <dt id="exchangelib.folders.SpoolerQueue.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
10905 | <dd> | |
10906 | <div class="desc"></div> | |
10907 | </dd> | |
10908 | </dl> | |
10909 | <h3>Inherited members</h3> | |
10910 | <ul class="hlist"> | |
10911 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
10912 | <ul class="hlist"> | |
10913 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
10914 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
10915 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
10916 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
10917 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
10918 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
10919 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
10920 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
10921 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
10922 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
10923 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
10924 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
10925 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
10926 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
10927 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
10928 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
10929 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
10930 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
10931 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
10932 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
10933 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
10934 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
10935 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
10936 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
10937 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
10938 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
10939 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
10940 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
10941 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
10942 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
10943 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
10944 | </ul> | |
10945 | </li> | |
10946 | </ul> | |
10947 | </dd> | |
10948 | <dt id="exchangelib.folders.SwssItems"><code class="flex name class"> | |
10949 | <span>class <span class="ident">SwssItems</span></span> | |
10950 | <span>(</span><span>**kwargs)</span> | |
10951 | </code></dt> | |
10952 | <dd> | |
10953 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
10954 | <details class="source"> | |
10955 | <summary> | |
10956 | <span>Expand source code</span> | |
10957 | </summary> | |
10958 | <pre><code class="python">class SwssItems(Folder): | |
10959 | CONTAINER_CLASS = "IPF.StoreItem.SwssItems"</code></pre> | |
10960 | </details> | |
10961 | <h3>Ancestors</h3> | |
10962 | <ul class="hlist"> | |
10963 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
10964 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
10965 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
10966 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
10967 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
10968 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
10969 | </ul> | |
10970 | <h3>Class variables</h3> | |
10971 | <dl> | |
10972 | <dt id="exchangelib.folders.SwssItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
10973 | <dd> | |
10974 | <div class="desc"></div> | |
10975 | </dd> | |
10976 | </dl> | |
10977 | <h3>Inherited members</h3> | |
10978 | <ul class="hlist"> | |
10979 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
10980 | <ul class="hlist"> | |
10981 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
10982 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
10983 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
10984 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
10985 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
10986 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
10987 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
10988 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
10989 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
10990 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
10991 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
10992 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
10993 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
10994 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
10995 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
10996 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
10997 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
10998 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
10999 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
11000 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
11001 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
11002 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
11003 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
11004 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
11005 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
11006 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
11007 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
11008 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
11009 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
11010 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
11011 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
11012 | </ul> | |
11013 | </li> | |
11014 | </ul> | |
11015 | </dd> | |
10375 | 11016 | <dt id="exchangelib.folders.SyncIssues"><code class="flex name class"> |
10376 | 11017 | <span>class <span class="ident">SyncIssues</span></span> |
10377 | 11018 | <span>(</span><span>**kwargs)</span> |
11149 | 11790 | <ul class=""> |
11150 | 11791 | <li><code><a title="exchangelib.folders.AllItems.CONTAINER_CLASS" href="#exchangelib.folders.AllItems.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
11151 | 11792 | <li><code><a title="exchangelib.folders.AllItems.LOCALIZED_NAMES" href="#exchangelib.folders.AllItems.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
11793 | </ul> | |
11794 | </li> | |
11795 | <li> | |
11796 | <h4><code><a title="exchangelib.folders.ApplicationData" href="#exchangelib.folders.ApplicationData">ApplicationData</a></code></h4> | |
11797 | <ul class=""> | |
11798 | <li><code><a title="exchangelib.folders.ApplicationData.CONTAINER_CLASS" href="#exchangelib.folders.ApplicationData.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
11152 | 11799 | </ul> |
11153 | 11800 | </li> |
11154 | 11801 | <li> |
11289 | 11936 | </ul> |
11290 | 11937 | </li> |
11291 | 11938 | <li> |
11939 | <h4><code><a title="exchangelib.folders.Birthdays" href="#exchangelib.folders.Birthdays">Birthdays</a></code></h4> | |
11940 | <ul class=""> | |
11941 | <li><code><a title="exchangelib.folders.Birthdays.CONTAINER_CLASS" href="#exchangelib.folders.Birthdays.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
11942 | <li><code><a title="exchangelib.folders.Birthdays.LOCALIZED_NAMES" href="#exchangelib.folders.Birthdays.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> | |
11943 | </ul> | |
11944 | </li> | |
11945 | <li> | |
11292 | 11946 | <h4><code><a title="exchangelib.folders.Calendar" href="#exchangelib.folders.Calendar">Calendar</a></code></h4> |
11293 | 11947 | <ul class=""> |
11294 | 11948 | <li><code><a title="exchangelib.folders.Calendar.CONTAINER_CLASS" href="#exchangelib.folders.Calendar.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
11350 | 12004 | </ul> |
11351 | 12005 | </li> |
11352 | 12006 | <li> |
12007 | <h4><code><a title="exchangelib.folders.CrawlerData" href="#exchangelib.folders.CrawlerData">CrawlerData</a></code></h4> | |
12008 | <ul class=""> | |
12009 | <li><code><a title="exchangelib.folders.CrawlerData.CONTAINER_CLASS" href="#exchangelib.folders.CrawlerData.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
12010 | </ul> | |
12011 | </li> | |
12012 | <li> | |
11353 | 12013 | <h4><code><a title="exchangelib.folders.DefaultFoldersChangeHistory" href="#exchangelib.folders.DefaultFoldersChangeHistory">DefaultFoldersChangeHistory</a></code></h4> |
11354 | 12014 | <ul class=""> |
11355 | 12015 | <li><code><a title="exchangelib.folders.DefaultFoldersChangeHistory.CONTAINER_CLASS" href="#exchangelib.folders.DefaultFoldersChangeHistory.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
11385 | 12045 | <li><code><a title="exchangelib.folders.DistinguishedFolderId.FIELDS" href="#exchangelib.folders.DistinguishedFolderId.FIELDS">FIELDS</a></code></li> |
11386 | 12046 | <li><code><a title="exchangelib.folders.DistinguishedFolderId.clean" href="#exchangelib.folders.DistinguishedFolderId.clean">clean</a></code></li> |
11387 | 12047 | <li><code><a title="exchangelib.folders.DistinguishedFolderId.mailbox" href="#exchangelib.folders.DistinguishedFolderId.mailbox">mailbox</a></code></li> |
12048 | </ul> | |
12049 | </li> | |
12050 | <li> | |
12051 | <h4><code><a title="exchangelib.folders.DlpPolicyEvaluation" href="#exchangelib.folders.DlpPolicyEvaluation">DlpPolicyEvaluation</a></code></h4> | |
12052 | <ul class=""> | |
12053 | <li><code><a title="exchangelib.folders.DlpPolicyEvaluation.CONTAINER_CLASS" href="#exchangelib.folders.DlpPolicyEvaluation.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
11388 | 12054 | </ul> |
11389 | 12055 | </li> |
11390 | 12056 | <li> |
11470 | 12136 | </ul> |
11471 | 12137 | </li> |
11472 | 12138 | <li> |
12139 | <h4><code><a title="exchangelib.folders.FreeBusyCache" href="#exchangelib.folders.FreeBusyCache">FreeBusyCache</a></code></h4> | |
12140 | <ul class=""> | |
12141 | <li><code><a title="exchangelib.folders.FreeBusyCache.CONTAINER_CLASS" href="#exchangelib.folders.FreeBusyCache.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
12142 | </ul> | |
12143 | </li> | |
12144 | <li> | |
11473 | 12145 | <h4><code><a title="exchangelib.folders.FreebusyData" href="#exchangelib.folders.FreebusyData">FreebusyData</a></code></h4> |
11474 | 12146 | <ul class=""> |
11475 | 12147 | <li><code><a title="exchangelib.folders.FreebusyData.LOCALIZED_NAMES" href="#exchangelib.folders.FreebusyData.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
11698 | 12370 | <ul class=""> |
11699 | 12371 | <li><code><a title="exchangelib.folders.RecoverableItemsVersions.DISTINGUISHED_FOLDER_ID" href="#exchangelib.folders.RecoverableItemsVersions.DISTINGUISHED_FOLDER_ID">DISTINGUISHED_FOLDER_ID</a></code></li> |
11700 | 12372 | <li><code><a title="exchangelib.folders.RecoverableItemsVersions.supported_from" href="#exchangelib.folders.RecoverableItemsVersions.supported_from">supported_from</a></code></li> |
12373 | </ul> | |
12374 | </li> | |
12375 | <li> | |
12376 | <h4><code><a title="exchangelib.folders.RecoveryPoints" href="#exchangelib.folders.RecoveryPoints">RecoveryPoints</a></code></h4> | |
12377 | <ul class=""> | |
12378 | <li><code><a title="exchangelib.folders.RecoveryPoints.CONTAINER_CLASS" href="#exchangelib.folders.RecoveryPoints.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
11701 | 12379 | </ul> |
11702 | 12380 | </li> |
11703 | 12381 | <li> |
11786 | 12464 | </ul> |
11787 | 12465 | </li> |
11788 | 12466 | <li> |
12467 | <h4><code><a title="exchangelib.folders.SkypeTeamsMessages" href="#exchangelib.folders.SkypeTeamsMessages">SkypeTeamsMessages</a></code></h4> | |
12468 | <ul class=""> | |
12469 | <li><code><a title="exchangelib.folders.SkypeTeamsMessages.CONTAINER_CLASS" href="#exchangelib.folders.SkypeTeamsMessages.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
12470 | <li><code><a title="exchangelib.folders.SkypeTeamsMessages.LOCALIZED_NAMES" href="#exchangelib.folders.SkypeTeamsMessages.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> | |
12471 | </ul> | |
12472 | </li> | |
12473 | <li> | |
11789 | 12474 | <h4><code><a title="exchangelib.folders.SmsAndChatsSync" href="#exchangelib.folders.SmsAndChatsSync">SmsAndChatsSync</a></code></h4> |
11790 | 12475 | <ul class=""> |
11791 | 12476 | <li><code><a title="exchangelib.folders.SmsAndChatsSync.CONTAINER_CLASS" href="#exchangelib.folders.SmsAndChatsSync.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
11796 | 12481 | <h4><code><a title="exchangelib.folders.SpoolerQueue" href="#exchangelib.folders.SpoolerQueue">SpoolerQueue</a></code></h4> |
11797 | 12482 | <ul class=""> |
11798 | 12483 | <li><code><a title="exchangelib.folders.SpoolerQueue.LOCALIZED_NAMES" href="#exchangelib.folders.SpoolerQueue.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
12484 | </ul> | |
12485 | </li> | |
12486 | <li> | |
12487 | <h4><code><a title="exchangelib.folders.SwssItems" href="#exchangelib.folders.SwssItems">SwssItems</a></code></h4> | |
12488 | <ul class=""> | |
12489 | <li><code><a title="exchangelib.folders.SwssItems.CONTAINER_CLASS" href="#exchangelib.folders.SwssItems.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
11799 | 12490 | </ul> |
11800 | 12491 | </li> |
11801 | 12492 | <li> |
89 | 89 | supported_item_models = (Message, MeetingRequest, MeetingResponse, MeetingCancellation) |
90 | 90 | |
91 | 91 | |
92 | class CrawlerData(Folder): | |
93 | CONTAINER_CLASS = "IPF.StoreItem.CrawlerData" | |
94 | ||
95 | ||
96 | class DlpPolicyEvaluation(Folder): | |
97 | CONTAINER_CLASS = "IPF.StoreItem.DlpPolicyEvaluation" | |
98 | ||
99 | ||
100 | class FreeBusyCache(Folder): | |
101 | CONTAINER_CLASS = "IPF.StoreItem.FreeBusyCache" | |
102 | ||
103 | ||
104 | class RecoveryPoints(Folder): | |
105 | CONTAINER_CLASS = "IPF.StoreItem.RecoveryPoints" | |
106 | ||
107 | ||
108 | class SwssItems(Folder): | |
109 | CONTAINER_CLASS = "IPF.StoreItem.SwssItems" | |
110 | ||
111 | ||
112 | class SkypeTeamsMessages(Folder): | |
113 | CONTAINER_CLASS = "IPF.SkypeTeams.Message" | |
114 | LOCALIZED_NAMES = { | |
115 | None: ("Team-chat",), | |
116 | } | |
117 | ||
118 | ||
119 | class Birthdays(Folder): | |
120 | CONTAINER_CLASS = "IPF.Appointment.Birthday" | |
121 | LOCALIZED_NAMES = { | |
122 | None: ("Birthdays",), | |
123 | "da_DK": ("Fødselsdage",), | |
124 | } | |
125 | ||
126 | ||
92 | 127 | class Drafts(Messages): |
93 | 128 | DISTINGUISHED_FOLDER_ID = "drafts" |
94 | 129 | |
129 | 164 | "de_DE": ("Postausgang",), |
130 | 165 | "en_US": ("Outbox",), |
131 | 166 | "es_ES": ("Bandeja de salida",), |
132 | "fr_CA": (u"Boîte d'envoi",), | |
167 | "fr_CA": ("Boîte d'envoi",), | |
133 | 168 | "nl_NL": ("Postvak UIT",), |
134 | 169 | "ru_RU": ("Исходящие",), |
135 | 170 | "sv_SE": ("Utkorgen",), |
294 | 329 | |
295 | 330 | DISTINGUISHED_FOLDER_ID = "msgfolderroot" |
296 | 331 | LOCALIZED_NAMES = { |
332 | None: ("Top of Information Store",), | |
333 | "da_DK": ("Informationslagerets øverste niveau",), | |
297 | 334 | "zh_CN": ("信息存储顶部",), |
298 | 335 | } |
299 | 336 | |
408 | 445 | } |
409 | 446 | |
410 | 447 | |
448 | class ApplicationData(NonDeletableFolderMixin, Folder): | |
449 | CONTAINER_CLASS = "IPM.ApplicationData" | |
450 | ||
451 | ||
411 | 452 | class Audits(NonDeletableFolderMixin, Folder): |
412 | 453 | LOCALIZED_NAMES = { |
413 | 454 | None: ("Audits",), |
433 | 474 | CONTAINTER_CLASS = "IPF.Contact.Company" |
434 | 475 | LOCALIZED_NAMES = { |
435 | 476 | None: ("Companies",), |
477 | "da_DK": ("Firmaer",), | |
436 | 478 | } |
437 | 479 | |
438 | 480 | |
646 | 688 | NON_DELETABLE_FOLDERS = [ |
647 | 689 | AllContacts, |
648 | 690 | AllItems, |
691 | ApplicationData, | |
649 | 692 | Audits, |
650 | 693 | CalendarLogging, |
651 | 694 | CommonViews, |
725 | 768 | ArchiveRecoverableItemsPurges, |
726 | 769 | ArchiveRecoverableItemsRoot, |
727 | 770 | ArchiveRecoverableItemsVersions, |
771 | ] | |
772 | ||
773 | MISC_FOLDERS = [ | |
774 | CrawlerData, | |
775 | DlpPolicyEvaluation, | |
776 | FreeBusyCache, | |
777 | RecoveryPoints, | |
778 | SwssItems, | |
779 | SkypeTeamsMessages, | |
780 | Birthdays, | |
728 | 781 | ]</code></pre> |
729 | 782 | </details> |
730 | 783 | </section> |
971 | 1024 | </li> |
972 | 1025 | </ul> |
973 | 1026 | </dd> |
1027 | <dt id="exchangelib.folders.known_folders.ApplicationData"><code class="flex name class"> | |
1028 | <span>class <span class="ident">ApplicationData</span></span> | |
1029 | <span>(</span><span>**kwargs)</span> | |
1030 | </code></dt> | |
1031 | <dd> | |
1032 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
1033 | <details class="source"> | |
1034 | <summary> | |
1035 | <span>Expand source code</span> | |
1036 | </summary> | |
1037 | <pre><code class="python">class ApplicationData(NonDeletableFolderMixin, Folder): | |
1038 | CONTAINER_CLASS = "IPM.ApplicationData"</code></pre> | |
1039 | </details> | |
1040 | <h3>Ancestors</h3> | |
1041 | <ul class="hlist"> | |
1042 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
1043 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1044 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1045 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1046 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1047 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1048 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1049 | </ul> | |
1050 | <h3>Class variables</h3> | |
1051 | <dl> | |
1052 | <dt id="exchangelib.folders.known_folders.ApplicationData.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
1053 | <dd> | |
1054 | <div class="desc"></div> | |
1055 | </dd> | |
1056 | </dl> | |
1057 | <h3>Inherited members</h3> | |
1058 | <ul class="hlist"> | |
1059 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
1060 | <ul class="hlist"> | |
1061 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
1062 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
1063 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
1064 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
1065 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
1066 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
1067 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
1068 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
1069 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
1070 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
1071 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
1072 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
1073 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
1074 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
1075 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
1076 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
1077 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
1078 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
1079 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
1080 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
1081 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
1082 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
1083 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
1084 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
1085 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
1086 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
1087 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
1088 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
1089 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
1090 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
1091 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
1092 | </ul> | |
1093 | </li> | |
1094 | </ul> | |
1095 | </dd> | |
974 | 1096 | <dt id="exchangelib.folders.known_folders.ArchiveDeletedItems"><code class="flex name class"> |
975 | 1097 | <span>class <span class="ident">ArchiveDeletedItems</span></span> |
976 | 1098 | <span>(</span><span>**kwargs)</span> |
1565 | 1687 | </li> |
1566 | 1688 | </ul> |
1567 | 1689 | </dd> |
1568 | <dt id="exchangelib.folders.known_folders.Calendar"><code class="flex name class"> | |
1569 | <span>class <span class="ident">Calendar</span></span> | |
1570 | <span>(</span><span>**kwargs)</span> | |
1571 | </code></dt> | |
1572 | <dd> | |
1573 | <div class="desc"><p>An interface for the Exchange calendar.</p></div> | |
1574 | <details class="source"> | |
1575 | <summary> | |
1576 | <span>Expand source code</span> | |
1577 | </summary> | |
1578 | <pre><code class="python">class Calendar(Folder): | |
1579 | """An interface for the Exchange calendar.""" | |
1580 | ||
1581 | DISTINGUISHED_FOLDER_ID = "calendar" | |
1582 | CONTAINER_CLASS = "IPF.Appointment" | |
1583 | supported_item_models = (CalendarItem,) | |
1584 | ||
1585 | LOCALIZED_NAMES = { | |
1586 | "da_DK": ("Kalender",), | |
1587 | "de_DE": ("Kalender",), | |
1588 | "en_US": ("Calendar",), | |
1589 | "es_ES": ("Calendario",), | |
1590 | "fr_CA": ("Calendrier",), | |
1591 | "nl_NL": ("Agenda",), | |
1592 | "ru_RU": ("Календарь",), | |
1593 | "sv_SE": ("Kalender",), | |
1594 | "zh_CN": ("日历",), | |
1595 | } | |
1596 | ||
1597 | def view(self, *args, **kwargs): | |
1598 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
1599 | </details> | |
1600 | <h3>Ancestors</h3> | |
1601 | <ul class="hlist"> | |
1602 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1603 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1604 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1605 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1606 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1607 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1608 | </ul> | |
1609 | <h3>Class variables</h3> | |
1610 | <dl> | |
1611 | <dt id="exchangelib.folders.known_folders.Calendar.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
1612 | <dd> | |
1613 | <div class="desc"></div> | |
1614 | </dd> | |
1615 | <dt id="exchangelib.folders.known_folders.Calendar.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
1616 | <dd> | |
1617 | <div class="desc"></div> | |
1618 | </dd> | |
1619 | <dt id="exchangelib.folders.known_folders.Calendar.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1620 | <dd> | |
1621 | <div class="desc"></div> | |
1622 | </dd> | |
1623 | <dt id="exchangelib.folders.known_folders.Calendar.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
1624 | <dd> | |
1625 | <div class="desc"></div> | |
1626 | </dd> | |
1627 | </dl> | |
1628 | <h3>Methods</h3> | |
1629 | <dl> | |
1630 | <dt id="exchangelib.folders.known_folders.Calendar.view"><code class="name flex"> | |
1631 | <span>def <span class="ident">view</span></span>(<span>self, *args, **kwargs)</span> | |
1632 | </code></dt> | |
1633 | <dd> | |
1634 | <div class="desc"></div> | |
1635 | <details class="source"> | |
1636 | <summary> | |
1637 | <span>Expand source code</span> | |
1638 | </summary> | |
1639 | <pre><code class="python">def view(self, *args, **kwargs): | |
1640 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
1641 | </details> | |
1690 | <dt id="exchangelib.folders.known_folders.Birthdays"><code class="flex name class"> | |
1691 | <span>class <span class="ident">Birthdays</span></span> | |
1692 | <span>(</span><span>**kwargs)</span> | |
1693 | </code></dt> | |
1694 | <dd> | |
1695 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
1696 | <details class="source"> | |
1697 | <summary> | |
1698 | <span>Expand source code</span> | |
1699 | </summary> | |
1700 | <pre><code class="python">class Birthdays(Folder): | |
1701 | CONTAINER_CLASS = "IPF.Appointment.Birthday" | |
1702 | LOCALIZED_NAMES = { | |
1703 | None: ("Birthdays",), | |
1704 | "da_DK": ("Fødselsdage",), | |
1705 | }</code></pre> | |
1706 | </details> | |
1707 | <h3>Ancestors</h3> | |
1708 | <ul class="hlist"> | |
1709 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1710 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1711 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1712 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1713 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1714 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1715 | </ul> | |
1716 | <h3>Class variables</h3> | |
1717 | <dl> | |
1718 | <dt id="exchangelib.folders.known_folders.Birthdays.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
1719 | <dd> | |
1720 | <div class="desc"></div> | |
1721 | </dd> | |
1722 | <dt id="exchangelib.folders.known_folders.Birthdays.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1723 | <dd> | |
1724 | <div class="desc"></div> | |
1642 | 1725 | </dd> |
1643 | 1726 | </dl> |
1644 | 1727 | <h3>Inherited members</h3> |
1680 | 1763 | </li> |
1681 | 1764 | </ul> |
1682 | 1765 | </dd> |
1683 | <dt id="exchangelib.folders.known_folders.CalendarLogging"><code class="flex name class"> | |
1684 | <span>class <span class="ident">CalendarLogging</span></span> | |
1685 | <span>(</span><span>**kwargs)</span> | |
1686 | </code></dt> | |
1687 | <dd> | |
1688 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
1689 | <details class="source"> | |
1690 | <summary> | |
1691 | <span>Expand source code</span> | |
1692 | </summary> | |
1693 | <pre><code class="python">class CalendarLogging(NonDeletableFolderMixin, Folder): | |
1694 | LOCALIZED_NAMES = { | |
1695 | None: ("Calendar Logging",), | |
1696 | }</code></pre> | |
1697 | </details> | |
1698 | <h3>Ancestors</h3> | |
1699 | <ul class="hlist"> | |
1700 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
1701 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1702 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1703 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1704 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1705 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1706 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1707 | </ul> | |
1708 | <h3>Class variables</h3> | |
1709 | <dl> | |
1710 | <dt id="exchangelib.folders.known_folders.CalendarLogging.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1711 | <dd> | |
1712 | <div class="desc"></div> | |
1766 | <dt id="exchangelib.folders.known_folders.Calendar"><code class="flex name class"> | |
1767 | <span>class <span class="ident">Calendar</span></span> | |
1768 | <span>(</span><span>**kwargs)</span> | |
1769 | </code></dt> | |
1770 | <dd> | |
1771 | <div class="desc"><p>An interface for the Exchange calendar.</p></div> | |
1772 | <details class="source"> | |
1773 | <summary> | |
1774 | <span>Expand source code</span> | |
1775 | </summary> | |
1776 | <pre><code class="python">class Calendar(Folder): | |
1777 | """An interface for the Exchange calendar.""" | |
1778 | ||
1779 | DISTINGUISHED_FOLDER_ID = "calendar" | |
1780 | CONTAINER_CLASS = "IPF.Appointment" | |
1781 | supported_item_models = (CalendarItem,) | |
1782 | ||
1783 | LOCALIZED_NAMES = { | |
1784 | "da_DK": ("Kalender",), | |
1785 | "de_DE": ("Kalender",), | |
1786 | "en_US": ("Calendar",), | |
1787 | "es_ES": ("Calendario",), | |
1788 | "fr_CA": ("Calendrier",), | |
1789 | "nl_NL": ("Agenda",), | |
1790 | "ru_RU": ("Календарь",), | |
1791 | "sv_SE": ("Kalender",), | |
1792 | "zh_CN": ("日历",), | |
1793 | } | |
1794 | ||
1795 | def view(self, *args, **kwargs): | |
1796 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
1797 | </details> | |
1798 | <h3>Ancestors</h3> | |
1799 | <ul class="hlist"> | |
1800 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1801 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1802 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1803 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1804 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1805 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1806 | </ul> | |
1807 | <h3>Class variables</h3> | |
1808 | <dl> | |
1809 | <dt id="exchangelib.folders.known_folders.Calendar.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
1810 | <dd> | |
1811 | <div class="desc"></div> | |
1812 | </dd> | |
1813 | <dt id="exchangelib.folders.known_folders.Calendar.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
1814 | <dd> | |
1815 | <div class="desc"></div> | |
1816 | </dd> | |
1817 | <dt id="exchangelib.folders.known_folders.Calendar.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1818 | <dd> | |
1819 | <div class="desc"></div> | |
1820 | </dd> | |
1821 | <dt id="exchangelib.folders.known_folders.Calendar.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
1822 | <dd> | |
1823 | <div class="desc"></div> | |
1824 | </dd> | |
1825 | </dl> | |
1826 | <h3>Methods</h3> | |
1827 | <dl> | |
1828 | <dt id="exchangelib.folders.known_folders.Calendar.view"><code class="name flex"> | |
1829 | <span>def <span class="ident">view</span></span>(<span>self, *args, **kwargs)</span> | |
1830 | </code></dt> | |
1831 | <dd> | |
1832 | <div class="desc"></div> | |
1833 | <details class="source"> | |
1834 | <summary> | |
1835 | <span>Expand source code</span> | |
1836 | </summary> | |
1837 | <pre><code class="python">def view(self, *args, **kwargs): | |
1838 | return FolderCollection(account=self.account, folders=[self]).view(*args, **kwargs)</code></pre> | |
1839 | </details> | |
1713 | 1840 | </dd> |
1714 | 1841 | </dl> |
1715 | 1842 | <h3>Inherited members</h3> |
1751 | 1878 | </li> |
1752 | 1879 | </ul> |
1753 | 1880 | </dd> |
1754 | <dt id="exchangelib.folders.known_folders.CommonViews"><code class="flex name class"> | |
1755 | <span>class <span class="ident">CommonViews</span></span> | |
1881 | <dt id="exchangelib.folders.known_folders.CalendarLogging"><code class="flex name class"> | |
1882 | <span>class <span class="ident">CalendarLogging</span></span> | |
1756 | 1883 | <span>(</span><span>**kwargs)</span> |
1757 | 1884 | </code></dt> |
1758 | 1885 | <dd> |
1761 | 1888 | <summary> |
1762 | 1889 | <span>Expand source code</span> |
1763 | 1890 | </summary> |
1764 | <pre><code class="python">class CommonViews(NonDeletableFolderMixin, Folder): | |
1765 | DEFAULT_ITEM_TRAVERSAL_DEPTH = ASSOCIATED | |
1766 | LOCALIZED_NAMES = { | |
1767 | None: ("Common Views",), | |
1891 | <pre><code class="python">class CalendarLogging(NonDeletableFolderMixin, Folder): | |
1892 | LOCALIZED_NAMES = { | |
1893 | None: ("Calendar Logging",), | |
1768 | 1894 | }</code></pre> |
1769 | 1895 | </details> |
1770 | 1896 | <h3>Ancestors</h3> |
1779 | 1905 | </ul> |
1780 | 1906 | <h3>Class variables</h3> |
1781 | 1907 | <dl> |
1782 | <dt id="exchangelib.folders.known_folders.CommonViews.DEFAULT_ITEM_TRAVERSAL_DEPTH"><code class="name">var <span class="ident">DEFAULT_ITEM_TRAVERSAL_DEPTH</span></code></dt> | |
1783 | <dd> | |
1784 | <div class="desc"></div> | |
1785 | </dd> | |
1786 | <dt id="exchangelib.folders.known_folders.CommonViews.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1908 | <dt id="exchangelib.folders.known_folders.CalendarLogging.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1787 | 1909 | <dd> |
1788 | 1910 | <div class="desc"></div> |
1789 | 1911 | </dd> |
1827 | 1949 | </li> |
1828 | 1950 | </ul> |
1829 | 1951 | </dd> |
1952 | <dt id="exchangelib.folders.known_folders.CommonViews"><code class="flex name class"> | |
1953 | <span>class <span class="ident">CommonViews</span></span> | |
1954 | <span>(</span><span>**kwargs)</span> | |
1955 | </code></dt> | |
1956 | <dd> | |
1957 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
1958 | <details class="source"> | |
1959 | <summary> | |
1960 | <span>Expand source code</span> | |
1961 | </summary> | |
1962 | <pre><code class="python">class CommonViews(NonDeletableFolderMixin, Folder): | |
1963 | DEFAULT_ITEM_TRAVERSAL_DEPTH = ASSOCIATED | |
1964 | LOCALIZED_NAMES = { | |
1965 | None: ("Common Views",), | |
1966 | }</code></pre> | |
1967 | </details> | |
1968 | <h3>Ancestors</h3> | |
1969 | <ul class="hlist"> | |
1970 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
1971 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
1972 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
1973 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
1974 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
1975 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
1976 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
1977 | </ul> | |
1978 | <h3>Class variables</h3> | |
1979 | <dl> | |
1980 | <dt id="exchangelib.folders.known_folders.CommonViews.DEFAULT_ITEM_TRAVERSAL_DEPTH"><code class="name">var <span class="ident">DEFAULT_ITEM_TRAVERSAL_DEPTH</span></code></dt> | |
1981 | <dd> | |
1982 | <div class="desc"></div> | |
1983 | </dd> | |
1984 | <dt id="exchangelib.folders.known_folders.CommonViews.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
1985 | <dd> | |
1986 | <div class="desc"></div> | |
1987 | </dd> | |
1988 | </dl> | |
1989 | <h3>Inherited members</h3> | |
1990 | <ul class="hlist"> | |
1991 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
1992 | <ul class="hlist"> | |
1993 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
1994 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
1995 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
1996 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
1997 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
1998 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
1999 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
2000 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
2001 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
2002 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
2003 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
2004 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
2005 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
2006 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
2007 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
2008 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
2009 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
2010 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
2011 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
2012 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
2013 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
2014 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
2015 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
2016 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
2017 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
2018 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
2019 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
2020 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
2021 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
2022 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
2023 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
2024 | </ul> | |
2025 | </li> | |
2026 | </ul> | |
2027 | </dd> | |
1830 | 2028 | <dt id="exchangelib.folders.known_folders.Companies"><code class="flex name class"> |
1831 | 2029 | <span>class <span class="ident">Companies</span></span> |
1832 | 2030 | <span>(</span><span>**kwargs)</span> |
1842 | 2040 | CONTAINTER_CLASS = "IPF.Contact.Company" |
1843 | 2041 | LOCALIZED_NAMES = { |
1844 | 2042 | None: ("Companies",), |
2043 | "da_DK": ("Firmaer",), | |
1845 | 2044 | }</code></pre> |
1846 | 2045 | </details> |
1847 | 2046 | <h3>Ancestors</h3> |
2238 | 2437 | </li> |
2239 | 2438 | </ul> |
2240 | 2439 | </dd> |
2241 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory"><code class="flex name class"> | |
2242 | <span>class <span class="ident">DefaultFoldersChangeHistory</span></span> | |
2243 | <span>(</span><span>**kwargs)</span> | |
2244 | </code></dt> | |
2245 | <dd> | |
2246 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
2247 | <details class="source"> | |
2248 | <summary> | |
2249 | <span>Expand source code</span> | |
2250 | </summary> | |
2251 | <pre><code class="python">class DefaultFoldersChangeHistory(NonDeletableFolderMixin, Folder): | |
2252 | CONTAINER_CLASS = "IPM.DefaultFolderHistoryItem" | |
2253 | LOCALIZED_NAMES = { | |
2254 | None: ("DefaultFoldersChangeHistory",), | |
2255 | }</code></pre> | |
2256 | </details> | |
2257 | <h3>Ancestors</h3> | |
2258 | <ul class="hlist"> | |
2259 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
2260 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2261 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2262 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2263 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2264 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2265 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2266 | </ul> | |
2267 | <h3>Class variables</h3> | |
2268 | <dl> | |
2269 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2270 | <dd> | |
2271 | <div class="desc"></div> | |
2272 | </dd> | |
2273 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2440 | <dt id="exchangelib.folders.known_folders.CrawlerData"><code class="flex name class"> | |
2441 | <span>class <span class="ident">CrawlerData</span></span> | |
2442 | <span>(</span><span>**kwargs)</span> | |
2443 | </code></dt> | |
2444 | <dd> | |
2445 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
2446 | <details class="source"> | |
2447 | <summary> | |
2448 | <span>Expand source code</span> | |
2449 | </summary> | |
2450 | <pre><code class="python">class CrawlerData(Folder): | |
2451 | CONTAINER_CLASS = "IPF.StoreItem.CrawlerData"</code></pre> | |
2452 | </details> | |
2453 | <h3>Ancestors</h3> | |
2454 | <ul class="hlist"> | |
2455 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2456 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2457 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2458 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2459 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2460 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2461 | </ul> | |
2462 | <h3>Class variables</h3> | |
2463 | <dl> | |
2464 | <dt id="exchangelib.folders.known_folders.CrawlerData.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2274 | 2465 | <dd> |
2275 | 2466 | <div class="desc"></div> |
2276 | 2467 | </dd> |
2314 | 2505 | </li> |
2315 | 2506 | </ul> |
2316 | 2507 | </dd> |
2317 | <dt id="exchangelib.folders.known_folders.DeferredAction"><code class="flex name class"> | |
2318 | <span>class <span class="ident">DeferredAction</span></span> | |
2508 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory"><code class="flex name class"> | |
2509 | <span>class <span class="ident">DefaultFoldersChangeHistory</span></span> | |
2319 | 2510 | <span>(</span><span>**kwargs)</span> |
2320 | 2511 | </code></dt> |
2321 | 2512 | <dd> |
2324 | 2515 | <summary> |
2325 | 2516 | <span>Expand source code</span> |
2326 | 2517 | </summary> |
2327 | <pre><code class="python">class DeferredAction(NonDeletableFolderMixin, Folder): | |
2328 | LOCALIZED_NAMES = { | |
2329 | None: ("Deferred Action",), | |
2518 | <pre><code class="python">class DefaultFoldersChangeHistory(NonDeletableFolderMixin, Folder): | |
2519 | CONTAINER_CLASS = "IPM.DefaultFolderHistoryItem" | |
2520 | LOCALIZED_NAMES = { | |
2521 | None: ("DefaultFoldersChangeHistory",), | |
2330 | 2522 | }</code></pre> |
2331 | 2523 | </details> |
2332 | 2524 | <h3>Ancestors</h3> |
2341 | 2533 | </ul> |
2342 | 2534 | <h3>Class variables</h3> |
2343 | 2535 | <dl> |
2344 | <dt id="exchangelib.folders.known_folders.DeferredAction.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2536 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2537 | <dd> | |
2538 | <div class="desc"></div> | |
2539 | </dd> | |
2540 | <dt id="exchangelib.folders.known_folders.DefaultFoldersChangeHistory.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2345 | 2541 | <dd> |
2346 | 2542 | <div class="desc"></div> |
2347 | 2543 | </dd> |
2385 | 2581 | </li> |
2386 | 2582 | </ul> |
2387 | 2583 | </dd> |
2388 | <dt id="exchangelib.folders.known_folders.DeletedItems"><code class="flex name class"> | |
2389 | <span>class <span class="ident">DeletedItems</span></span> | |
2390 | <span>(</span><span>**kwargs)</span> | |
2391 | </code></dt> | |
2392 | <dd> | |
2393 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
2394 | <details class="source"> | |
2395 | <summary> | |
2396 | <span>Expand source code</span> | |
2397 | </summary> | |
2398 | <pre><code class="python">class DeletedItems(Folder): | |
2399 | DISTINGUISHED_FOLDER_ID = "deleteditems" | |
2400 | CONTAINER_CLASS = "IPF.Note" | |
2401 | supported_item_models = ITEM_CLASSES | |
2402 | ||
2403 | LOCALIZED_NAMES = { | |
2404 | "da_DK": ("Slettet post",), | |
2405 | "de_DE": ("Gelöschte Elemente",), | |
2406 | "en_US": ("Deleted Items",), | |
2407 | "es_ES": ("Elementos eliminados",), | |
2408 | "fr_CA": ("Éléments supprimés",), | |
2409 | "nl_NL": ("Verwijderde items",), | |
2410 | "ru_RU": ("Удаленные",), | |
2411 | "sv_SE": ("Borttaget",), | |
2412 | "zh_CN": ("已删除邮件",), | |
2584 | <dt id="exchangelib.folders.known_folders.DeferredAction"><code class="flex name class"> | |
2585 | <span>class <span class="ident">DeferredAction</span></span> | |
2586 | <span>(</span><span>**kwargs)</span> | |
2587 | </code></dt> | |
2588 | <dd> | |
2589 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
2590 | <details class="source"> | |
2591 | <summary> | |
2592 | <span>Expand source code</span> | |
2593 | </summary> | |
2594 | <pre><code class="python">class DeferredAction(NonDeletableFolderMixin, Folder): | |
2595 | LOCALIZED_NAMES = { | |
2596 | None: ("Deferred Action",), | |
2413 | 2597 | }</code></pre> |
2414 | 2598 | </details> |
2415 | 2599 | <h3>Ancestors</h3> |
2416 | 2600 | <ul class="hlist"> |
2417 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2418 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2419 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2420 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2421 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2422 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2423 | </ul> | |
2424 | <h3>Class variables</h3> | |
2425 | <dl> | |
2426 | <dt id="exchangelib.folders.known_folders.DeletedItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2427 | <dd> | |
2428 | <div class="desc"></div> | |
2429 | </dd> | |
2430 | <dt id="exchangelib.folders.known_folders.DeletedItems.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
2431 | <dd> | |
2432 | <div class="desc"></div> | |
2433 | </dd> | |
2434 | <dt id="exchangelib.folders.known_folders.DeletedItems.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2435 | <dd> | |
2436 | <div class="desc"></div> | |
2437 | </dd> | |
2438 | <dt id="exchangelib.folders.known_folders.DeletedItems.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
2601 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
2602 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2603 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2604 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2605 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2606 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2607 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2608 | </ul> | |
2609 | <h3>Class variables</h3> | |
2610 | <dl> | |
2611 | <dt id="exchangelib.folders.known_folders.DeferredAction.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2439 | 2612 | <dd> |
2440 | 2613 | <div class="desc"></div> |
2441 | 2614 | </dd> |
2479 | 2652 | </li> |
2480 | 2653 | </ul> |
2481 | 2654 | </dd> |
2655 | <dt id="exchangelib.folders.known_folders.DeletedItems"><code class="flex name class"> | |
2656 | <span>class <span class="ident">DeletedItems</span></span> | |
2657 | <span>(</span><span>**kwargs)</span> | |
2658 | </code></dt> | |
2659 | <dd> | |
2660 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
2661 | <details class="source"> | |
2662 | <summary> | |
2663 | <span>Expand source code</span> | |
2664 | </summary> | |
2665 | <pre><code class="python">class DeletedItems(Folder): | |
2666 | DISTINGUISHED_FOLDER_ID = "deleteditems" | |
2667 | CONTAINER_CLASS = "IPF.Note" | |
2668 | supported_item_models = ITEM_CLASSES | |
2669 | ||
2670 | LOCALIZED_NAMES = { | |
2671 | "da_DK": ("Slettet post",), | |
2672 | "de_DE": ("Gelöschte Elemente",), | |
2673 | "en_US": ("Deleted Items",), | |
2674 | "es_ES": ("Elementos eliminados",), | |
2675 | "fr_CA": ("Éléments supprimés",), | |
2676 | "nl_NL": ("Verwijderde items",), | |
2677 | "ru_RU": ("Удаленные",), | |
2678 | "sv_SE": ("Borttaget",), | |
2679 | "zh_CN": ("已删除邮件",), | |
2680 | }</code></pre> | |
2681 | </details> | |
2682 | <h3>Ancestors</h3> | |
2683 | <ul class="hlist"> | |
2684 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2685 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2686 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2687 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2688 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2689 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2690 | </ul> | |
2691 | <h3>Class variables</h3> | |
2692 | <dl> | |
2693 | <dt id="exchangelib.folders.known_folders.DeletedItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2694 | <dd> | |
2695 | <div class="desc"></div> | |
2696 | </dd> | |
2697 | <dt id="exchangelib.folders.known_folders.DeletedItems.DISTINGUISHED_FOLDER_ID"><code class="name">var <span class="ident">DISTINGUISHED_FOLDER_ID</span></code></dt> | |
2698 | <dd> | |
2699 | <div class="desc"></div> | |
2700 | </dd> | |
2701 | <dt id="exchangelib.folders.known_folders.DeletedItems.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
2702 | <dd> | |
2703 | <div class="desc"></div> | |
2704 | </dd> | |
2705 | <dt id="exchangelib.folders.known_folders.DeletedItems.supported_item_models"><code class="name">var <span class="ident">supported_item_models</span></code></dt> | |
2706 | <dd> | |
2707 | <div class="desc"></div> | |
2708 | </dd> | |
2709 | </dl> | |
2710 | <h3>Inherited members</h3> | |
2711 | <ul class="hlist"> | |
2712 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
2713 | <ul class="hlist"> | |
2714 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
2715 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
2716 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
2717 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
2718 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
2719 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
2720 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
2721 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
2722 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
2723 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
2724 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
2725 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
2726 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
2727 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
2728 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
2729 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
2730 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
2731 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
2732 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
2733 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
2734 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
2735 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
2736 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
2737 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
2738 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
2739 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
2740 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
2741 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
2742 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
2743 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
2744 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
2745 | </ul> | |
2746 | </li> | |
2747 | </ul> | |
2748 | </dd> | |
2482 | 2749 | <dt id="exchangelib.folders.known_folders.Directory"><code class="flex name class"> |
2483 | 2750 | <span>class <span class="ident">Directory</span></span> |
2484 | 2751 | <span>(</span><span>**kwargs)</span> |
2553 | 2820 | </li> |
2554 | 2821 | </ul> |
2555 | 2822 | </dd> |
2823 | <dt id="exchangelib.folders.known_folders.DlpPolicyEvaluation"><code class="flex name class"> | |
2824 | <span>class <span class="ident">DlpPolicyEvaluation</span></span> | |
2825 | <span>(</span><span>**kwargs)</span> | |
2826 | </code></dt> | |
2827 | <dd> | |
2828 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
2829 | <details class="source"> | |
2830 | <summary> | |
2831 | <span>Expand source code</span> | |
2832 | </summary> | |
2833 | <pre><code class="python">class DlpPolicyEvaluation(Folder): | |
2834 | CONTAINER_CLASS = "IPF.StoreItem.DlpPolicyEvaluation"</code></pre> | |
2835 | </details> | |
2836 | <h3>Ancestors</h3> | |
2837 | <ul class="hlist"> | |
2838 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2839 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2840 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2841 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2842 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2843 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2844 | </ul> | |
2845 | <h3>Class variables</h3> | |
2846 | <dl> | |
2847 | <dt id="exchangelib.folders.known_folders.DlpPolicyEvaluation.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2848 | <dd> | |
2849 | <div class="desc"></div> | |
2850 | </dd> | |
2851 | </dl> | |
2852 | <h3>Inherited members</h3> | |
2853 | <ul class="hlist"> | |
2854 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
2855 | <ul class="hlist"> | |
2856 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
2857 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
2858 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
2859 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
2860 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
2861 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
2862 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
2863 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
2864 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
2865 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
2866 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
2867 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
2868 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
2869 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
2870 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
2871 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
2872 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
2873 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
2874 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
2875 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
2876 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
2877 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
2878 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
2879 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
2880 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
2881 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
2882 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
2883 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
2884 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
2885 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
2886 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
2887 | </ul> | |
2888 | </li> | |
2889 | </ul> | |
2890 | </dd> | |
2556 | 2891 | <dt id="exchangelib.folders.known_folders.Drafts"><code class="flex name class"> |
2557 | 2892 | <span>class <span class="ident">Drafts</span></span> |
2558 | 2893 | <span>(</span><span>**kwargs)</span> |
2865 | 3200 | </li> |
2866 | 3201 | </ul> |
2867 | 3202 | </dd> |
2868 | <dt id="exchangelib.folders.known_folders.FreebusyData"><code class="flex name class"> | |
2869 | <span>class <span class="ident">FreebusyData</span></span> | |
2870 | <span>(</span><span>**kwargs)</span> | |
2871 | </code></dt> | |
2872 | <dd> | |
2873 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
2874 | <details class="source"> | |
2875 | <summary> | |
2876 | <span>Expand source code</span> | |
2877 | </summary> | |
2878 | <pre><code class="python">class FreebusyData(NonDeletableFolderMixin, Folder): | |
2879 | LOCALIZED_NAMES = { | |
2880 | None: ("Freebusy Data",), | |
2881 | }</code></pre> | |
2882 | </details> | |
2883 | <h3>Ancestors</h3> | |
2884 | <ul class="hlist"> | |
2885 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
2886 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
2887 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
2888 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
2889 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
2890 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
2891 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
2892 | </ul> | |
2893 | <h3>Class variables</h3> | |
2894 | <dl> | |
2895 | <dt id="exchangelib.folders.known_folders.FreebusyData.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3203 | <dt id="exchangelib.folders.known_folders.FreeBusyCache"><code class="flex name class"> | |
3204 | <span>class <span class="ident">FreeBusyCache</span></span> | |
3205 | <span>(</span><span>**kwargs)</span> | |
3206 | </code></dt> | |
3207 | <dd> | |
3208 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
3209 | <details class="source"> | |
3210 | <summary> | |
3211 | <span>Expand source code</span> | |
3212 | </summary> | |
3213 | <pre><code class="python">class FreeBusyCache(Folder): | |
3214 | CONTAINER_CLASS = "IPF.StoreItem.FreeBusyCache"</code></pre> | |
3215 | </details> | |
3216 | <h3>Ancestors</h3> | |
3217 | <ul class="hlist"> | |
3218 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
3219 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
3220 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
3221 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
3222 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
3223 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
3224 | </ul> | |
3225 | <h3>Class variables</h3> | |
3226 | <dl> | |
3227 | <dt id="exchangelib.folders.known_folders.FreeBusyCache.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
2896 | 3228 | <dd> |
2897 | 3229 | <div class="desc"></div> |
2898 | 3230 | </dd> |
2936 | 3268 | </li> |
2937 | 3269 | </ul> |
2938 | 3270 | </dd> |
3271 | <dt id="exchangelib.folders.known_folders.FreebusyData"><code class="flex name class"> | |
3272 | <span>class <span class="ident">FreebusyData</span></span> | |
3273 | <span>(</span><span>**kwargs)</span> | |
3274 | </code></dt> | |
3275 | <dd> | |
3276 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
3277 | <details class="source"> | |
3278 | <summary> | |
3279 | <span>Expand source code</span> | |
3280 | </summary> | |
3281 | <pre><code class="python">class FreebusyData(NonDeletableFolderMixin, Folder): | |
3282 | LOCALIZED_NAMES = { | |
3283 | None: ("Freebusy Data",), | |
3284 | }</code></pre> | |
3285 | </details> | |
3286 | <h3>Ancestors</h3> | |
3287 | <ul class="hlist"> | |
3288 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
3289 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
3290 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
3291 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
3292 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
3293 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
3294 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
3295 | </ul> | |
3296 | <h3>Class variables</h3> | |
3297 | <dl> | |
3298 | <dt id="exchangelib.folders.known_folders.FreebusyData.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
3299 | <dd> | |
3300 | <div class="desc"></div> | |
3301 | </dd> | |
3302 | </dl> | |
3303 | <h3>Inherited members</h3> | |
3304 | <ul class="hlist"> | |
3305 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
3306 | <ul class="hlist"> | |
3307 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
3308 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
3309 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
3310 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
3311 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
3312 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
3313 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
3314 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
3315 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
3316 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
3317 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
3318 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
3319 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
3320 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
3321 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
3322 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
3323 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
3324 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
3325 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
3326 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
3327 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
3328 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
3329 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
3330 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
3331 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
3332 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
3333 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
3334 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
3335 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
3336 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
3337 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
3338 | </ul> | |
3339 | </li> | |
3340 | </ul> | |
3341 | </dd> | |
2939 | 3342 | <dt id="exchangelib.folders.known_folders.Friends"><code class="flex name class"> |
2940 | 3343 | <span>class <span class="ident">Friends</span></span> |
2941 | 3344 | <span>(</span><span>**kwargs)</span> |
3808 | 4211 | |
3809 | 4212 | DISTINGUISHED_FOLDER_ID = "msgfolderroot" |
3810 | 4213 | LOCALIZED_NAMES = { |
4214 | None: ("Top of Information Store",), | |
4215 | "da_DK": ("Informationslagerets øverste niveau",), | |
3811 | 4216 | "zh_CN": ("信息存储顶部",), |
3812 | 4217 | }</code></pre> |
3813 | 4218 | </details> |
4047 | 4452 | <ul class="hlist"> |
4048 | 4453 | <li><a title="exchangelib.folders.known_folders.AllContacts" href="#exchangelib.folders.known_folders.AllContacts">AllContacts</a></li> |
4049 | 4454 | <li><a title="exchangelib.folders.known_folders.AllItems" href="#exchangelib.folders.known_folders.AllItems">AllItems</a></li> |
4455 | <li><a title="exchangelib.folders.known_folders.ApplicationData" href="#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></li> | |
4050 | 4456 | <li><a title="exchangelib.folders.known_folders.Audits" href="#exchangelib.folders.known_folders.Audits">Audits</a></li> |
4051 | 4457 | <li><a title="exchangelib.folders.known_folders.CalendarLogging" href="#exchangelib.folders.known_folders.CalendarLogging">CalendarLogging</a></li> |
4052 | 4458 | <li><a title="exchangelib.folders.known_folders.CommonViews" href="#exchangelib.folders.known_folders.CommonViews">CommonViews</a></li> |
4279 | 4685 | "de_DE": ("Postausgang",), |
4280 | 4686 | "en_US": ("Outbox",), |
4281 | 4687 | "es_ES": ("Bandeja de salida",), |
4282 | "fr_CA": (u"Boîte d'envoi",), | |
4688 | "fr_CA": ("Boîte d'envoi",), | |
4283 | 4689 | "nl_NL": ("Postvak UIT",), |
4284 | 4690 | "ru_RU": ("Исходящие",), |
4285 | 4691 | "sv_SE": ("Utkorgen",), |
5266 | 5672 | </li> |
5267 | 5673 | </ul> |
5268 | 5674 | </dd> |
5269 | <dt id="exchangelib.folders.known_folders.Reminders"><code class="flex name class"> | |
5270 | <span>class <span class="ident">Reminders</span></span> | |
5271 | <span>(</span><span>**kwargs)</span> | |
5272 | </code></dt> | |
5273 | <dd> | |
5274 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
5275 | <details class="source"> | |
5276 | <summary> | |
5277 | <span>Expand source code</span> | |
5278 | </summary> | |
5279 | <pre><code class="python">class Reminders(NonDeletableFolderMixin, Folder): | |
5280 | CONTAINER_CLASS = "Outlook.Reminder" | |
5281 | LOCALIZED_NAMES = { | |
5282 | "da_DK": ("Påmindelser",), | |
5283 | }</code></pre> | |
5284 | </details> | |
5285 | <h3>Ancestors</h3> | |
5286 | <ul class="hlist"> | |
5287 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
5288 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
5289 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
5290 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
5291 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
5292 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
5293 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
5294 | </ul> | |
5295 | <h3>Class variables</h3> | |
5296 | <dl> | |
5297 | <dt id="exchangelib.folders.known_folders.Reminders.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
5298 | <dd> | |
5299 | <div class="desc"></div> | |
5300 | </dd> | |
5301 | <dt id="exchangelib.folders.known_folders.Reminders.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5675 | <dt id="exchangelib.folders.known_folders.RecoveryPoints"><code class="flex name class"> | |
5676 | <span>class <span class="ident">RecoveryPoints</span></span> | |
5677 | <span>(</span><span>**kwargs)</span> | |
5678 | </code></dt> | |
5679 | <dd> | |
5680 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
5681 | <details class="source"> | |
5682 | <summary> | |
5683 | <span>Expand source code</span> | |
5684 | </summary> | |
5685 | <pre><code class="python">class RecoveryPoints(Folder): | |
5686 | CONTAINER_CLASS = "IPF.StoreItem.RecoveryPoints"</code></pre> | |
5687 | </details> | |
5688 | <h3>Ancestors</h3> | |
5689 | <ul class="hlist"> | |
5690 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
5691 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
5692 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
5693 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
5694 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
5695 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
5696 | </ul> | |
5697 | <h3>Class variables</h3> | |
5698 | <dl> | |
5699 | <dt id="exchangelib.folders.known_folders.RecoveryPoints.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
5302 | 5700 | <dd> |
5303 | 5701 | <div class="desc"></div> |
5304 | 5702 | </dd> |
5342 | 5740 | </li> |
5343 | 5741 | </ul> |
5344 | 5742 | </dd> |
5345 | <dt id="exchangelib.folders.known_folders.Schedule"><code class="flex name class"> | |
5346 | <span>class <span class="ident">Schedule</span></span> | |
5743 | <dt id="exchangelib.folders.known_folders.Reminders"><code class="flex name class"> | |
5744 | <span>class <span class="ident">Reminders</span></span> | |
5347 | 5745 | <span>(</span><span>**kwargs)</span> |
5348 | 5746 | </code></dt> |
5349 | 5747 | <dd> |
5352 | 5750 | <summary> |
5353 | 5751 | <span>Expand source code</span> |
5354 | 5752 | </summary> |
5355 | <pre><code class="python">class Schedule(NonDeletableFolderMixin, Folder): | |
5356 | LOCALIZED_NAMES = { | |
5357 | None: ("Schedule",), | |
5753 | <pre><code class="python">class Reminders(NonDeletableFolderMixin, Folder): | |
5754 | CONTAINER_CLASS = "Outlook.Reminder" | |
5755 | LOCALIZED_NAMES = { | |
5756 | "da_DK": ("Påmindelser",), | |
5358 | 5757 | }</code></pre> |
5359 | 5758 | </details> |
5360 | 5759 | <h3>Ancestors</h3> |
5369 | 5768 | </ul> |
5370 | 5769 | <h3>Class variables</h3> |
5371 | 5770 | <dl> |
5372 | <dt id="exchangelib.folders.known_folders.Schedule.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5771 | <dt id="exchangelib.folders.known_folders.Reminders.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
5772 | <dd> | |
5773 | <div class="desc"></div> | |
5774 | </dd> | |
5775 | <dt id="exchangelib.folders.known_folders.Reminders.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5373 | 5776 | <dd> |
5374 | 5777 | <div class="desc"></div> |
5375 | 5778 | </dd> |
5413 | 5816 | </li> |
5414 | 5817 | </ul> |
5415 | 5818 | </dd> |
5819 | <dt id="exchangelib.folders.known_folders.Schedule"><code class="flex name class"> | |
5820 | <span>class <span class="ident">Schedule</span></span> | |
5821 | <span>(</span><span>**kwargs)</span> | |
5822 | </code></dt> | |
5823 | <dd> | |
5824 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
5825 | <details class="source"> | |
5826 | <summary> | |
5827 | <span>Expand source code</span> | |
5828 | </summary> | |
5829 | <pre><code class="python">class Schedule(NonDeletableFolderMixin, Folder): | |
5830 | LOCALIZED_NAMES = { | |
5831 | None: ("Schedule",), | |
5832 | }</code></pre> | |
5833 | </details> | |
5834 | <h3>Ancestors</h3> | |
5835 | <ul class="hlist"> | |
5836 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
5837 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
5838 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
5839 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
5840 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
5841 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
5842 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
5843 | </ul> | |
5844 | <h3>Class variables</h3> | |
5845 | <dl> | |
5846 | <dt id="exchangelib.folders.known_folders.Schedule.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5847 | <dd> | |
5848 | <div class="desc"></div> | |
5849 | </dd> | |
5850 | </dl> | |
5851 | <h3>Inherited members</h3> | |
5852 | <ul class="hlist"> | |
5853 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
5854 | <ul class="hlist"> | |
5855 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
5856 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
5857 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
5858 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
5859 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
5860 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
5861 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
5862 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
5863 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
5864 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
5865 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
5866 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
5867 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
5868 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
5869 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
5870 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
5871 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
5872 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
5873 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
5874 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
5875 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
5876 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
5877 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
5878 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
5879 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
5880 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
5881 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
5882 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
5883 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
5884 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
5885 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
5886 | </ul> | |
5887 | </li> | |
5888 | </ul> | |
5889 | </dd> | |
5416 | 5890 | <dt id="exchangelib.folders.known_folders.SearchFolders"><code class="flex name class"> |
5417 | 5891 | <span>class <span class="ident">SearchFolders</span></span> |
5418 | 5892 | <span>(</span><span>**kwargs)</span> |
5864 | 6338 | </li> |
5865 | 6339 | </ul> |
5866 | 6340 | </dd> |
5867 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync"><code class="flex name class"> | |
5868 | <span>class <span class="ident">SmsAndChatsSync</span></span> | |
5869 | <span>(</span><span>**kwargs)</span> | |
5870 | </code></dt> | |
5871 | <dd> | |
5872 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
5873 | <details class="source"> | |
5874 | <summary> | |
5875 | <span>Expand source code</span> | |
5876 | </summary> | |
5877 | <pre><code class="python">class SmsAndChatsSync(NonDeletableFolderMixin, Folder): | |
5878 | CONTAINER_CLASS = "IPF.SmsAndChatsSync" | |
5879 | LOCALIZED_NAMES = { | |
5880 | None: ("SmsAndChatsSync",), | |
6341 | <dt id="exchangelib.folders.known_folders.SkypeTeamsMessages"><code class="flex name class"> | |
6342 | <span>class <span class="ident">SkypeTeamsMessages</span></span> | |
6343 | <span>(</span><span>**kwargs)</span> | |
6344 | </code></dt> | |
6345 | <dd> | |
6346 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
6347 | <details class="source"> | |
6348 | <summary> | |
6349 | <span>Expand source code</span> | |
6350 | </summary> | |
6351 | <pre><code class="python">class SkypeTeamsMessages(Folder): | |
6352 | CONTAINER_CLASS = "IPF.SkypeTeams.Message" | |
6353 | LOCALIZED_NAMES = { | |
6354 | None: ("Team-chat",), | |
5881 | 6355 | }</code></pre> |
5882 | 6356 | </details> |
5883 | 6357 | <h3>Ancestors</h3> |
5884 | 6358 | <ul class="hlist"> |
5885 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
5886 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
5887 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
5888 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
5889 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
5890 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
5891 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
5892 | </ul> | |
5893 | <h3>Class variables</h3> | |
5894 | <dl> | |
5895 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
5896 | <dd> | |
5897 | <div class="desc"></div> | |
5898 | </dd> | |
5899 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
6359 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
6360 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
6361 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
6362 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
6363 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6364 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
6365 | </ul> | |
6366 | <h3>Class variables</h3> | |
6367 | <dl> | |
6368 | <dt id="exchangelib.folders.known_folders.SkypeTeamsMessages.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
6369 | <dd> | |
6370 | <div class="desc"></div> | |
6371 | </dd> | |
6372 | <dt id="exchangelib.folders.known_folders.SkypeTeamsMessages.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5900 | 6373 | <dd> |
5901 | 6374 | <div class="desc"></div> |
5902 | 6375 | </dd> |
5940 | 6413 | </li> |
5941 | 6414 | </ul> |
5942 | 6415 | </dd> |
5943 | <dt id="exchangelib.folders.known_folders.SpoolerQueue"><code class="flex name class"> | |
5944 | <span>class <span class="ident">SpoolerQueue</span></span> | |
6416 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync"><code class="flex name class"> | |
6417 | <span>class <span class="ident">SmsAndChatsSync</span></span> | |
5945 | 6418 | <span>(</span><span>**kwargs)</span> |
5946 | 6419 | </code></dt> |
5947 | 6420 | <dd> |
5950 | 6423 | <summary> |
5951 | 6424 | <span>Expand source code</span> |
5952 | 6425 | </summary> |
5953 | <pre><code class="python">class SpoolerQueue(NonDeletableFolderMixin, Folder): | |
5954 | LOCALIZED_NAMES = { | |
5955 | None: ("Spooler Queue",), | |
6426 | <pre><code class="python">class SmsAndChatsSync(NonDeletableFolderMixin, Folder): | |
6427 | CONTAINER_CLASS = "IPF.SmsAndChatsSync" | |
6428 | LOCALIZED_NAMES = { | |
6429 | None: ("SmsAndChatsSync",), | |
5956 | 6430 | }</code></pre> |
5957 | 6431 | </details> |
5958 | 6432 | <h3>Ancestors</h3> |
5967 | 6441 | </ul> |
5968 | 6442 | <h3>Class variables</h3> |
5969 | 6443 | <dl> |
5970 | <dt id="exchangelib.folders.known_folders.SpoolerQueue.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
6444 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
6445 | <dd> | |
6446 | <div class="desc"></div> | |
6447 | </dd> | |
6448 | <dt id="exchangelib.folders.known_folders.SmsAndChatsSync.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
5971 | 6449 | <dd> |
5972 | 6450 | <div class="desc"></div> |
5973 | 6451 | </dd> |
6011 | 6489 | </li> |
6012 | 6490 | </ul> |
6013 | 6491 | </dd> |
6492 | <dt id="exchangelib.folders.known_folders.SpoolerQueue"><code class="flex name class"> | |
6493 | <span>class <span class="ident">SpoolerQueue</span></span> | |
6494 | <span>(</span><span>**kwargs)</span> | |
6495 | </code></dt> | |
6496 | <dd> | |
6497 | <div class="desc"><p>A mixin for non-wellknown folders than that are not deletable.</p></div> | |
6498 | <details class="source"> | |
6499 | <summary> | |
6500 | <span>Expand source code</span> | |
6501 | </summary> | |
6502 | <pre><code class="python">class SpoolerQueue(NonDeletableFolderMixin, Folder): | |
6503 | LOCALIZED_NAMES = { | |
6504 | None: ("Spooler Queue",), | |
6505 | }</code></pre> | |
6506 | </details> | |
6507 | <h3>Ancestors</h3> | |
6508 | <ul class="hlist"> | |
6509 | <li><a title="exchangelib.folders.known_folders.NonDeletableFolderMixin" href="#exchangelib.folders.known_folders.NonDeletableFolderMixin">NonDeletableFolderMixin</a></li> | |
6510 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
6511 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
6512 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
6513 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
6514 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6515 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
6516 | </ul> | |
6517 | <h3>Class variables</h3> | |
6518 | <dl> | |
6519 | <dt id="exchangelib.folders.known_folders.SpoolerQueue.LOCALIZED_NAMES"><code class="name">var <span class="ident">LOCALIZED_NAMES</span></code></dt> | |
6520 | <dd> | |
6521 | <div class="desc"></div> | |
6522 | </dd> | |
6523 | </dl> | |
6524 | <h3>Inherited members</h3> | |
6525 | <ul class="hlist"> | |
6526 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
6527 | <ul class="hlist"> | |
6528 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
6529 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
6530 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6531 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
6532 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
6533 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
6534 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
6535 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
6536 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
6537 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
6538 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
6539 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
6540 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
6541 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
6542 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
6543 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
6544 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
6545 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
6546 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
6547 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6548 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
6549 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
6550 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
6551 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
6552 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6553 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
6554 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
6555 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
6556 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
6557 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
6558 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6559 | </ul> | |
6560 | </li> | |
6561 | </ul> | |
6562 | </dd> | |
6563 | <dt id="exchangelib.folders.known_folders.SwssItems"><code class="flex name class"> | |
6564 | <span>class <span class="ident">SwssItems</span></span> | |
6565 | <span>(</span><span>**kwargs)</span> | |
6566 | </code></dt> | |
6567 | <dd> | |
6568 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/folder</a></p></div> | |
6569 | <details class="source"> | |
6570 | <summary> | |
6571 | <span>Expand source code</span> | |
6572 | </summary> | |
6573 | <pre><code class="python">class SwssItems(Folder): | |
6574 | CONTAINER_CLASS = "IPF.StoreItem.SwssItems"</code></pre> | |
6575 | </details> | |
6576 | <h3>Ancestors</h3> | |
6577 | <ul class="hlist"> | |
6578 | <li><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></li> | |
6579 | <li><a title="exchangelib.folders.base.BaseFolder" href="base.html#exchangelib.folders.base.BaseFolder">BaseFolder</a></li> | |
6580 | <li><a title="exchangelib.items.base.RegisterMixIn" href="../items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
6581 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="../properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
6582 | <li><a title="exchangelib.properties.EWSElement" href="../properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6583 | <li><a title="exchangelib.queryset.SearchableMixIn" href="../queryset.html#exchangelib.queryset.SearchableMixIn">SearchableMixIn</a></li> | |
6584 | </ul> | |
6585 | <h3>Class variables</h3> | |
6586 | <dl> | |
6587 | <dt id="exchangelib.folders.known_folders.SwssItems.CONTAINER_CLASS"><code class="name">var <span class="ident">CONTAINER_CLASS</span></code></dt> | |
6588 | <dd> | |
6589 | <div class="desc"></div> | |
6590 | </dd> | |
6591 | </dl> | |
6592 | <h3>Inherited members</h3> | |
6593 | <ul class="hlist"> | |
6594 | <li><code><b><a title="exchangelib.folders.base.Folder" href="base.html#exchangelib.folders.base.Folder">Folder</a></b></code>: | |
6595 | <ul class="hlist"> | |
6596 | <li><code><a title="exchangelib.folders.base.Folder.ID_ELEMENT_CLS" href="base.html#exchangelib.folders.base.BaseFolder.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
6597 | <li><code><a title="exchangelib.folders.base.Folder.account" href="base.html#exchangelib.folders.base.BaseFolder.account">account</a></code></li> | |
6598 | <li><code><a title="exchangelib.folders.base.Folder.add_field" href="../properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6599 | <li><code><a title="exchangelib.folders.base.Folder.all" href="../queryset.html#exchangelib.queryset.SearchableMixIn.all">all</a></code></li> | |
6600 | <li><code><a title="exchangelib.folders.base.Folder.deregister" href="../items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
6601 | <li><code><a title="exchangelib.folders.base.Folder.exclude" href="../queryset.html#exchangelib.queryset.SearchableMixIn.exclude">exclude</a></code></li> | |
6602 | <li><code><a title="exchangelib.folders.base.Folder.filter" href="../queryset.html#exchangelib.queryset.SearchableMixIn.filter">filter</a></code></li> | |
6603 | <li><code><a title="exchangelib.folders.base.Folder.folder_cls_from_container_class" href="base.html#exchangelib.folders.base.BaseFolder.folder_cls_from_container_class">folder_cls_from_container_class</a></code></li> | |
6604 | <li><code><a title="exchangelib.folders.base.Folder.folder_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.folder_sync_state">folder_sync_state</a></code></li> | |
6605 | <li><code><a title="exchangelib.folders.base.Folder.get" href="../queryset.html#exchangelib.queryset.SearchableMixIn.get">get</a></code></li> | |
6606 | <li><code><a title="exchangelib.folders.base.Folder.get_distinguished" href="base.html#exchangelib.folders.base.Folder.get_distinguished">get_distinguished</a></code></li> | |
6607 | <li><code><a title="exchangelib.folders.base.Folder.get_events" href="base.html#exchangelib.folders.base.BaseFolder.get_events">get_events</a></code></li> | |
6608 | <li><code><a title="exchangelib.folders.base.Folder.get_streaming_events" href="base.html#exchangelib.folders.base.BaseFolder.get_streaming_events">get_streaming_events</a></code></li> | |
6609 | <li><code><a title="exchangelib.folders.base.Folder.is_distinguished" href="base.html#exchangelib.folders.base.BaseFolder.is_distinguished">is_distinguished</a></code></li> | |
6610 | <li><code><a title="exchangelib.folders.base.Folder.item_sync_state" href="base.html#exchangelib.folders.base.BaseFolder.item_sync_state">item_sync_state</a></code></li> | |
6611 | <li><code><a title="exchangelib.folders.base.Folder.none" href="../queryset.html#exchangelib.queryset.SearchableMixIn.none">none</a></code></li> | |
6612 | <li><code><a title="exchangelib.folders.base.Folder.parent" href="base.html#exchangelib.folders.base.BaseFolder.parent">parent</a></code></li> | |
6613 | <li><code><a title="exchangelib.folders.base.Folder.people" href="../queryset.html#exchangelib.queryset.SearchableMixIn.people">people</a></code></li> | |
6614 | <li><code><a title="exchangelib.folders.base.Folder.register" href="../items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
6615 | <li><code><a title="exchangelib.folders.base.Folder.remove_field" href="../properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6616 | <li><code><a title="exchangelib.folders.base.Folder.root" href="base.html#exchangelib.folders.base.BaseFolder.root">root</a></code></li> | |
6617 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_pull" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_pull">subscribe_to_pull</a></code></li> | |
6618 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_push" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_push">subscribe_to_push</a></code></li> | |
6619 | <li><code><a title="exchangelib.folders.base.Folder.subscribe_to_streaming" href="base.html#exchangelib.folders.base.BaseFolder.subscribe_to_streaming">subscribe_to_streaming</a></code></li> | |
6620 | <li><code><a title="exchangelib.folders.base.Folder.supported_fields" href="../properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6621 | <li><code><a title="exchangelib.folders.base.Folder.sync_hierarchy" href="base.html#exchangelib.folders.base.BaseFolder.sync_hierarchy">sync_hierarchy</a></code></li> | |
6622 | <li><code><a title="exchangelib.folders.base.Folder.sync_items" href="base.html#exchangelib.folders.base.BaseFolder.sync_items">sync_items</a></code></li> | |
6623 | <li><code><a title="exchangelib.folders.base.Folder.test_access" href="base.html#exchangelib.folders.base.BaseFolder.test_access">test_access</a></code></li> | |
6624 | <li><code><a title="exchangelib.folders.base.Folder.tree" href="base.html#exchangelib.folders.base.BaseFolder.tree">tree</a></code></li> | |
6625 | <li><code><a title="exchangelib.folders.base.Folder.unsubscribe" href="base.html#exchangelib.folders.base.BaseFolder.unsubscribe">unsubscribe</a></code></li> | |
6626 | <li><code><a title="exchangelib.folders.base.Folder.validate_field" href="../properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6627 | </ul> | |
6628 | </li> | |
6629 | </ul> | |
6630 | </dd> | |
6014 | 6631 | <dt id="exchangelib.folders.known_folders.SyncIssues"><code class="flex name class"> |
6015 | 6632 | <span>class <span class="ident">SyncIssues</span></span> |
6016 | 6633 | <span>(</span><span>**kwargs)</span> |
6858 | 7475 | </ul> |
6859 | 7476 | </li> |
6860 | 7477 | <li> |
7478 | <h4><code><a title="exchangelib.folders.known_folders.ApplicationData" href="#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></code></h4> | |
7479 | <ul class=""> | |
7480 | <li><code><a title="exchangelib.folders.known_folders.ApplicationData.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.ApplicationData.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7481 | </ul> | |
7482 | </li> | |
7483 | <li> | |
6861 | 7484 | <h4><code><a title="exchangelib.folders.known_folders.ArchiveDeletedItems" href="#exchangelib.folders.known_folders.ArchiveDeletedItems">ArchiveDeletedItems</a></code></h4> |
6862 | 7485 | <ul class=""> |
6863 | 7486 | <li><code><a title="exchangelib.folders.known_folders.ArchiveDeletedItems.DISTINGUISHED_FOLDER_ID" href="#exchangelib.folders.known_folders.ArchiveDeletedItems.DISTINGUISHED_FOLDER_ID">DISTINGUISHED_FOLDER_ID</a></code></li> |
6911 | 7534 | <ul class=""> |
6912 | 7535 | <li><code><a title="exchangelib.folders.known_folders.Audits.LOCALIZED_NAMES" href="#exchangelib.folders.known_folders.Audits.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
6913 | 7536 | <li><code><a title="exchangelib.folders.known_folders.Audits.get_folder_allowed" href="#exchangelib.folders.known_folders.Audits.get_folder_allowed">get_folder_allowed</a></code></li> |
7537 | </ul> | |
7538 | </li> | |
7539 | <li> | |
7540 | <h4><code><a title="exchangelib.folders.known_folders.Birthdays" href="#exchangelib.folders.known_folders.Birthdays">Birthdays</a></code></h4> | |
7541 | <ul class=""> | |
7542 | <li><code><a title="exchangelib.folders.known_folders.Birthdays.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.Birthdays.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7543 | <li><code><a title="exchangelib.folders.known_folders.Birthdays.LOCALIZED_NAMES" href="#exchangelib.folders.known_folders.Birthdays.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> | |
6914 | 7544 | </ul> |
6915 | 7545 | </li> |
6916 | 7546 | <li> |
6975 | 7605 | </ul> |
6976 | 7606 | </li> |
6977 | 7607 | <li> |
7608 | <h4><code><a title="exchangelib.folders.known_folders.CrawlerData" href="#exchangelib.folders.known_folders.CrawlerData">CrawlerData</a></code></h4> | |
7609 | <ul class=""> | |
7610 | <li><code><a title="exchangelib.folders.known_folders.CrawlerData.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.CrawlerData.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7611 | </ul> | |
7612 | </li> | |
7613 | <li> | |
6978 | 7614 | <h4><code><a title="exchangelib.folders.known_folders.DefaultFoldersChangeHistory" href="#exchangelib.folders.known_folders.DefaultFoldersChangeHistory">DefaultFoldersChangeHistory</a></code></h4> |
6979 | 7615 | <ul class=""> |
6980 | 7616 | <li><code><a title="exchangelib.folders.known_folders.DefaultFoldersChangeHistory.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.DefaultFoldersChangeHistory.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
7004 | 7640 | </ul> |
7005 | 7641 | </li> |
7006 | 7642 | <li> |
7643 | <h4><code><a title="exchangelib.folders.known_folders.DlpPolicyEvaluation" href="#exchangelib.folders.known_folders.DlpPolicyEvaluation">DlpPolicyEvaluation</a></code></h4> | |
7644 | <ul class=""> | |
7645 | <li><code><a title="exchangelib.folders.known_folders.DlpPolicyEvaluation.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.DlpPolicyEvaluation.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7646 | </ul> | |
7647 | </li> | |
7648 | <li> | |
7007 | 7649 | <h4><code><a title="exchangelib.folders.known_folders.Drafts" href="#exchangelib.folders.known_folders.Drafts">Drafts</a></code></h4> |
7008 | 7650 | <ul class=""> |
7009 | 7651 | <li><code><a title="exchangelib.folders.known_folders.Drafts.DISTINGUISHED_FOLDER_ID" href="#exchangelib.folders.known_folders.Drafts.DISTINGUISHED_FOLDER_ID">DISTINGUISHED_FOLDER_ID</a></code></li> |
7029 | 7671 | <ul class=""> |
7030 | 7672 | <li><code><a title="exchangelib.folders.known_folders.Files.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.Files.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
7031 | 7673 | <li><code><a title="exchangelib.folders.known_folders.Files.LOCALIZED_NAMES" href="#exchangelib.folders.known_folders.Files.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
7674 | </ul> | |
7675 | </li> | |
7676 | <li> | |
7677 | <h4><code><a title="exchangelib.folders.known_folders.FreeBusyCache" href="#exchangelib.folders.known_folders.FreeBusyCache">FreeBusyCache</a></code></h4> | |
7678 | <ul class=""> | |
7679 | <li><code><a title="exchangelib.folders.known_folders.FreeBusyCache.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.FreeBusyCache.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7032 | 7680 | </ul> |
7033 | 7681 | </li> |
7034 | 7682 | <li> |
7254 | 7902 | </ul> |
7255 | 7903 | </li> |
7256 | 7904 | <li> |
7905 | <h4><code><a title="exchangelib.folders.known_folders.RecoveryPoints" href="#exchangelib.folders.known_folders.RecoveryPoints">RecoveryPoints</a></code></h4> | |
7906 | <ul class=""> | |
7907 | <li><code><a title="exchangelib.folders.known_folders.RecoveryPoints.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.RecoveryPoints.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7908 | </ul> | |
7909 | </li> | |
7910 | <li> | |
7257 | 7911 | <h4><code><a title="exchangelib.folders.known_folders.Reminders" href="#exchangelib.folders.known_folders.Reminders">Reminders</a></code></h4> |
7258 | 7912 | <ul class=""> |
7259 | 7913 | <li><code><a title="exchangelib.folders.known_folders.Reminders.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.Reminders.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
7307 | 7961 | </ul> |
7308 | 7962 | </li> |
7309 | 7963 | <li> |
7964 | <h4><code><a title="exchangelib.folders.known_folders.SkypeTeamsMessages" href="#exchangelib.folders.known_folders.SkypeTeamsMessages">SkypeTeamsMessages</a></code></h4> | |
7965 | <ul class=""> | |
7966 | <li><code><a title="exchangelib.folders.known_folders.SkypeTeamsMessages.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.SkypeTeamsMessages.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7967 | <li><code><a title="exchangelib.folders.known_folders.SkypeTeamsMessages.LOCALIZED_NAMES" href="#exchangelib.folders.known_folders.SkypeTeamsMessages.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> | |
7968 | </ul> | |
7969 | </li> | |
7970 | <li> | |
7310 | 7971 | <h4><code><a title="exchangelib.folders.known_folders.SmsAndChatsSync" href="#exchangelib.folders.known_folders.SmsAndChatsSync">SmsAndChatsSync</a></code></h4> |
7311 | 7972 | <ul class=""> |
7312 | 7973 | <li><code><a title="exchangelib.folders.known_folders.SmsAndChatsSync.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.SmsAndChatsSync.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> |
7317 | 7978 | <h4><code><a title="exchangelib.folders.known_folders.SpoolerQueue" href="#exchangelib.folders.known_folders.SpoolerQueue">SpoolerQueue</a></code></h4> |
7318 | 7979 | <ul class=""> |
7319 | 7980 | <li><code><a title="exchangelib.folders.known_folders.SpoolerQueue.LOCALIZED_NAMES" href="#exchangelib.folders.known_folders.SpoolerQueue.LOCALIZED_NAMES">LOCALIZED_NAMES</a></code></li> |
7981 | </ul> | |
7982 | </li> | |
7983 | <li> | |
7984 | <h4><code><a title="exchangelib.folders.known_folders.SwssItems" href="#exchangelib.folders.known_folders.SwssItems">SwssItems</a></code></h4> | |
7985 | <ul class=""> | |
7986 | <li><code><a title="exchangelib.folders.known_folders.SwssItems.CONTAINER_CLASS" href="#exchangelib.folders.known_folders.SwssItems.CONTAINER_CLASS">CONTAINER_CLASS</a></code></li> | |
7320 | 7987 | </ul> |
7321 | 7988 | </li> |
7322 | 7989 | <li> |
35 | 35 | from .base import BaseFolder |
36 | 36 | from .collections import FolderCollection |
37 | 37 | from .known_folders import ( |
38 | MISC_FOLDERS, | |
38 | 39 | NON_DELETABLE_FOLDERS, |
39 | 40 | WELLKNOWN_FOLDERS_IN_ARCHIVE_ROOT, |
40 | 41 | WELLKNOWN_FOLDERS_IN_ROOT, |
232 | 233 | :param folder_name: |
233 | 234 | :param locale: a string, e.g. 'da_DK' |
234 | 235 | """ |
235 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
236 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
236 | 237 | if folder_name.lower() in folder_cls.localized_names(locale): |
237 | 238 | return folder_cls |
238 | 239 | raise KeyError() |
983 | 984 | :param folder_name: |
984 | 985 | :param locale: a string, e.g. 'da_DK' |
985 | 986 | """ |
986 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
987 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
987 | 988 | if folder_name.lower() in folder_cls.localized_names(locale): |
988 | 989 | return folder_cls |
989 | 990 | raise KeyError() |
1049 | 1050 | :param folder_name: |
1050 | 1051 | :param locale: a string, e.g. 'da_DK' |
1051 | 1052 | """ |
1052 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
1053 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
1053 | 1054 | if folder_name.lower() in folder_cls.localized_names(locale): |
1054 | 1055 | return folder_cls |
1055 | 1056 | raise KeyError()</code></pre> |
43 | 43 | ForwardItem, |
44 | 44 | Message, |
45 | 45 | PostItem, |
46 | PostReplyItem, | |
46 | 47 | ReplyAllToItem, |
47 | 48 | ReplyToItem, |
48 | 49 | Task, |
55 | 56 | from .transport import BASIC, CBA, DIGEST, GSSAPI, NTLM, OAUTH2, SSPI |
56 | 57 | from .version import Build, Version |
57 | 58 | |
58 | __version__ = "4.7.2" | |
59 | __version__ = "4.7.6" | |
59 | 60 | |
60 | 61 | __all__ = [ |
61 | 62 | "__version__", |
63 | "AcceptItem", | |
62 | 64 | "Account", |
63 | "Identity", | |
64 | "FileAttachment", | |
65 | "ItemAttachment", | |
66 | "discover", | |
65 | "Attendee", | |
66 | "BASIC", | |
67 | "BaseProtocol", | |
68 | "Body", | |
69 | "Build", | |
70 | "CBA", | |
71 | "CalendarItem", | |
72 | "CancelCalendarItem", | |
67 | 73 | "Configuration", |
74 | "Contact", | |
75 | "Credentials", | |
76 | "DEEP", | |
68 | 77 | "DELEGATE", |
69 | "IMPERSONATION", | |
70 | "Credentials", | |
71 | "OAuth2AuthorizationCodeCredentials", | |
72 | "OAuth2Credentials", | |
78 | "DIGEST", | |
79 | "DLMailbox", | |
80 | "DeclineItem", | |
81 | "DistributionList", | |
73 | 82 | "EWSDate", |
74 | 83 | "EWSDateTime", |
75 | 84 | "EWSTimeZone", |
85 | "ExtendedProperty", | |
86 | "FailFast", | |
87 | "FaultTolerance", | |
88 | "FileAttachment", | |
89 | "Folder", | |
90 | "FolderCollection", | |
91 | "ForwardItem", | |
92 | "GSSAPI", | |
93 | "HTMLBody", | |
94 | "IMPERSONATION", | |
95 | "Identity", | |
96 | "ItemAttachment", | |
97 | "ItemId", | |
98 | "Mailbox", | |
99 | "Message", | |
100 | "NTLM", | |
101 | "NoVerifyHTTPAdapter", | |
102 | "OAUTH2", | |
103 | "OAuth2AuthorizationCodeCredentials", | |
104 | "OAuth2Credentials", | |
105 | "OofSettings", | |
106 | "PostItem", | |
107 | "PostReplyItem", | |
108 | "Q", | |
109 | "ReplyAllToItem", | |
110 | "ReplyToItem", | |
111 | "Room", | |
112 | "RoomList", | |
113 | "RootOfHierarchy", | |
114 | "SHALLOW", | |
115 | "SSPI", | |
116 | "TLSClientAuth", | |
117 | "Task", | |
118 | "TentativelyAcceptItem", | |
119 | "UID", | |
76 | 120 | "UTC", |
77 | 121 | "UTC_NOW", |
78 | "ExtendedProperty", | |
79 | "Folder", | |
80 | "RootOfHierarchy", | |
81 | "FolderCollection", | |
82 | "SHALLOW", | |
83 | "DEEP", | |
84 | "AcceptItem", | |
85 | "TentativelyAcceptItem", | |
86 | "DeclineItem", | |
87 | "CalendarItem", | |
88 | "CancelCalendarItem", | |
89 | "Contact", | |
90 | "DistributionList", | |
91 | "Message", | |
92 | "PostItem", | |
93 | "Task", | |
94 | "ForwardItem", | |
95 | "ReplyToItem", | |
96 | "ReplyAllToItem", | |
97 | "ItemId", | |
98 | "Mailbox", | |
99 | "DLMailbox", | |
100 | "Attendee", | |
101 | "Room", | |
102 | "RoomList", | |
103 | "Body", | |
104 | "HTMLBody", | |
105 | "UID", | |
106 | "FailFast", | |
107 | "FaultTolerance", | |
108 | "BaseProtocol", | |
109 | "NoVerifyHTTPAdapter", | |
110 | "TLSClientAuth", | |
111 | "OofSettings", | |
112 | "Q", | |
113 | "BASIC", | |
114 | "DIGEST", | |
115 | "NTLM", | |
116 | "GSSAPI", | |
117 | "SSPI", | |
118 | "OAUTH2", | |
119 | "CBA", | |
120 | "Build", | |
121 | 122 | "Version", |
122 | 123 | "close_connections", |
124 | "discover", | |
123 | 125 | ] |
124 | 126 | |
125 | 127 | # Set a default user agent, e.g. "exchangelib/3.1.1 (python-requests/2.22.0)" |
2867 | 2869 | session = self.renew_session(session) |
2868 | 2870 | self._session_pool.put(session, block=False) |
2869 | 2871 | |
2870 | @staticmethod | |
2871 | def close_session(session): | |
2872 | def close_session(self, session): | |
2873 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
2874 | self.credentials, OAuth2AuthorizationCodeCredentials | |
2875 | ): | |
2876 | # Reset token if client is of type BackendApplicationClient | |
2877 | self.credentials.access_token = None | |
2872 | 2878 | session.close() |
2873 | 2879 | del session |
2874 | 2880 | |
2931 | 2937 | return session |
2932 | 2938 | |
2933 | 2939 | def create_oauth2_session(self): |
2934 | has_token = False | |
2935 | scope = ["https://outlook.office365.com/.default"] | |
2936 | session_params = {} | |
2940 | session_params = {"token": self.credentials.access_token} # Token may be None | |
2937 | 2941 | token_params = {} |
2938 | 2942 | |
2939 | 2943 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
2940 | # Ask for a refresh token | |
2941 | scope.append("offline_access") | |
2942 | ||
2943 | # We don't know (or need) the Microsoft tenant ID. Use | |
2944 | # common/ to let Microsoft select the appropriate tenant | |
2945 | # for the provided authorization code or refresh token. | |
2946 | # | |
2947 | # Suppress looks-like-password warning from Bandit. | |
2948 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
2949 | ||
2950 | client_params = {} | |
2951 | has_token = self.credentials.access_token is not None | |
2952 | if has_token: | |
2953 | session_params["token"] = self.credentials.access_token | |
2954 | elif self.credentials.authorization_code is not None: | |
2955 | token_params["code"] = self.credentials.authorization_code | |
2956 | self.credentials.authorization_code = None | |
2957 | ||
2958 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
2959 | # If we're given a client ID and secret, we have enough | |
2960 | # to refresh access tokens ourselves. In other cases the | |
2961 | # session will raise TokenExpiredError and we'll need to | |
2962 | # ask the calling application to refresh the token (that | |
2963 | # covers cases where the caller doesn't have access to | |
2964 | # the client secret but is working with a service that | |
2965 | # can provide it refreshed tokens on a limited basis). | |
2944 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
2945 | self.credentials.authorization_code = None # We can only use the code once | |
2946 | ||
2947 | if self.credentials.client_id and self.credentials.client_secret: | |
2948 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
2949 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
2950 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
2951 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
2966 | 2952 | session_params.update( |
2967 | 2953 | { |
2968 | 2954 | "auto_refresh_kwargs": { |
2969 | 2955 | "client_id": self.credentials.client_id, |
2970 | 2956 | "client_secret": self.credentials.client_secret, |
2971 | 2957 | }, |
2972 | "auto_refresh_url": token_url, | |
2958 | "auto_refresh_url": self.credentials.token_url, | |
2973 | 2959 | "token_updater": self.credentials.on_token_auto_refreshed, |
2974 | 2960 | } |
2975 | 2961 | ) |
2976 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
2962 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
2977 | 2963 | else: |
2978 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
2979 | 2964 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
2980 | 2965 | |
2981 | 2966 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
2982 | if not has_token: | |
2967 | if not session.token: | |
2983 | 2968 | # Fetch the token explicitly -- it doesn't occur implicitly |
2984 | 2969 | token = session.fetch_token( |
2985 | token_url=token_url, | |
2970 | token_url=self.credentials.token_url, | |
2986 | 2971 | client_id=self.credentials.client_id, |
2987 | 2972 | client_secret=self.credentials.client_secret, |
2988 | scope=scope, | |
2973 | scope=self.credentials.scope, | |
2989 | 2974 | timeout=self.TIMEOUT, |
2990 | 2975 | **token_params, |
2991 | 2976 | ) |
2992 | # Allow the credentials object to update its copy of the new | |
2993 | # token, and give the application an opportunity to cache it | |
2977 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
2978 | # to cache it. | |
2994 | 2979 | self.credentials.on_token_auto_refreshed(token) |
2995 | 2980 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
2996 | 2981 | |
3069 | 3054 | </dl> |
3070 | 3055 | <h3>Static methods</h3> |
3071 | 3056 | <dl> |
3072 | <dt id="exchangelib.BaseProtocol.close_session"><code class="name flex"> | |
3073 | <span>def <span class="ident">close_session</span></span>(<span>session)</span> | |
3074 | </code></dt> | |
3075 | <dd> | |
3076 | <div class="desc"></div> | |
3077 | <details class="source"> | |
3078 | <summary> | |
3079 | <span>Expand source code</span> | |
3080 | </summary> | |
3081 | <pre><code class="python">@staticmethod | |
3082 | def close_session(session): | |
3083 | session.close() | |
3084 | del session</code></pre> | |
3085 | </details> | |
3086 | </dd> | |
3087 | 3057 | <dt id="exchangelib.BaseProtocol.get_adapter"><code class="name flex"> |
3088 | 3058 | <span>def <span class="ident">get_adapter</span></span>(<span>)</span> |
3089 | 3059 | </code></dt> |
3226 | 3196 | break</code></pre> |
3227 | 3197 | </details> |
3228 | 3198 | </dd> |
3199 | <dt id="exchangelib.BaseProtocol.close_session"><code class="name flex"> | |
3200 | <span>def <span class="ident">close_session</span></span>(<span>self, session)</span> | |
3201 | </code></dt> | |
3202 | <dd> | |
3203 | <div class="desc"></div> | |
3204 | <details class="source"> | |
3205 | <summary> | |
3206 | <span>Expand source code</span> | |
3207 | </summary> | |
3208 | <pre><code class="python">def close_session(self, session): | |
3209 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
3210 | self.credentials, OAuth2AuthorizationCodeCredentials | |
3211 | ): | |
3212 | # Reset token if client is of type BackendApplicationClient | |
3213 | self.credentials.access_token = None | |
3214 | session.close() | |
3215 | del session</code></pre> | |
3216 | </details> | |
3217 | </dd> | |
3229 | 3218 | <dt id="exchangelib.BaseProtocol.create_oauth2_session"><code class="name flex"> |
3230 | 3219 | <span>def <span class="ident">create_oauth2_session</span></span>(<span>self)</span> |
3231 | 3220 | </code></dt> |
3236 | 3225 | <span>Expand source code</span> |
3237 | 3226 | </summary> |
3238 | 3227 | <pre><code class="python">def create_oauth2_session(self): |
3239 | has_token = False | |
3240 | scope = ["https://outlook.office365.com/.default"] | |
3241 | session_params = {} | |
3228 | session_params = {"token": self.credentials.access_token} # Token may be None | |
3242 | 3229 | token_params = {} |
3243 | 3230 | |
3244 | 3231 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
3245 | # Ask for a refresh token | |
3246 | scope.append("offline_access") | |
3247 | ||
3248 | # We don't know (or need) the Microsoft tenant ID. Use | |
3249 | # common/ to let Microsoft select the appropriate tenant | |
3250 | # for the provided authorization code or refresh token. | |
3251 | # | |
3252 | # Suppress looks-like-password warning from Bandit. | |
3253 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
3254 | ||
3255 | client_params = {} | |
3256 | has_token = self.credentials.access_token is not None | |
3257 | if has_token: | |
3258 | session_params["token"] = self.credentials.access_token | |
3259 | elif self.credentials.authorization_code is not None: | |
3260 | token_params["code"] = self.credentials.authorization_code | |
3261 | self.credentials.authorization_code = None | |
3262 | ||
3263 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
3264 | # If we're given a client ID and secret, we have enough | |
3265 | # to refresh access tokens ourselves. In other cases the | |
3266 | # session will raise TokenExpiredError and we'll need to | |
3267 | # ask the calling application to refresh the token (that | |
3268 | # covers cases where the caller doesn't have access to | |
3269 | # the client secret but is working with a service that | |
3270 | # can provide it refreshed tokens on a limited basis). | |
3232 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
3233 | self.credentials.authorization_code = None # We can only use the code once | |
3234 | ||
3235 | if self.credentials.client_id and self.credentials.client_secret: | |
3236 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
3237 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
3238 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
3239 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
3271 | 3240 | session_params.update( |
3272 | 3241 | { |
3273 | 3242 | "auto_refresh_kwargs": { |
3274 | 3243 | "client_id": self.credentials.client_id, |
3275 | 3244 | "client_secret": self.credentials.client_secret, |
3276 | 3245 | }, |
3277 | "auto_refresh_url": token_url, | |
3246 | "auto_refresh_url": self.credentials.token_url, | |
3278 | 3247 | "token_updater": self.credentials.on_token_auto_refreshed, |
3279 | 3248 | } |
3280 | 3249 | ) |
3281 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
3250 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
3282 | 3251 | else: |
3283 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
3284 | 3252 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
3285 | 3253 | |
3286 | 3254 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
3287 | if not has_token: | |
3255 | if not session.token: | |
3288 | 3256 | # Fetch the token explicitly -- it doesn't occur implicitly |
3289 | 3257 | token = session.fetch_token( |
3290 | token_url=token_url, | |
3258 | token_url=self.credentials.token_url, | |
3291 | 3259 | client_id=self.credentials.client_id, |
3292 | 3260 | client_secret=self.credentials.client_secret, |
3293 | scope=scope, | |
3261 | scope=self.credentials.scope, | |
3294 | 3262 | timeout=self.TIMEOUT, |
3295 | 3263 | **token_params, |
3296 | 3264 | ) |
3297 | # Allow the credentials object to update its copy of the new | |
3298 | # token, and give the application an opportunity to cache it | |
3265 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
3266 | # to cache it. | |
3299 | 3267 | self.credentials.on_token_auto_refreshed(token) |
3300 | 3268 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
3301 | 3269 | |
4667 | 4635 | if auth_type is None: |
4668 | 4636 | # Set a default auth type for the credentials where this makes sense |
4669 | 4637 | auth_type = DEFAULT_AUTH_TYPE.get(type(credentials)) |
4670 | elif credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
4638 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
4639 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
4640 | if credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
4671 | 4641 | raise ValueError(f"Auth type {auth_type!r} was detected but no credentials were provided") |
4672 | 4642 | if server and service_endpoint: |
4673 | 4643 | raise AttributeError("Only one of 'server' or 'service_endpoint' must be provided") |
4674 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
4675 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
4676 | 4644 | if not retry_policy: |
4677 | 4645 | retry_policy = FailFast() |
4678 | 4646 | if not isinstance(version, (Version, type(None))): |
5917 | 5885 | </details> |
5918 | 5886 | <h3>Ancestors</h3> |
5919 | 5887 | <ul class="hlist"> |
5920 | <li>backports.zoneinfo.ZoneInfo</li> | |
5888 | <li>zoneinfo.ZoneInfo</li> | |
5921 | 5889 | <li>datetime.tzinfo</li> |
5922 | 5890 | </ul> |
5923 | 5891 | <h3>Class variables</h3> |
7192 | 7160 | <h3>Subclasses</h3> |
7193 | 7161 | <ul class="hlist"> |
7194 | 7162 | <li><a title="exchangelib.folders.known_folders.AllItems" href="folders/known_folders.html#exchangelib.folders.known_folders.AllItems">AllItems</a></li> |
7163 | <li><a title="exchangelib.folders.known_folders.ApplicationData" href="folders/known_folders.html#exchangelib.folders.known_folders.ApplicationData">ApplicationData</a></li> | |
7195 | 7164 | <li><a title="exchangelib.folders.known_folders.Audits" href="folders/known_folders.html#exchangelib.folders.known_folders.Audits">Audits</a></li> |
7165 | <li><a title="exchangelib.folders.known_folders.Birthdays" href="folders/known_folders.html#exchangelib.folders.known_folders.Birthdays">Birthdays</a></li> | |
7196 | 7166 | <li><a title="exchangelib.folders.known_folders.Calendar" href="folders/known_folders.html#exchangelib.folders.known_folders.Calendar">Calendar</a></li> |
7197 | 7167 | <li><a title="exchangelib.folders.known_folders.CalendarLogging" href="folders/known_folders.html#exchangelib.folders.known_folders.CalendarLogging">CalendarLogging</a></li> |
7198 | 7168 | <li><a title="exchangelib.folders.known_folders.CommonViews" href="folders/known_folders.html#exchangelib.folders.known_folders.CommonViews">CommonViews</a></li> |
7199 | 7169 | <li><a title="exchangelib.folders.known_folders.Contacts" href="folders/known_folders.html#exchangelib.folders.known_folders.Contacts">Contacts</a></li> |
7200 | 7170 | <li><a title="exchangelib.folders.known_folders.ConversationSettings" href="folders/known_folders.html#exchangelib.folders.known_folders.ConversationSettings">ConversationSettings</a></li> |
7171 | <li><a title="exchangelib.folders.known_folders.CrawlerData" href="folders/known_folders.html#exchangelib.folders.known_folders.CrawlerData">CrawlerData</a></li> | |
7201 | 7172 | <li><a title="exchangelib.folders.known_folders.DefaultFoldersChangeHistory" href="folders/known_folders.html#exchangelib.folders.known_folders.DefaultFoldersChangeHistory">DefaultFoldersChangeHistory</a></li> |
7202 | 7173 | <li><a title="exchangelib.folders.known_folders.DeferredAction" href="folders/known_folders.html#exchangelib.folders.known_folders.DeferredAction">DeferredAction</a></li> |
7203 | 7174 | <li><a title="exchangelib.folders.known_folders.DeletedItems" href="folders/known_folders.html#exchangelib.folders.known_folders.DeletedItems">DeletedItems</a></li> |
7175 | <li><a title="exchangelib.folders.known_folders.DlpPolicyEvaluation" href="folders/known_folders.html#exchangelib.folders.known_folders.DlpPolicyEvaluation">DlpPolicyEvaluation</a></li> | |
7204 | 7176 | <li><a title="exchangelib.folders.known_folders.ExchangeSyncData" href="folders/known_folders.html#exchangelib.folders.known_folders.ExchangeSyncData">ExchangeSyncData</a></li> |
7205 | 7177 | <li><a title="exchangelib.folders.known_folders.Files" href="folders/known_folders.html#exchangelib.folders.known_folders.Files">Files</a></li> |
7178 | <li><a title="exchangelib.folders.known_folders.FreeBusyCache" href="folders/known_folders.html#exchangelib.folders.known_folders.FreeBusyCache">FreeBusyCache</a></li> | |
7206 | 7179 | <li><a title="exchangelib.folders.known_folders.FreebusyData" href="folders/known_folders.html#exchangelib.folders.known_folders.FreebusyData">FreebusyData</a></li> |
7207 | 7180 | <li><a title="exchangelib.folders.known_folders.GraphAnalytics" href="folders/known_folders.html#exchangelib.folders.known_folders.GraphAnalytics">GraphAnalytics</a></li> |
7208 | 7181 | <li><a title="exchangelib.folders.known_folders.Location" href="folders/known_folders.html#exchangelib.folders.known_folders.Location">Location</a></li> |
7212 | 7185 | <li><a title="exchangelib.folders.known_folders.PassThroughSearchResults" href="folders/known_folders.html#exchangelib.folders.known_folders.PassThroughSearchResults">PassThroughSearchResults</a></li> |
7213 | 7186 | <li><a title="exchangelib.folders.known_folders.PdpProfileV2Secured" href="folders/known_folders.html#exchangelib.folders.known_folders.PdpProfileV2Secured">PdpProfileV2Secured</a></li> |
7214 | 7187 | <li><a title="exchangelib.folders.known_folders.RSSFeeds" href="folders/known_folders.html#exchangelib.folders.known_folders.RSSFeeds">RSSFeeds</a></li> |
7188 | <li><a title="exchangelib.folders.known_folders.RecoveryPoints" href="folders/known_folders.html#exchangelib.folders.known_folders.RecoveryPoints">RecoveryPoints</a></li> | |
7215 | 7189 | <li><a title="exchangelib.folders.known_folders.Reminders" href="folders/known_folders.html#exchangelib.folders.known_folders.Reminders">Reminders</a></li> |
7216 | 7190 | <li><a title="exchangelib.folders.known_folders.Schedule" href="folders/known_folders.html#exchangelib.folders.known_folders.Schedule">Schedule</a></li> |
7217 | 7191 | <li><a title="exchangelib.folders.known_folders.Sharing" href="folders/known_folders.html#exchangelib.folders.known_folders.Sharing">Sharing</a></li> |
7218 | 7192 | <li><a title="exchangelib.folders.known_folders.Shortcuts" href="folders/known_folders.html#exchangelib.folders.known_folders.Shortcuts">Shortcuts</a></li> |
7219 | 7193 | <li><a title="exchangelib.folders.known_folders.Signal" href="folders/known_folders.html#exchangelib.folders.known_folders.Signal">Signal</a></li> |
7194 | <li><a title="exchangelib.folders.known_folders.SkypeTeamsMessages" href="folders/known_folders.html#exchangelib.folders.known_folders.SkypeTeamsMessages">SkypeTeamsMessages</a></li> | |
7220 | 7195 | <li><a title="exchangelib.folders.known_folders.SmsAndChatsSync" href="folders/known_folders.html#exchangelib.folders.known_folders.SmsAndChatsSync">SmsAndChatsSync</a></li> |
7221 | 7196 | <li><a title="exchangelib.folders.known_folders.SpoolerQueue" href="folders/known_folders.html#exchangelib.folders.known_folders.SpoolerQueue">SpoolerQueue</a></li> |
7197 | <li><a title="exchangelib.folders.known_folders.SwssItems" href="folders/known_folders.html#exchangelib.folders.known_folders.SwssItems">SwssItems</a></li> | |
7222 | 7198 | <li><a title="exchangelib.folders.known_folders.System" href="folders/known_folders.html#exchangelib.folders.known_folders.System">System</a></li> |
7223 | 7199 | <li><a title="exchangelib.folders.known_folders.System1" href="folders/known_folders.html#exchangelib.folders.known_folders.System1">System1</a></li> |
7224 | 7200 | <li><a title="exchangelib.folders.known_folders.Tasks" href="folders/known_folders.html#exchangelib.folders.known_folders.Tasks">Tasks</a></li> |
8930 | 8906 | <li><a title="exchangelib.properties.ConversationId" href="properties.html#exchangelib.properties.ConversationId">ConversationId</a></li> |
8931 | 8907 | <li><a title="exchangelib.properties.FolderId" href="properties.html#exchangelib.properties.FolderId">FolderId</a></li> |
8932 | 8908 | <li><a title="exchangelib.properties.MovedItemId" href="properties.html#exchangelib.properties.MovedItemId">MovedItemId</a></li> |
8909 | <li><a title="exchangelib.properties.OldItemId" href="properties.html#exchangelib.properties.OldItemId">OldItemId</a></li> | |
8933 | 8910 | <li><a title="exchangelib.properties.ParentFolderId" href="properties.html#exchangelib.properties.ParentFolderId">ParentFolderId</a></li> |
8934 | 8911 | <li><a title="exchangelib.properties.ParentItemId" href="properties.html#exchangelib.properties.ParentItemId">ParentItemId</a></li> |
8935 | 8912 | <li><a title="exchangelib.properties.PersonaId" href="properties.html#exchangelib.properties.PersonaId">PersonaId</a></li> |
9169 | 9146 | conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) |
9170 | 9147 | # Rename 'From' to 'author'. We can't use fieldname 'from' since it's a Python keyword. |
9171 | 9148 | author = MailboxField(field_uri="message:From", is_read_only_after_send=True) |
9172 | message_id = CharField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
9149 | message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
9173 | 9150 | is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) |
9174 | 9151 | is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) |
9175 | 9152 | references = TextField(field_uri="message:References") |
9301 | 9278 | from ..services import MarkAsJunk |
9302 | 9279 | |
9303 | 9280 | res = MarkAsJunk(account=self.account).get( |
9304 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
9281 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
9305 | 9282 | ) |
9306 | 9283 | if res is None: |
9307 | 9284 | return |
9475 | 9452 | from ..services import MarkAsJunk |
9476 | 9453 | |
9477 | 9454 | res = MarkAsJunk(account=self.account).get( |
9478 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
9455 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
9479 | 9456 | ) |
9480 | 9457 | if res is None: |
9481 | 9458 | return |
9671 | 9648 | </dd> |
9672 | 9649 | <dt id="exchangelib.OAuth2AuthorizationCodeCredentials"><code class="flex name class"> |
9673 | 9650 | <span>class <span class="ident">OAuth2AuthorizationCodeCredentials</span></span> |
9674 | <span>(</span><span>authorization_code=None, access_token=None, **kwargs)</span> | |
9651 | <span>(</span><span>authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs)</span> | |
9675 | 9652 | </code></dt> |
9676 | 9653 | <dd> |
9677 | 9654 | <div class="desc"><p>Login info for OAuth 2.0 authentication using the authorization code grant type. This can be used in one of |
9678 | 9655 | several ways: |
9679 | 9656 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
9680 | 9657 | supplied with a refresh token. |
9681 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
9682 | expires and then refresh it as needed. | |
9658 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
9659 | refresh it as needed. | |
9683 | 9660 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
9684 | 9661 | refresh tokens itself by subclassing and implementing refresh().</p> |
9685 | 9662 | <p>Unlike the base (client credentials) grant, authorization code credentials don't require a Microsoft tenant ID |
9702 | 9679 | several ways: |
9703 | 9680 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
9704 | 9681 | supplied with a refresh token. |
9705 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
9706 | expires and then refresh it as needed. | |
9682 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
9683 | refresh it as needed. | |
9707 | 9684 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
9708 | 9685 | refresh tokens itself by subclassing and implementing refresh(). |
9709 | 9686 | |
9712 | 9689 | tenant. |
9713 | 9690 | """ |
9714 | 9691 | |
9715 | def __init__(self, authorization_code=None, access_token=None, **kwargs): | |
9692 | def __init__(self, authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs): | |
9716 | 9693 | """ |
9717 | 9694 | |
9718 | 9695 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
9724 | 9701 | :param access_token: Previously-obtained access token. If a token exists and the application will handle |
9725 | 9702 | refreshing by itself (or opts not to handle it), this parameter alone is sufficient. |
9726 | 9703 | """ |
9727 | super().__init__(**kwargs) | |
9704 | super().__init__(client_id=client_id, client_secret=client_secret, **kwargs) | |
9728 | 9705 | self.authorization_code = authorization_code |
9729 | 9706 | if access_token is not None and not isinstance(access_token, dict): |
9730 | 9707 | raise InvalidTypeError("access_token", access_token, OAuth2Token) |
9731 | 9708 | self.access_token = access_token |
9709 | ||
9710 | @property | |
9711 | def token_url(self): | |
9712 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
9713 | # tenant for the provided authorization code or refresh token. | |
9714 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
9715 | ||
9716 | @property | |
9717 | def scope(self): | |
9718 | res = super().scope | |
9719 | res.append("offline_access") | |
9720 | return res | |
9732 | 9721 | |
9733 | 9722 | def __repr__(self): |
9734 | 9723 | return self.__class__.__name__ + repr( |
9750 | 9739 | <li><a title="exchangelib.credentials.OAuth2Credentials" href="credentials.html#exchangelib.credentials.OAuth2Credentials">OAuth2Credentials</a></li> |
9751 | 9740 | <li><a title="exchangelib.credentials.BaseCredentials" href="credentials.html#exchangelib.credentials.BaseCredentials">BaseCredentials</a></li> |
9752 | 9741 | </ul> |
9742 | <h3>Instance variables</h3> | |
9743 | <dl> | |
9744 | <dt id="exchangelib.OAuth2AuthorizationCodeCredentials.scope"><code class="name">var <span class="ident">scope</span></code></dt> | |
9745 | <dd> | |
9746 | <div class="desc"></div> | |
9747 | <details class="source"> | |
9748 | <summary> | |
9749 | <span>Expand source code</span> | |
9750 | </summary> | |
9751 | <pre><code class="python">@property | |
9752 | def scope(self): | |
9753 | res = super().scope | |
9754 | res.append("offline_access") | |
9755 | return res</code></pre> | |
9756 | </details> | |
9757 | </dd> | |
9758 | <dt id="exchangelib.OAuth2AuthorizationCodeCredentials.token_url"><code class="name">var <span class="ident">token_url</span></code></dt> | |
9759 | <dd> | |
9760 | <div class="desc"></div> | |
9761 | <details class="source"> | |
9762 | <summary> | |
9763 | <span>Expand source code</span> | |
9764 | </summary> | |
9765 | <pre><code class="python">@property | |
9766 | def token_url(self): | |
9767 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
9768 | # tenant for the provided authorization code or refresh token. | |
9769 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec</code></pre> | |
9770 | </details> | |
9771 | </dd> | |
9772 | </dl> | |
9753 | 9773 | <h3>Inherited members</h3> |
9754 | 9774 | <ul class="hlist"> |
9755 | 9775 | <li><code><b><a title="exchangelib.credentials.OAuth2Credentials" href="credentials.html#exchangelib.credentials.OAuth2Credentials">OAuth2Credentials</a></b></code>: |
9762 | 9782 | </dd> |
9763 | 9783 | <dt id="exchangelib.OAuth2Credentials"><code class="flex name class"> |
9764 | 9784 | <span>class <span class="ident">OAuth2Credentials</span></span> |
9765 | <span>(</span><span>client_id, client_secret, tenant_id=None, identity=None)</span> | |
9785 | <span>(</span><span>client_id, client_secret, tenant_id=None, identity=None, access_token=None)</span> | |
9766 | 9786 | </code></dt> |
9767 | 9787 | <dd> |
9768 | 9788 | <div class="desc"><p>Login info for OAuth 2.0 client credentials authentication, as well as a base for other OAuth 2.0 grant types.</p> |
9773 | 9793 | <p>:param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
9774 | 9794 | :param client_secret: Secret associated with the OAuth application |
9775 | 9795 | :param tenant_id: Microsoft tenant ID of the account to access |
9776 | :param identity: An Identity object representing the account that these credentials are connected to.</p></div> | |
9796 | :param identity: An Identity object representing the account that these credentials are connected to. | |
9797 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token</p></div> | |
9777 | 9798 | <details class="source"> |
9778 | 9799 | <summary> |
9779 | 9800 | <span>Expand source code</span> |
9787 | 9808 | the associated auth code grant type for multi-tenant applications. |
9788 | 9809 | """ |
9789 | 9810 | |
9790 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None): | |
9811 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None, access_token=None): | |
9791 | 9812 | """ |
9792 | 9813 | |
9793 | 9814 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
9794 | 9815 | :param client_secret: Secret associated with the OAuth application |
9795 | 9816 | :param tenant_id: Microsoft tenant ID of the account to access |
9796 | 9817 | :param identity: An Identity object representing the account that these credentials are connected to. |
9818 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token | |
9797 | 9819 | """ |
9798 | 9820 | super().__init__() |
9799 | 9821 | self.client_id = client_id |
9800 | 9822 | self.client_secret = client_secret |
9801 | 9823 | self.tenant_id = tenant_id |
9802 | 9824 | self.identity = identity |
9803 | # When set, access_token is a dict (or an oauthlib.oauth2.OAuth2Token, which is also a dict) | |
9804 | self.access_token = None | |
9825 | self.access_token = access_token | |
9805 | 9826 | |
9806 | 9827 | def refresh(self, session): |
9807 | 9828 | # Creating a new session gets a new access token, so there's no work here to refresh the credentials. This |
9841 | 9862 | res.append(getattr(self, k)) |
9842 | 9863 | return hash(tuple(res)) |
9843 | 9864 | |
9865 | @property | |
9866 | def token_url(self): | |
9867 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token" | |
9868 | ||
9869 | @property | |
9870 | def scope(self): | |
9871 | return ["https://outlook.office365.com/.default"] | |
9872 | ||
9844 | 9873 | def __repr__(self): |
9845 | 9874 | return self.__class__.__name__ + repr((self.client_id, "********")) |
9846 | 9875 | |
9855 | 9884 | <ul class="hlist"> |
9856 | 9885 | <li><a title="exchangelib.credentials.OAuth2AuthorizationCodeCredentials" href="credentials.html#exchangelib.credentials.OAuth2AuthorizationCodeCredentials">OAuth2AuthorizationCodeCredentials</a></li> |
9857 | 9886 | </ul> |
9887 | <h3>Instance variables</h3> | |
9888 | <dl> | |
9889 | <dt id="exchangelib.OAuth2Credentials.scope"><code class="name">var <span class="ident">scope</span></code></dt> | |
9890 | <dd> | |
9891 | <div class="desc"></div> | |
9892 | <details class="source"> | |
9893 | <summary> | |
9894 | <span>Expand source code</span> | |
9895 | </summary> | |
9896 | <pre><code class="python">@property | |
9897 | def scope(self): | |
9898 | return ["https://outlook.office365.com/.default"]</code></pre> | |
9899 | </details> | |
9900 | </dd> | |
9901 | <dt id="exchangelib.OAuth2Credentials.token_url"><code class="name">var <span class="ident">token_url</span></code></dt> | |
9902 | <dd> | |
9903 | <div class="desc"></div> | |
9904 | <details class="source"> | |
9905 | <summary> | |
9906 | <span>Expand source code</span> | |
9907 | </summary> | |
9908 | <pre><code class="python">@property | |
9909 | def token_url(self): | |
9910 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token"</code></pre> | |
9911 | </details> | |
9912 | </dd> | |
9913 | </dl> | |
9858 | 9914 | <h3>Methods</h3> |
9859 | 9915 | <dl> |
9860 | 9916 | <dt id="exchangelib.OAuth2Credentials.on_token_auto_refreshed"><code class="name flex"> |
10244 | 10300 | <div class="desc"></div> |
10245 | 10301 | </dd> |
10246 | 10302 | <dt id="exchangelib.PostItem.sender"><code class="name">var <span class="ident">sender</span></code></dt> |
10303 | <dd> | |
10304 | <div class="desc"></div> | |
10305 | </dd> | |
10306 | </dl> | |
10307 | <h3>Inherited members</h3> | |
10308 | <ul class="hlist"> | |
10309 | <li><code><b><a title="exchangelib.items.item.Item" href="items/item.html#exchangelib.items.item.Item">Item</a></b></code>: | |
10310 | <ul class="hlist"> | |
10311 | <li><code><a title="exchangelib.items.item.Item.ID_ELEMENT_CLS" href="items/base.html#exchangelib.items.base.BaseItem.ID_ELEMENT_CLS">ID_ELEMENT_CLS</a></code></li> | |
10312 | <li><code><a title="exchangelib.items.item.Item.account" href="items/base.html#exchangelib.items.base.BaseItem.account">account</a></code></li> | |
10313 | <li><code><a title="exchangelib.items.item.Item.add_field" href="properties.html#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
10314 | <li><code><a title="exchangelib.items.item.Item.attach" href="items/item.html#exchangelib.items.item.Item.attach">attach</a></code></li> | |
10315 | <li><code><a title="exchangelib.items.item.Item.deregister" href="items/base.html#exchangelib.items.base.RegisterMixIn.deregister">deregister</a></code></li> | |
10316 | <li><code><a title="exchangelib.items.item.Item.detach" href="items/item.html#exchangelib.items.item.Item.detach">detach</a></code></li> | |
10317 | <li><code><a title="exchangelib.items.item.Item.folder" href="items/base.html#exchangelib.items.base.BaseItem.folder">folder</a></code></li> | |
10318 | <li><code><a title="exchangelib.items.item.Item.register" href="items/base.html#exchangelib.items.base.RegisterMixIn.register">register</a></code></li> | |
10319 | <li><code><a title="exchangelib.items.item.Item.remove_field" href="properties.html#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
10320 | <li><code><a title="exchangelib.items.item.Item.supported_fields" href="properties.html#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
10321 | <li><code><a title="exchangelib.items.item.Item.validate_field" href="properties.html#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
10322 | </ul> | |
10323 | </li> | |
10324 | </ul> | |
10325 | </dd> | |
10326 | <dt id="exchangelib.PostReplyItem"><code class="flex name class"> | |
10327 | <span>class <span class="ident">PostReplyItem</span></span> | |
10328 | <span>(</span><span>**kwargs)</span> | |
10329 | </code></dt> | |
10330 | <dd> | |
10331 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postreplyitem">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postreplyitem</a></p> | |
10332 | <p>Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.</p> | |
10333 | <p>:param kwargs: | |
10334 | 'account' is optional but allows calling 'send()' and 'delete()' | |
10335 | 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, | |
10336 | we use folder.account.</p></div> | |
10337 | <details class="source"> | |
10338 | <summary> | |
10339 | <span>Expand source code</span> | |
10340 | </summary> | |
10341 | <pre><code class="python">class PostReplyItem(Item): | |
10342 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postreplyitem""" | |
10343 | ||
10344 | ELEMENT_NAME = "PostReplyItem" | |
10345 | ||
10346 | # This element only has Item fields up to, and including, 'culture' | |
10347 | # TDO: Plus all message fields | |
10348 | new_body = BodyField(field_uri="NewBodyContent") # Accepts and returns Body or HTMLBody instances | |
10349 | ||
10350 | culture_idx = Item.FIELDS.index_by_name("culture") | |
10351 | sender_idx = Message.FIELDS.index_by_name("sender") | |
10352 | FIELDS = Item.FIELDS[: culture_idx + 1] + Message.FIELDS[sender_idx:]</code></pre> | |
10353 | </details> | |
10354 | <h3>Ancestors</h3> | |
10355 | <ul class="hlist"> | |
10356 | <li><a title="exchangelib.items.item.Item" href="items/item.html#exchangelib.items.item.Item">Item</a></li> | |
10357 | <li><a title="exchangelib.items.base.BaseItem" href="items/base.html#exchangelib.items.base.BaseItem">BaseItem</a></li> | |
10358 | <li><a title="exchangelib.items.base.RegisterMixIn" href="items/base.html#exchangelib.items.base.RegisterMixIn">RegisterMixIn</a></li> | |
10359 | <li><a title="exchangelib.properties.IdChangeKeyMixIn" href="properties.html#exchangelib.properties.IdChangeKeyMixIn">IdChangeKeyMixIn</a></li> | |
10360 | <li><a title="exchangelib.properties.EWSElement" href="properties.html#exchangelib.properties.EWSElement">EWSElement</a></li> | |
10361 | </ul> | |
10362 | <h3>Class variables</h3> | |
10363 | <dl> | |
10364 | <dt id="exchangelib.PostReplyItem.ELEMENT_NAME"><code class="name">var <span class="ident">ELEMENT_NAME</span></code></dt> | |
10365 | <dd> | |
10366 | <div class="desc"></div> | |
10367 | </dd> | |
10368 | <dt id="exchangelib.PostReplyItem.FIELDS"><code class="name">var <span class="ident">FIELDS</span></code></dt> | |
10369 | <dd> | |
10370 | <div class="desc"></div> | |
10371 | </dd> | |
10372 | <dt id="exchangelib.PostReplyItem.culture_idx"><code class="name">var <span class="ident">culture_idx</span></code></dt> | |
10373 | <dd> | |
10374 | <div class="desc"></div> | |
10375 | </dd> | |
10376 | <dt id="exchangelib.PostReplyItem.sender_idx"><code class="name">var <span class="ident">sender_idx</span></code></dt> | |
10377 | <dd> | |
10378 | <div class="desc"></div> | |
10379 | </dd> | |
10380 | </dl> | |
10381 | <h3>Instance variables</h3> | |
10382 | <dl> | |
10383 | <dt id="exchangelib.PostReplyItem.author"><code class="name">var <span class="ident">author</span></code></dt> | |
10384 | <dd> | |
10385 | <div class="desc"></div> | |
10386 | </dd> | |
10387 | <dt id="exchangelib.PostReplyItem.bcc_recipients"><code class="name">var <span class="ident">bcc_recipients</span></code></dt> | |
10388 | <dd> | |
10389 | <div class="desc"></div> | |
10390 | </dd> | |
10391 | <dt id="exchangelib.PostReplyItem.cc_recipients"><code class="name">var <span class="ident">cc_recipients</span></code></dt> | |
10392 | <dd> | |
10393 | <div class="desc"></div> | |
10394 | </dd> | |
10395 | <dt id="exchangelib.PostReplyItem.conversation_index"><code class="name">var <span class="ident">conversation_index</span></code></dt> | |
10396 | <dd> | |
10397 | <div class="desc"></div> | |
10398 | </dd> | |
10399 | <dt id="exchangelib.PostReplyItem.conversation_topic"><code class="name">var <span class="ident">conversation_topic</span></code></dt> | |
10400 | <dd> | |
10401 | <div class="desc"></div> | |
10402 | </dd> | |
10403 | <dt id="exchangelib.PostReplyItem.is_delivery_receipt_requested"><code class="name">var <span class="ident">is_delivery_receipt_requested</span></code></dt> | |
10404 | <dd> | |
10405 | <div class="desc"></div> | |
10406 | </dd> | |
10407 | <dt id="exchangelib.PostReplyItem.is_read"><code class="name">var <span class="ident">is_read</span></code></dt> | |
10408 | <dd> | |
10409 | <div class="desc"></div> | |
10410 | </dd> | |
10411 | <dt id="exchangelib.PostReplyItem.is_read_receipt_requested"><code class="name">var <span class="ident">is_read_receipt_requested</span></code></dt> | |
10412 | <dd> | |
10413 | <div class="desc"></div> | |
10414 | </dd> | |
10415 | <dt id="exchangelib.PostReplyItem.is_response_requested"><code class="name">var <span class="ident">is_response_requested</span></code></dt> | |
10416 | <dd> | |
10417 | <div class="desc"></div> | |
10418 | </dd> | |
10419 | <dt id="exchangelib.PostReplyItem.message_id"><code class="name">var <span class="ident">message_id</span></code></dt> | |
10420 | <dd> | |
10421 | <div class="desc"></div> | |
10422 | </dd> | |
10423 | <dt id="exchangelib.PostReplyItem.new_body"><code class="name">var <span class="ident">new_body</span></code></dt> | |
10424 | <dd> | |
10425 | <div class="desc"></div> | |
10426 | </dd> | |
10427 | <dt id="exchangelib.PostReplyItem.received_by"><code class="name">var <span class="ident">received_by</span></code></dt> | |
10428 | <dd> | |
10429 | <div class="desc"></div> | |
10430 | </dd> | |
10431 | <dt id="exchangelib.PostReplyItem.received_representing"><code class="name">var <span class="ident">received_representing</span></code></dt> | |
10432 | <dd> | |
10433 | <div class="desc"></div> | |
10434 | </dd> | |
10435 | <dt id="exchangelib.PostReplyItem.references"><code class="name">var <span class="ident">references</span></code></dt> | |
10436 | <dd> | |
10437 | <div class="desc"></div> | |
10438 | </dd> | |
10439 | <dt id="exchangelib.PostReplyItem.reminder_message_data"><code class="name">var <span class="ident">reminder_message_data</span></code></dt> | |
10440 | <dd> | |
10441 | <div class="desc"></div> | |
10442 | </dd> | |
10443 | <dt id="exchangelib.PostReplyItem.reply_to"><code class="name">var <span class="ident">reply_to</span></code></dt> | |
10444 | <dd> | |
10445 | <div class="desc"></div> | |
10446 | </dd> | |
10447 | <dt id="exchangelib.PostReplyItem.sender"><code class="name">var <span class="ident">sender</span></code></dt> | |
10448 | <dd> | |
10449 | <div class="desc"></div> | |
10450 | </dd> | |
10451 | <dt id="exchangelib.PostReplyItem.to_recipients"><code class="name">var <span class="ident">to_recipients</span></code></dt> | |
10247 | 10452 | <dd> |
10248 | 10453 | <div class="desc"></div> |
10249 | 10454 | </dd> |
11596 | 11801 | :param folder_name: |
11597 | 11802 | :param locale: a string, e.g. 'da_DK' |
11598 | 11803 | """ |
11599 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
11804 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
11600 | 11805 | if folder_name.lower() in folder_cls.localized_names(locale): |
11601 | 11806 | return folder_cls |
11602 | 11807 | raise KeyError() |
11662 | 11867 | :param folder_name: |
11663 | 11868 | :param locale: a string, e.g. 'da_DK' |
11664 | 11869 | """ |
11665 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
11870 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
11666 | 11871 | if folder_name.lower() in folder_cls.localized_names(locale): |
11667 | 11872 | return folder_cls |
11668 | 11873 | raise KeyError()</code></pre> |
13219 | 13424 | </li> |
13220 | 13425 | <li> |
13221 | 13426 | <h4><code><a title="exchangelib.OAuth2AuthorizationCodeCredentials" href="#exchangelib.OAuth2AuthorizationCodeCredentials">OAuth2AuthorizationCodeCredentials</a></code></h4> |
13427 | <ul class=""> | |
13428 | <li><code><a title="exchangelib.OAuth2AuthorizationCodeCredentials.scope" href="#exchangelib.OAuth2AuthorizationCodeCredentials.scope">scope</a></code></li> | |
13429 | <li><code><a title="exchangelib.OAuth2AuthorizationCodeCredentials.token_url" href="#exchangelib.OAuth2AuthorizationCodeCredentials.token_url">token_url</a></code></li> | |
13430 | </ul> | |
13222 | 13431 | </li> |
13223 | 13432 | <li> |
13224 | 13433 | <h4><code><a title="exchangelib.OAuth2Credentials" href="#exchangelib.OAuth2Credentials">OAuth2Credentials</a></code></h4> |
13225 | 13434 | <ul class=""> |
13226 | 13435 | <li><code><a title="exchangelib.OAuth2Credentials.on_token_auto_refreshed" href="#exchangelib.OAuth2Credentials.on_token_auto_refreshed">on_token_auto_refreshed</a></code></li> |
13436 | <li><code><a title="exchangelib.OAuth2Credentials.scope" href="#exchangelib.OAuth2Credentials.scope">scope</a></code></li> | |
13227 | 13437 | <li><code><a title="exchangelib.OAuth2Credentials.sig" href="#exchangelib.OAuth2Credentials.sig">sig</a></code></li> |
13438 | <li><code><a title="exchangelib.OAuth2Credentials.token_url" href="#exchangelib.OAuth2Credentials.token_url">token_url</a></code></li> | |
13228 | 13439 | </ul> |
13229 | 13440 | </li> |
13230 | 13441 | <li> |
13261 | 13472 | <li><code><a title="exchangelib.PostItem.posted_time" href="#exchangelib.PostItem.posted_time">posted_time</a></code></li> |
13262 | 13473 | <li><code><a title="exchangelib.PostItem.references" href="#exchangelib.PostItem.references">references</a></code></li> |
13263 | 13474 | <li><code><a title="exchangelib.PostItem.sender" href="#exchangelib.PostItem.sender">sender</a></code></li> |
13475 | </ul> | |
13476 | </li> | |
13477 | <li> | |
13478 | <h4><code><a title="exchangelib.PostReplyItem" href="#exchangelib.PostReplyItem">PostReplyItem</a></code></h4> | |
13479 | <ul class=""> | |
13480 | <li><code><a title="exchangelib.PostReplyItem.ELEMENT_NAME" href="#exchangelib.PostReplyItem.ELEMENT_NAME">ELEMENT_NAME</a></code></li> | |
13481 | <li><code><a title="exchangelib.PostReplyItem.FIELDS" href="#exchangelib.PostReplyItem.FIELDS">FIELDS</a></code></li> | |
13482 | <li><code><a title="exchangelib.PostReplyItem.author" href="#exchangelib.PostReplyItem.author">author</a></code></li> | |
13483 | <li><code><a title="exchangelib.PostReplyItem.bcc_recipients" href="#exchangelib.PostReplyItem.bcc_recipients">bcc_recipients</a></code></li> | |
13484 | <li><code><a title="exchangelib.PostReplyItem.cc_recipients" href="#exchangelib.PostReplyItem.cc_recipients">cc_recipients</a></code></li> | |
13485 | <li><code><a title="exchangelib.PostReplyItem.conversation_index" href="#exchangelib.PostReplyItem.conversation_index">conversation_index</a></code></li> | |
13486 | <li><code><a title="exchangelib.PostReplyItem.conversation_topic" href="#exchangelib.PostReplyItem.conversation_topic">conversation_topic</a></code></li> | |
13487 | <li><code><a title="exchangelib.PostReplyItem.culture_idx" href="#exchangelib.PostReplyItem.culture_idx">culture_idx</a></code></li> | |
13488 | <li><code><a title="exchangelib.PostReplyItem.is_delivery_receipt_requested" href="#exchangelib.PostReplyItem.is_delivery_receipt_requested">is_delivery_receipt_requested</a></code></li> | |
13489 | <li><code><a title="exchangelib.PostReplyItem.is_read" href="#exchangelib.PostReplyItem.is_read">is_read</a></code></li> | |
13490 | <li><code><a title="exchangelib.PostReplyItem.is_read_receipt_requested" href="#exchangelib.PostReplyItem.is_read_receipt_requested">is_read_receipt_requested</a></code></li> | |
13491 | <li><code><a title="exchangelib.PostReplyItem.is_response_requested" href="#exchangelib.PostReplyItem.is_response_requested">is_response_requested</a></code></li> | |
13492 | <li><code><a title="exchangelib.PostReplyItem.message_id" href="#exchangelib.PostReplyItem.message_id">message_id</a></code></li> | |
13493 | <li><code><a title="exchangelib.PostReplyItem.new_body" href="#exchangelib.PostReplyItem.new_body">new_body</a></code></li> | |
13494 | <li><code><a title="exchangelib.PostReplyItem.received_by" href="#exchangelib.PostReplyItem.received_by">received_by</a></code></li> | |
13495 | <li><code><a title="exchangelib.PostReplyItem.received_representing" href="#exchangelib.PostReplyItem.received_representing">received_representing</a></code></li> | |
13496 | <li><code><a title="exchangelib.PostReplyItem.references" href="#exchangelib.PostReplyItem.references">references</a></code></li> | |
13497 | <li><code><a title="exchangelib.PostReplyItem.reminder_message_data" href="#exchangelib.PostReplyItem.reminder_message_data">reminder_message_data</a></code></li> | |
13498 | <li><code><a title="exchangelib.PostReplyItem.reply_to" href="#exchangelib.PostReplyItem.reply_to">reply_to</a></code></li> | |
13499 | <li><code><a title="exchangelib.PostReplyItem.sender" href="#exchangelib.PostReplyItem.sender">sender</a></code></li> | |
13500 | <li><code><a title="exchangelib.PostReplyItem.sender_idx" href="#exchangelib.PostReplyItem.sender_idx">sender_idx</a></code></li> | |
13501 | <li><code><a title="exchangelib.PostReplyItem.to_recipients" href="#exchangelib.PostReplyItem.to_recipients">to_recipients</a></code></li> | |
13264 | 13502 | </ul> |
13265 | 13503 | </li> |
13266 | 13504 | <li> |
437 | 437 | |
438 | 438 | @require_account |
439 | 439 | def send(self, message_disposition=SEND_AND_SAVE_COPY): |
440 | # Some responses contain multiple response IDs, e.g. MeetingRequest.accept(). Return either the single ID or | |
441 | # the list of IDs. | |
442 | 440 | from ..services import CreateItem |
443 | 441 | |
444 | return CreateItem(account=self.account).get( | |
445 | items=[self], | |
446 | folder=self.folder, | |
447 | message_disposition=message_disposition, | |
448 | send_meeting_invitations=SEND_TO_NONE, | |
442 | res = list( | |
443 | CreateItem(account=self.account).call( | |
444 | items=[self], | |
445 | folder=self.folder, | |
446 | message_disposition=message_disposition, | |
447 | send_meeting_invitations=SEND_TO_NONE, | |
448 | ) | |
449 | 449 | ) |
450 | for r in res: | |
451 | if isinstance(r, Exception): | |
452 | raise r | |
453 | # CreateItem may return multiple item IDs when given a meeting reply item. See issue#886. In lack of a better | |
454 | # idea, return either the single ID or the list of IDs here. | |
455 | if len(res) == 1: | |
456 | return res[0] | |
457 | return res | |
450 | 458 | |
451 | 459 | |
452 | 460 | class AcceptItem(BaseMeetingReplyItem): |
858 | 866 | |
859 | 867 | @require_account |
860 | 868 | def send(self, message_disposition=SEND_AND_SAVE_COPY): |
861 | # Some responses contain multiple response IDs, e.g. MeetingRequest.accept(). Return either the single ID or | |
862 | # the list of IDs. | |
863 | 869 | from ..services import CreateItem |
864 | 870 | |
865 | return CreateItem(account=self.account).get( | |
866 | items=[self], | |
867 | folder=self.folder, | |
868 | message_disposition=message_disposition, | |
869 | send_meeting_invitations=SEND_TO_NONE, | |
870 | )</code></pre> | |
871 | res = list( | |
872 | CreateItem(account=self.account).call( | |
873 | items=[self], | |
874 | folder=self.folder, | |
875 | message_disposition=message_disposition, | |
876 | send_meeting_invitations=SEND_TO_NONE, | |
877 | ) | |
878 | ) | |
879 | for r in res: | |
880 | if isinstance(r, Exception): | |
881 | raise r | |
882 | # CreateItem may return multiple item IDs when given a meeting reply item. See issue#886. In lack of a better | |
883 | # idea, return either the single ID or the list of IDs here. | |
884 | if len(res) == 1: | |
885 | return res[0] | |
886 | return res</code></pre> | |
871 | 887 | </details> |
872 | 888 | <h3>Ancestors</h3> |
873 | 889 | <ul class="hlist"> |
969 | 985 | </summary> |
970 | 986 | <pre><code class="python">@require_account |
971 | 987 | def send(self, message_disposition=SEND_AND_SAVE_COPY): |
972 | # Some responses contain multiple response IDs, e.g. MeetingRequest.accept(). Return either the single ID or | |
973 | # the list of IDs. | |
974 | 988 | from ..services import CreateItem |
975 | 989 | |
976 | return CreateItem(account=self.account).get( | |
977 | items=[self], | |
978 | folder=self.folder, | |
979 | message_disposition=message_disposition, | |
980 | send_meeting_invitations=SEND_TO_NONE, | |
981 | )</code></pre> | |
990 | res = list( | |
991 | CreateItem(account=self.account).call( | |
992 | items=[self], | |
993 | folder=self.folder, | |
994 | message_disposition=message_disposition, | |
995 | send_meeting_invitations=SEND_TO_NONE, | |
996 | ) | |
997 | ) | |
998 | for r in res: | |
999 | if isinstance(r, Exception): | |
1000 | raise r | |
1001 | # CreateItem may return multiple item IDs when given a meeting reply item. See issue#886. In lack of a better | |
1002 | # idea, return either the single ID or the list of IDs here. | |
1003 | if len(res) == 1: | |
1004 | return res[0] | |
1005 | return res</code></pre> | |
982 | 1006 | </details> |
983 | 1007 | </dd> |
984 | 1008 | </dl> |
808 | 808 | hobbies = StringAttributedValueField(field_uri="persona:Hobbies") |
809 | 809 | wedding_anniversaries = StringAttributedValueField(field_uri="persona:WeddingAnniversaries") |
810 | 810 | birthdays = StringAttributedValueField(field_uri="persona:Birthdays") |
811 | locations = StringAttributedValueField(field_uri="persona:Locations")</code></pre> | |
811 | locations = StringAttributedValueField(field_uri="persona:Locations") | |
812 | # This class has an additional field of type "ExtendedPropertyAttributedValueField" and | |
813 | # field_uri 'persona:ExtendedProperties'</code></pre> | |
812 | 814 | </details> |
813 | 815 | <h3>Ancestors</h3> |
814 | 816 | <ul class="hlist"> |
3014 | 3014 | conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) |
3015 | 3015 | # Rename 'From' to 'author'. We can't use fieldname 'from' since it's a Python keyword. |
3016 | 3016 | author = MailboxField(field_uri="message:From", is_read_only_after_send=True) |
3017 | message_id = CharField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
3017 | message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
3018 | 3018 | is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) |
3019 | 3019 | is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) |
3020 | 3020 | references = TextField(field_uri="message:References") |
3146 | 3146 | from ..services import MarkAsJunk |
3147 | 3147 | |
3148 | 3148 | res = MarkAsJunk(account=self.account).get( |
3149 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
3149 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
3150 | 3150 | ) |
3151 | 3151 | if res is None: |
3152 | 3152 | return |
3320 | 3320 | from ..services import MarkAsJunk |
3321 | 3321 | |
3322 | 3322 | res = MarkAsJunk(account=self.account).get( |
3323 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
3323 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
3324 | 3324 | ) |
3325 | 3325 | if res is None: |
3326 | 3326 | return |
3575 | 3575 | hobbies = StringAttributedValueField(field_uri="persona:Hobbies") |
3576 | 3576 | wedding_anniversaries = StringAttributedValueField(field_uri="persona:WeddingAnniversaries") |
3577 | 3577 | birthdays = StringAttributedValueField(field_uri="persona:Birthdays") |
3578 | locations = StringAttributedValueField(field_uri="persona:Locations")</code></pre> | |
3578 | locations = StringAttributedValueField(field_uri="persona:Locations") | |
3579 | # This class has an additional field of type "ExtendedPropertyAttributedValueField" and | |
3580 | # field_uri 'persona:ExtendedProperties'</code></pre> | |
3579 | 3581 | </details> |
3580 | 3582 | <h3>Ancestors</h3> |
3581 | 3583 | <ul class="hlist"> |
64 | 64 | conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) |
65 | 65 | # Rename 'From' to 'author'. We can't use fieldname 'from' since it's a Python keyword. |
66 | 66 | author = MailboxField(field_uri="message:From", is_read_only_after_send=True) |
67 | message_id = CharField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
67 | message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
68 | 68 | is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) |
69 | 69 | is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) |
70 | 70 | references = TextField(field_uri="message:References") |
196 | 196 | from ..services import MarkAsJunk |
197 | 197 | |
198 | 198 | res = MarkAsJunk(account=self.account).get( |
199 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
199 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
200 | 200 | ) |
201 | 201 | if res is None: |
202 | 202 | return |
315 | 315 | conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) |
316 | 316 | # Rename 'From' to 'author'. We can't use fieldname 'from' since it's a Python keyword. |
317 | 317 | author = MailboxField(field_uri="message:From", is_read_only_after_send=True) |
318 | message_id = CharField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
318 | message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
319 | 319 | is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) |
320 | 320 | is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) |
321 | 321 | references = TextField(field_uri="message:References") |
447 | 447 | from ..services import MarkAsJunk |
448 | 448 | |
449 | 449 | res = MarkAsJunk(account=self.account).get( |
450 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
450 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
451 | 451 | ) |
452 | 452 | if res is None: |
453 | 453 | return |
621 | 621 | from ..services import MarkAsJunk |
622 | 622 | |
623 | 623 | res = MarkAsJunk(account=self.account).get( |
624 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
624 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
625 | 625 | ) |
626 | 626 | if res is None: |
627 | 627 | return |
34 | 34 | from inspect import getmro |
35 | 35 | from threading import Lock |
36 | 36 | |
37 | from .errors import InvalidTypeError, TimezoneDefinitionInvalidForYear | |
37 | from .errors import InvalidTypeError | |
38 | 38 | from .fields import ( |
39 | 39 | WEEKDAY_NAMES, |
40 | 40 | AssociatedCalendarItemIdField, |
246 | 246 | # Folder class, making the custom field available for subclasses). |
247 | 247 | if local_fields: |
248 | 248 | kwargs["FIELDS"] = fields |
249 | cls = super().__new__(mcs, name, bases, kwargs) | |
250 | cls._slots_keys = mcs._get_slots_keys(cls) | |
251 | return cls | |
249 | klass = super().__new__(mcs, name, bases, kwargs) | |
250 | klass._slots_keys = mcs._get_slots_keys(klass) | |
251 | return klass | |
252 | 252 | |
253 | 253 | @staticmethod |
254 | def _get_slots_keys(cls): | |
254 | def _get_slots_keys(klass): | |
255 | 255 | seen = set() |
256 | 256 | keys = [] |
257 | for c in reversed(getmro(cls)): | |
257 | for c in reversed(getmro(klass)): | |
258 | 258 | if not hasattr(c, "__slots__"): |
259 | 259 | continue |
260 | 260 | for k in c.__slots__: |
607 | 607 | def id_from_xml(cls, elem): |
608 | 608 | item = cls.from_xml(elem=elem, account=None) |
609 | 609 | return item.id, item.changekey |
610 | ||
611 | ||
612 | class OldItemId(ItemId): | |
613 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldfolderid""" | |
614 | ||
615 | ELEMENT_NAME = "OldItemId" | |
616 | ||
617 | ||
618 | class OldFolderId(FolderId): | |
619 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/olditemid""" | |
620 | ||
621 | ELEMENT_NAME = "OldFolderId" | |
622 | ||
623 | ||
624 | class OldParentFolderId(ParentFolderId): | |
625 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldparentfolderid""" | |
626 | ||
627 | ELEMENT_NAME = "OldParentFolderId" | |
610 | 628 | |
611 | 629 | |
612 | 630 | class Mailbox(EWSElement): |
1436 | 1454 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/responseobjects""" |
1437 | 1455 | |
1438 | 1456 | ELEMENT_NAME = "ResponseObjects" |
1439 | NAMESPACE = EWSElement.NAMESPACE | |
1440 | ||
1441 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=NAMESPACE) | |
1457 | ||
1458 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=TNS) | |
1442 | 1459 | tentatively_accept_item = EWSElementField( |
1443 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=NAMESPACE | |
1460 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=TNS | |
1444 | 1461 | ) |
1445 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=NAMESPACE) | |
1446 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=NAMESPACE) | |
1447 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=NAMESPACE) | |
1448 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=NAMESPACE) | |
1462 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=TNS) | |
1463 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=TNS) | |
1464 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=TNS) | |
1465 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=TNS) | |
1449 | 1466 | cancel_calendar_item = EWSElementField( |
1450 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=NAMESPACE | |
1467 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=TNS | |
1451 | 1468 | ) |
1452 | 1469 | remove_item = EWSElementField(field_uri="RemoveItem", value_cls=RemoveItem) |
1453 | post_reply_item = EWSElementField( | |
1454 | field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=EWSElement.NAMESPACE | |
1455 | ) | |
1470 | post_reply_item = EWSElementField(field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=TNS) | |
1456 | 1471 | success_read_receipt = EWSElementField(field_uri="SuppressReadReceipt", value_cls=SuppressReadReceipt) |
1457 | 1472 | accept_sharing_invitation = EWSElementField(field_uri="AcceptSharingInvitation", value_cls=AcceptSharingInvitation) |
1458 | 1473 | |
1732 | 1747 | ITEM = "item" |
1733 | 1748 | |
1734 | 1749 | timestamp = DateTimeField(field_uri="TimeStamp") |
1735 | item_id = EWSElementField(field_uri="ItemId", value_cls=ItemId) | |
1736 | folder_id = EWSElementField(field_uri="FolderId", value_cls=FolderId) | |
1737 | parent_folder_id = EWSElementField(field_uri="ParentFolderId", value_cls=ParentFolderId) | |
1750 | item_id = EWSElementField(value_cls=ItemId) | |
1751 | folder_id = EWSElementField(value_cls=FolderId) | |
1752 | parent_folder_id = EWSElementField(value_cls=ParentFolderId) | |
1738 | 1753 | |
1739 | 1754 | @property |
1740 | 1755 | def event_type(self): |
1748 | 1763 | class OldTimestampEvent(TimestampEvent, metaclass=EWSMeta): |
1749 | 1764 | """Base class for both item and folder copy/move events.""" |
1750 | 1765 | |
1751 | old_item_id = EWSElementField(field_uri="OldItemId", value_cls=ItemId) | |
1752 | old_folder_id = EWSElementField(field_uri="OldFolderId", value_cls=FolderId) | |
1753 | old_parent_folder_id = EWSElementField(field_uri="OldParentFolderId", value_cls=ParentFolderId) | |
1766 | old_item_id = EWSElementField(value_cls=OldItemId) | |
1767 | old_folder_id = EWSElementField(value_cls=OldFolderId) | |
1768 | old_parent_folder_id = EWSElementField(value_cls=OldParentFolderId) | |
1754 | 1769 | |
1755 | 1770 | |
1756 | 1771 | class CopiedEvent(OldTimestampEvent): |
1891 | 1906 | name = CharField(field_uri="Name", is_attribute=True) |
1892 | 1907 | bias = TimeDeltaField(field_uri="Bias", is_attribute=True) |
1893 | 1908 | |
1894 | def _split_id(self): | |
1895 | to_year, to_type = self.id.rsplit("/", 1)[1].split("-") | |
1896 | return int(to_year), to_type | |
1897 | ||
1898 | @property | |
1899 | def year(self): | |
1900 | return self._split_id()[0] | |
1901 | ||
1902 | @property | |
1903 | def type(self): | |
1904 | return self._split_id()[1] | |
1905 | ||
1906 | 1909 | @property |
1907 | 1910 | def bias_in_minutes(self): |
1908 | 1911 | return int(self.bias.total_seconds()) // 60 # Convert to minutes |
1933 | 1936 | def from_xml(cls, elem, account): |
1934 | 1937 | return super().from_xml(elem, account) |
1935 | 1938 | |
1936 | def _get_standard_period(self, for_year): | |
1937 | # Look through periods and pick a relevant period according to the 'for_year' value | |
1938 | valid_period = None | |
1939 | for period in sorted(self.periods, key=lambda p: (p.year, p.type)): | |
1940 | if period.year > for_year: | |
1941 | break | |
1942 | if period.type != "Standard": | |
1939 | def _get_standard_period(self, transitions_group): | |
1940 | # Find the first standard period referenced from transitions_group | |
1941 | standard_periods_map = {p.id: p for p in self.periods if p.name == "Standard"} | |
1942 | for transition in transitions_group.transitions: | |
1943 | try: | |
1944 | return standard_periods_map[transition.to] | |
1945 | except KeyError: | |
1943 | 1946 | continue |
1944 | valid_period = period | |
1945 | if valid_period is None: | |
1946 | raise TimezoneDefinitionInvalidForYear(f"Year {for_year} not included in periods {self.periods}") | |
1947 | return valid_period | |
1947 | raise ValueError(f"No standard period matching any transition in {transitions_group}") | |
1948 | 1948 | |
1949 | 1949 | def _get_transitions_group(self, for_year): |
1950 | 1950 | # Look through the transitions, and pick the relevant transition group according to the 'for_year' value |
1966 | 1966 | if not 0 <= len(transitions_group.transitions) <= 2: |
1967 | 1967 | raise ValueError(f"Expected 0-2 transitions in transitions group {transitions_group}") |
1968 | 1968 | |
1969 | standard_period = self._get_standard_period(for_year) | |
1969 | standard_period = self._get_standard_period(transitions_group) | |
1970 | 1970 | periods_map = {p.id: p for p in self.periods} |
1971 | 1971 | standard_time, daylight_time = None, None |
1972 | 1972 | if len(transitions_group.transitions) == 1: |
3534 | 3534 | <pre><code class="python">class ConversationId(ItemId): |
3535 | 3535 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/conversationid""" |
3536 | 3536 | |
3537 | ELEMENT_NAME = "ConversationId"</code></pre> | |
3537 | ELEMENT_NAME = "ConversationId" | |
3538 | ||
3539 | # ChangeKey attribute is sometimes required, see MSDN link</code></pre> | |
3538 | 3540 | </details> |
3539 | 3541 | <h3>Ancestors</h3> |
3540 | 3542 | <ul class="hlist"> |
4614 | 4616 | <span>(</span><span>*args, **kwargs)</span> |
4615 | 4617 | </code></dt> |
4616 | 4618 | <dd> |
4617 | <div class="desc"><p>type(object_or_name, bases, dict) | |
4618 | type(object) -> the object's type | |
4619 | type(name, bases, dict) -> a new type</p></div> | |
4619 | <div class="desc"><p>type(object) -> the object's type | |
4620 | type(name, bases, dict, **kwds) -> a new type</p></div> | |
4620 | 4621 | <details class="source"> |
4621 | 4622 | <summary> |
4622 | 4623 | <span>Expand source code</span> |
4652 | 4653 | # Folder class, making the custom field available for subclasses). |
4653 | 4654 | if local_fields: |
4654 | 4655 | kwargs["FIELDS"] = fields |
4655 | cls = super().__new__(mcs, name, bases, kwargs) | |
4656 | cls._slots_keys = mcs._get_slots_keys(cls) | |
4657 | return cls | |
4656 | klass = super().__new__(mcs, name, bases, kwargs) | |
4657 | klass._slots_keys = mcs._get_slots_keys(klass) | |
4658 | return klass | |
4658 | 4659 | |
4659 | 4660 | @staticmethod |
4660 | def _get_slots_keys(cls): | |
4661 | def _get_slots_keys(klass): | |
4661 | 4662 | seen = set() |
4662 | 4663 | keys = [] |
4663 | for c in reversed(getmro(cls)): | |
4664 | for c in reversed(getmro(klass)): | |
4664 | 4665 | if not hasattr(c, "__slots__"): |
4665 | 4666 | continue |
4666 | 4667 | for k in c.__slots__: |
5434 | 5435 | <h3>Subclasses</h3> |
5435 | 5436 | <ul class="hlist"> |
5436 | 5437 | <li><a title="exchangelib.properties.DistinguishedFolderId" href="#exchangelib.properties.DistinguishedFolderId">DistinguishedFolderId</a></li> |
5438 | <li><a title="exchangelib.properties.OldFolderId" href="#exchangelib.properties.OldFolderId">OldFolderId</a></li> | |
5437 | 5439 | </ul> |
5438 | 5440 | <h3>Class variables</h3> |
5439 | 5441 | <dl> |
6022 | 6024 | <li><a title="exchangelib.properties.ConversationId" href="#exchangelib.properties.ConversationId">ConversationId</a></li> |
6023 | 6025 | <li><a title="exchangelib.properties.FolderId" href="#exchangelib.properties.FolderId">FolderId</a></li> |
6024 | 6026 | <li><a title="exchangelib.properties.MovedItemId" href="#exchangelib.properties.MovedItemId">MovedItemId</a></li> |
6027 | <li><a title="exchangelib.properties.OldItemId" href="#exchangelib.properties.OldItemId">OldItemId</a></li> | |
6025 | 6028 | <li><a title="exchangelib.properties.ParentFolderId" href="#exchangelib.properties.ParentFolderId">ParentFolderId</a></li> |
6026 | 6029 | <li><a title="exchangelib.properties.ParentItemId" href="#exchangelib.properties.ParentItemId">ParentItemId</a></li> |
6027 | 6030 | <li><a title="exchangelib.properties.PersonaId" href="#exchangelib.properties.PersonaId">PersonaId</a></li> |
6858 | 6861 | </li> |
6859 | 6862 | </ul> |
6860 | 6863 | </dd> |
6864 | <dt id="exchangelib.properties.OldFolderId"><code class="flex name class"> | |
6865 | <span>class <span class="ident">OldFolderId</span></span> | |
6866 | <span>(</span><span>*args, **kwargs)</span> | |
6867 | </code></dt> | |
6868 | <dd> | |
6869 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/olditemid">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/olditemid</a></p></div> | |
6870 | <details class="source"> | |
6871 | <summary> | |
6872 | <span>Expand source code</span> | |
6873 | </summary> | |
6874 | <pre><code class="python">class OldFolderId(FolderId): | |
6875 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/olditemid""" | |
6876 | ||
6877 | ELEMENT_NAME = "OldFolderId"</code></pre> | |
6878 | </details> | |
6879 | <h3>Ancestors</h3> | |
6880 | <ul class="hlist"> | |
6881 | <li><a title="exchangelib.properties.FolderId" href="#exchangelib.properties.FolderId">FolderId</a></li> | |
6882 | <li><a title="exchangelib.properties.ItemId" href="#exchangelib.properties.ItemId">ItemId</a></li> | |
6883 | <li><a title="exchangelib.properties.BaseItemId" href="#exchangelib.properties.BaseItemId">BaseItemId</a></li> | |
6884 | <li><a title="exchangelib.properties.EWSElement" href="#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6885 | </ul> | |
6886 | <h3>Class variables</h3> | |
6887 | <dl> | |
6888 | <dt id="exchangelib.properties.OldFolderId.ELEMENT_NAME"><code class="name">var <span class="ident">ELEMENT_NAME</span></code></dt> | |
6889 | <dd> | |
6890 | <div class="desc"></div> | |
6891 | </dd> | |
6892 | </dl> | |
6893 | <h3>Inherited members</h3> | |
6894 | <ul class="hlist"> | |
6895 | <li><code><b><a title="exchangelib.properties.FolderId" href="#exchangelib.properties.FolderId">FolderId</a></b></code>: | |
6896 | <ul class="hlist"> | |
6897 | <li><code><a title="exchangelib.properties.FolderId.add_field" href="#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6898 | <li><code><a title="exchangelib.properties.FolderId.remove_field" href="#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6899 | <li><code><a title="exchangelib.properties.FolderId.supported_fields" href="#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6900 | <li><code><a title="exchangelib.properties.FolderId.validate_field" href="#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6901 | </ul> | |
6902 | </li> | |
6903 | </ul> | |
6904 | </dd> | |
6905 | <dt id="exchangelib.properties.OldItemId"><code class="flex name class"> | |
6906 | <span>class <span class="ident">OldItemId</span></span> | |
6907 | <span>(</span><span>*args, **kwargs)</span> | |
6908 | </code></dt> | |
6909 | <dd> | |
6910 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldfolderid">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldfolderid</a></p></div> | |
6911 | <details class="source"> | |
6912 | <summary> | |
6913 | <span>Expand source code</span> | |
6914 | </summary> | |
6915 | <pre><code class="python">class OldItemId(ItemId): | |
6916 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldfolderid""" | |
6917 | ||
6918 | ELEMENT_NAME = "OldItemId"</code></pre> | |
6919 | </details> | |
6920 | <h3>Ancestors</h3> | |
6921 | <ul class="hlist"> | |
6922 | <li><a title="exchangelib.properties.ItemId" href="#exchangelib.properties.ItemId">ItemId</a></li> | |
6923 | <li><a title="exchangelib.properties.BaseItemId" href="#exchangelib.properties.BaseItemId">BaseItemId</a></li> | |
6924 | <li><a title="exchangelib.properties.EWSElement" href="#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6925 | </ul> | |
6926 | <h3>Class variables</h3> | |
6927 | <dl> | |
6928 | <dt id="exchangelib.properties.OldItemId.ELEMENT_NAME"><code class="name">var <span class="ident">ELEMENT_NAME</span></code></dt> | |
6929 | <dd> | |
6930 | <div class="desc"></div> | |
6931 | </dd> | |
6932 | </dl> | |
6933 | <h3>Inherited members</h3> | |
6934 | <ul class="hlist"> | |
6935 | <li><code><b><a title="exchangelib.properties.ItemId" href="#exchangelib.properties.ItemId">ItemId</a></b></code>: | |
6936 | <ul class="hlist"> | |
6937 | <li><code><a title="exchangelib.properties.ItemId.add_field" href="#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6938 | <li><code><a title="exchangelib.properties.ItemId.remove_field" href="#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6939 | <li><code><a title="exchangelib.properties.ItemId.supported_fields" href="#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6940 | <li><code><a title="exchangelib.properties.ItemId.validate_field" href="#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6941 | </ul> | |
6942 | </li> | |
6943 | </ul> | |
6944 | </dd> | |
6945 | <dt id="exchangelib.properties.OldParentFolderId"><code class="flex name class"> | |
6946 | <span>class <span class="ident">OldParentFolderId</span></span> | |
6947 | <span>(</span><span>*args, **kwargs)</span> | |
6948 | </code></dt> | |
6949 | <dd> | |
6950 | <div class="desc"><p>MSDN: <a href="https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldparentfolderid">https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldparentfolderid</a></p></div> | |
6951 | <details class="source"> | |
6952 | <summary> | |
6953 | <span>Expand source code</span> | |
6954 | </summary> | |
6955 | <pre><code class="python">class OldParentFolderId(ParentFolderId): | |
6956 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldparentfolderid""" | |
6957 | ||
6958 | ELEMENT_NAME = "OldParentFolderId"</code></pre> | |
6959 | </details> | |
6960 | <h3>Ancestors</h3> | |
6961 | <ul class="hlist"> | |
6962 | <li><a title="exchangelib.properties.ParentFolderId" href="#exchangelib.properties.ParentFolderId">ParentFolderId</a></li> | |
6963 | <li><a title="exchangelib.properties.ItemId" href="#exchangelib.properties.ItemId">ItemId</a></li> | |
6964 | <li><a title="exchangelib.properties.BaseItemId" href="#exchangelib.properties.BaseItemId">BaseItemId</a></li> | |
6965 | <li><a title="exchangelib.properties.EWSElement" href="#exchangelib.properties.EWSElement">EWSElement</a></li> | |
6966 | </ul> | |
6967 | <h3>Class variables</h3> | |
6968 | <dl> | |
6969 | <dt id="exchangelib.properties.OldParentFolderId.ELEMENT_NAME"><code class="name">var <span class="ident">ELEMENT_NAME</span></code></dt> | |
6970 | <dd> | |
6971 | <div class="desc"></div> | |
6972 | </dd> | |
6973 | </dl> | |
6974 | <h3>Inherited members</h3> | |
6975 | <ul class="hlist"> | |
6976 | <li><code><b><a title="exchangelib.properties.ParentFolderId" href="#exchangelib.properties.ParentFolderId">ParentFolderId</a></b></code>: | |
6977 | <ul class="hlist"> | |
6978 | <li><code><a title="exchangelib.properties.ParentFolderId.add_field" href="#exchangelib.properties.EWSElement.add_field">add_field</a></code></li> | |
6979 | <li><code><a title="exchangelib.properties.ParentFolderId.remove_field" href="#exchangelib.properties.EWSElement.remove_field">remove_field</a></code></li> | |
6980 | <li><code><a title="exchangelib.properties.ParentFolderId.supported_fields" href="#exchangelib.properties.EWSElement.supported_fields">supported_fields</a></code></li> | |
6981 | <li><code><a title="exchangelib.properties.ParentFolderId.validate_field" href="#exchangelib.properties.EWSElement.validate_field">validate_field</a></code></li> | |
6982 | </ul> | |
6983 | </li> | |
6984 | </ul> | |
6985 | </dd> | |
6861 | 6986 | <dt id="exchangelib.properties.OldTimestampEvent"><code class="flex name class"> |
6862 | 6987 | <span>class <span class="ident">OldTimestampEvent</span></span> |
6863 | 6988 | <span>(</span><span>**kwargs)</span> |
6871 | 6996 | <pre><code class="python">class OldTimestampEvent(TimestampEvent, metaclass=EWSMeta): |
6872 | 6997 | """Base class for both item and folder copy/move events.""" |
6873 | 6998 | |
6874 | old_item_id = EWSElementField(field_uri="OldItemId", value_cls=ItemId) | |
6875 | old_folder_id = EWSElementField(field_uri="OldFolderId", value_cls=FolderId) | |
6876 | old_parent_folder_id = EWSElementField(field_uri="OldParentFolderId", value_cls=ParentFolderId)</code></pre> | |
6999 | old_item_id = EWSElementField(value_cls=OldItemId) | |
7000 | old_folder_id = EWSElementField(value_cls=OldFolderId) | |
7001 | old_parent_folder_id = EWSElementField(value_cls=OldParentFolderId)</code></pre> | |
6877 | 7002 | </details> |
6878 | 7003 | <h3>Ancestors</h3> |
6879 | 7004 | <ul class="hlist"> |
7065 | 7190 | <li><a title="exchangelib.properties.BaseItemId" href="#exchangelib.properties.BaseItemId">BaseItemId</a></li> |
7066 | 7191 | <li><a title="exchangelib.properties.EWSElement" href="#exchangelib.properties.EWSElement">EWSElement</a></li> |
7067 | 7192 | </ul> |
7193 | <h3>Subclasses</h3> | |
7194 | <ul class="hlist"> | |
7195 | <li><a title="exchangelib.properties.OldParentFolderId" href="#exchangelib.properties.OldParentFolderId">OldParentFolderId</a></li> | |
7196 | </ul> | |
7068 | 7197 | <h3>Class variables</h3> |
7069 | 7198 | <dl> |
7070 | 7199 | <dt id="exchangelib.properties.ParentFolderId.ELEMENT_NAME"><code class="name">var <span class="ident">ELEMENT_NAME</span></code></dt> |
7148 | 7277 | name = CharField(field_uri="Name", is_attribute=True) |
7149 | 7278 | bias = TimeDeltaField(field_uri="Bias", is_attribute=True) |
7150 | 7279 | |
7151 | def _split_id(self): | |
7152 | to_year, to_type = self.id.rsplit("/", 1)[1].split("-") | |
7153 | return int(to_year), to_type | |
7154 | ||
7155 | @property | |
7156 | def year(self): | |
7157 | return self._split_id()[0] | |
7158 | ||
7159 | @property | |
7160 | def type(self): | |
7161 | return self._split_id()[1] | |
7162 | ||
7163 | 7280 | @property |
7164 | 7281 | def bias_in_minutes(self): |
7165 | 7282 | return int(self.bias.total_seconds()) // 60 # Convert to minutes</code></pre> |
7204 | 7321 | <dt id="exchangelib.properties.Period.name"><code class="name">var <span class="ident">name</span></code></dt> |
7205 | 7322 | <dd> |
7206 | 7323 | <div class="desc"></div> |
7207 | </dd> | |
7208 | <dt id="exchangelib.properties.Period.type"><code class="name">var <span class="ident">type</span></code></dt> | |
7209 | <dd> | |
7210 | <div class="desc"></div> | |
7211 | <details class="source"> | |
7212 | <summary> | |
7213 | <span>Expand source code</span> | |
7214 | </summary> | |
7215 | <pre><code class="python">@property | |
7216 | def type(self): | |
7217 | return self._split_id()[1]</code></pre> | |
7218 | </details> | |
7219 | </dd> | |
7220 | <dt id="exchangelib.properties.Period.year"><code class="name">var <span class="ident">year</span></code></dt> | |
7221 | <dd> | |
7222 | <div class="desc"></div> | |
7223 | <details class="source"> | |
7224 | <summary> | |
7225 | <span>Expand source code</span> | |
7226 | </summary> | |
7227 | <pre><code class="python">@property | |
7228 | def year(self): | |
7229 | return self._split_id()[0]</code></pre> | |
7230 | </details> | |
7231 | 7324 | </dd> |
7232 | 7325 | </dl> |
7233 | 7326 | <h3>Inherited members</h3> |
8254 | 8347 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/responseobjects""" |
8255 | 8348 | |
8256 | 8349 | ELEMENT_NAME = "ResponseObjects" |
8257 | NAMESPACE = EWSElement.NAMESPACE | |
8258 | ||
8259 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=NAMESPACE) | |
8350 | ||
8351 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=TNS) | |
8260 | 8352 | tentatively_accept_item = EWSElementField( |
8261 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=NAMESPACE | |
8353 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=TNS | |
8262 | 8354 | ) |
8263 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=NAMESPACE) | |
8264 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=NAMESPACE) | |
8265 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=NAMESPACE) | |
8266 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=NAMESPACE) | |
8355 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=TNS) | |
8356 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=TNS) | |
8357 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=TNS) | |
8358 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=TNS) | |
8267 | 8359 | cancel_calendar_item = EWSElementField( |
8268 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=NAMESPACE | |
8360 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=TNS | |
8269 | 8361 | ) |
8270 | 8362 | remove_item = EWSElementField(field_uri="RemoveItem", value_cls=RemoveItem) |
8271 | post_reply_item = EWSElementField( | |
8272 | field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=EWSElement.NAMESPACE | |
8273 | ) | |
8363 | post_reply_item = EWSElementField(field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=TNS) | |
8274 | 8364 | success_read_receipt = EWSElementField(field_uri="SuppressReadReceipt", value_cls=SuppressReadReceipt) |
8275 | 8365 | accept_sharing_invitation = EWSElementField(field_uri="AcceptSharingInvitation", value_cls=AcceptSharingInvitation)</code></pre> |
8276 | 8366 | </details> |
8285 | 8375 | <div class="desc"></div> |
8286 | 8376 | </dd> |
8287 | 8377 | <dt id="exchangelib.properties.ResponseObjects.FIELDS"><code class="name">var <span class="ident">FIELDS</span></code></dt> |
8288 | <dd> | |
8289 | <div class="desc"></div> | |
8290 | </dd> | |
8291 | <dt id="exchangelib.properties.ResponseObjects.NAMESPACE"><code class="name">var <span class="ident">NAMESPACE</span></code></dt> | |
8292 | 8378 | <dd> |
8293 | 8379 | <div class="desc"></div> |
8294 | 8380 | </dd> |
9235 | 9321 | def from_xml(cls, elem, account): |
9236 | 9322 | return super().from_xml(elem, account) |
9237 | 9323 | |
9238 | def _get_standard_period(self, for_year): | |
9239 | # Look through periods and pick a relevant period according to the 'for_year' value | |
9240 | valid_period = None | |
9241 | for period in sorted(self.periods, key=lambda p: (p.year, p.type)): | |
9242 | if period.year > for_year: | |
9243 | break | |
9244 | if period.type != "Standard": | |
9324 | def _get_standard_period(self, transitions_group): | |
9325 | # Find the first standard period referenced from transitions_group | |
9326 | standard_periods_map = {p.id: p for p in self.periods if p.name == "Standard"} | |
9327 | for transition in transitions_group.transitions: | |
9328 | try: | |
9329 | return standard_periods_map[transition.to] | |
9330 | except KeyError: | |
9245 | 9331 | continue |
9246 | valid_period = period | |
9247 | if valid_period is None: | |
9248 | raise TimezoneDefinitionInvalidForYear(f"Year {for_year} not included in periods {self.periods}") | |
9249 | return valid_period | |
9332 | raise ValueError(f"No standard period matching any transition in {transitions_group}") | |
9250 | 9333 | |
9251 | 9334 | def _get_transitions_group(self, for_year): |
9252 | 9335 | # Look through the transitions, and pick the relevant transition group according to the 'for_year' value |
9268 | 9351 | if not 0 <= len(transitions_group.transitions) <= 2: |
9269 | 9352 | raise ValueError(f"Expected 0-2 transitions in transitions group {transitions_group}") |
9270 | 9353 | |
9271 | standard_period = self._get_standard_period(for_year) | |
9354 | standard_period = self._get_standard_period(transitions_group) | |
9272 | 9355 | periods_map = {p.id: p for p in self.periods} |
9273 | 9356 | standard_time, daylight_time = None, None |
9274 | 9357 | if len(transitions_group.transitions) == 1: |
9372 | 9455 | if not 0 <= len(transitions_group.transitions) <= 2: |
9373 | 9456 | raise ValueError(f"Expected 0-2 transitions in transitions group {transitions_group}") |
9374 | 9457 | |
9375 | standard_period = self._get_standard_period(for_year) | |
9458 | standard_period = self._get_standard_period(transitions_group) | |
9376 | 9459 | periods_map = {p.id: p for p in self.periods} |
9377 | 9460 | standard_time, daylight_time = None, None |
9378 | 9461 | if len(transitions_group.transitions) == 1: |
9562 | 9645 | ITEM = "item" |
9563 | 9646 | |
9564 | 9647 | timestamp = DateTimeField(field_uri="TimeStamp") |
9565 | item_id = EWSElementField(field_uri="ItemId", value_cls=ItemId) | |
9566 | folder_id = EWSElementField(field_uri="FolderId", value_cls=FolderId) | |
9567 | parent_folder_id = EWSElementField(field_uri="ParentFolderId", value_cls=ParentFolderId) | |
9648 | item_id = EWSElementField(value_cls=ItemId) | |
9649 | folder_id = EWSElementField(value_cls=FolderId) | |
9650 | parent_folder_id = EWSElementField(value_cls=ParentFolderId) | |
9568 | 9651 | |
9569 | 9652 | @property |
9570 | 9653 | def event_type(self): |
10829 | 10912 | </ul> |
10830 | 10913 | </li> |
10831 | 10914 | <li> |
10915 | <h4><code><a title="exchangelib.properties.OldFolderId" href="#exchangelib.properties.OldFolderId">OldFolderId</a></code></h4> | |
10916 | <ul class=""> | |
10917 | <li><code><a title="exchangelib.properties.OldFolderId.ELEMENT_NAME" href="#exchangelib.properties.OldFolderId.ELEMENT_NAME">ELEMENT_NAME</a></code></li> | |
10918 | </ul> | |
10919 | </li> | |
10920 | <li> | |
10921 | <h4><code><a title="exchangelib.properties.OldItemId" href="#exchangelib.properties.OldItemId">OldItemId</a></code></h4> | |
10922 | <ul class=""> | |
10923 | <li><code><a title="exchangelib.properties.OldItemId.ELEMENT_NAME" href="#exchangelib.properties.OldItemId.ELEMENT_NAME">ELEMENT_NAME</a></code></li> | |
10924 | </ul> | |
10925 | </li> | |
10926 | <li> | |
10927 | <h4><code><a title="exchangelib.properties.OldParentFolderId" href="#exchangelib.properties.OldParentFolderId">OldParentFolderId</a></code></h4> | |
10928 | <ul class=""> | |
10929 | <li><code><a title="exchangelib.properties.OldParentFolderId.ELEMENT_NAME" href="#exchangelib.properties.OldParentFolderId.ELEMENT_NAME">ELEMENT_NAME</a></code></li> | |
10930 | </ul> | |
10931 | </li> | |
10932 | <li> | |
10832 | 10933 | <h4><code><a title="exchangelib.properties.OldTimestampEvent" href="#exchangelib.properties.OldTimestampEvent">OldTimestampEvent</a></code></h4> |
10833 | 10934 | <ul class=""> |
10834 | 10935 | <li><code><a title="exchangelib.properties.OldTimestampEvent.FIELDS" href="#exchangelib.properties.OldTimestampEvent.FIELDS">FIELDS</a></code></li> |
10871 | 10972 | <li><code><a title="exchangelib.properties.Period.bias_in_minutes" href="#exchangelib.properties.Period.bias_in_minutes">bias_in_minutes</a></code></li> |
10872 | 10973 | <li><code><a title="exchangelib.properties.Period.id" href="#exchangelib.properties.Period.id">id</a></code></li> |
10873 | 10974 | <li><code><a title="exchangelib.properties.Period.name" href="#exchangelib.properties.Period.name">name</a></code></li> |
10874 | <li><code><a title="exchangelib.properties.Period.type" href="#exchangelib.properties.Period.type">type</a></code></li> | |
10875 | <li><code><a title="exchangelib.properties.Period.year" href="#exchangelib.properties.Period.year">year</a></code></li> | |
10876 | 10975 | </ul> |
10877 | 10976 | </li> |
10878 | 10977 | <li> |
11030 | 11129 | <ul class=""> |
11031 | 11130 | <li><code><a title="exchangelib.properties.ResponseObjects.ELEMENT_NAME" href="#exchangelib.properties.ResponseObjects.ELEMENT_NAME">ELEMENT_NAME</a></code></li> |
11032 | 11131 | <li><code><a title="exchangelib.properties.ResponseObjects.FIELDS" href="#exchangelib.properties.ResponseObjects.FIELDS">FIELDS</a></code></li> |
11033 | <li><code><a title="exchangelib.properties.ResponseObjects.NAMESPACE" href="#exchangelib.properties.ResponseObjects.NAMESPACE">NAMESPACE</a></code></li> | |
11034 | 11132 | <li><code><a title="exchangelib.properties.ResponseObjects.accept_item" href="#exchangelib.properties.ResponseObjects.accept_item">accept_item</a></code></li> |
11035 | 11133 | <li><code><a title="exchangelib.properties.ResponseObjects.accept_sharing_invitation" href="#exchangelib.properties.ResponseObjects.accept_sharing_invitation">accept_sharing_invitation</a></code></li> |
11036 | 11134 | <li><code><a title="exchangelib.properties.ResponseObjects.cancel_calendar_item" href="#exchangelib.properties.ResponseObjects.cancel_calendar_item">cancel_calendar_item</a></code></li> |
275 | 275 | session = self.renew_session(session) |
276 | 276 | self._session_pool.put(session, block=False) |
277 | 277 | |
278 | @staticmethod | |
279 | def close_session(session): | |
278 | def close_session(self, session): | |
279 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
280 | self.credentials, OAuth2AuthorizationCodeCredentials | |
281 | ): | |
282 | # Reset token if client is of type BackendApplicationClient | |
283 | self.credentials.access_token = None | |
280 | 284 | session.close() |
281 | 285 | del session |
282 | 286 | |
339 | 343 | return session |
340 | 344 | |
341 | 345 | def create_oauth2_session(self): |
342 | has_token = False | |
343 | scope = ["https://outlook.office365.com/.default"] | |
344 | session_params = {} | |
346 | session_params = {"token": self.credentials.access_token} # Token may be None | |
345 | 347 | token_params = {} |
346 | 348 | |
347 | 349 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
348 | # Ask for a refresh token | |
349 | scope.append("offline_access") | |
350 | ||
351 | # We don't know (or need) the Microsoft tenant ID. Use | |
352 | # common/ to let Microsoft select the appropriate tenant | |
353 | # for the provided authorization code or refresh token. | |
354 | # | |
355 | # Suppress looks-like-password warning from Bandit. | |
356 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
357 | ||
358 | client_params = {} | |
359 | has_token = self.credentials.access_token is not None | |
360 | if has_token: | |
361 | session_params["token"] = self.credentials.access_token | |
362 | elif self.credentials.authorization_code is not None: | |
363 | token_params["code"] = self.credentials.authorization_code | |
364 | self.credentials.authorization_code = None | |
365 | ||
366 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
367 | # If we're given a client ID and secret, we have enough | |
368 | # to refresh access tokens ourselves. In other cases the | |
369 | # session will raise TokenExpiredError and we'll need to | |
370 | # ask the calling application to refresh the token (that | |
371 | # covers cases where the caller doesn't have access to | |
372 | # the client secret but is working with a service that | |
373 | # can provide it refreshed tokens on a limited basis). | |
350 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
351 | self.credentials.authorization_code = None # We can only use the code once | |
352 | ||
353 | if self.credentials.client_id and self.credentials.client_secret: | |
354 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
355 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
356 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
357 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
374 | 358 | session_params.update( |
375 | 359 | { |
376 | 360 | "auto_refresh_kwargs": { |
377 | 361 | "client_id": self.credentials.client_id, |
378 | 362 | "client_secret": self.credentials.client_secret, |
379 | 363 | }, |
380 | "auto_refresh_url": token_url, | |
364 | "auto_refresh_url": self.credentials.token_url, | |
381 | 365 | "token_updater": self.credentials.on_token_auto_refreshed, |
382 | 366 | } |
383 | 367 | ) |
384 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
368 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
385 | 369 | else: |
386 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
387 | 370 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
388 | 371 | |
389 | 372 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
390 | if not has_token: | |
373 | if not session.token: | |
391 | 374 | # Fetch the token explicitly -- it doesn't occur implicitly |
392 | 375 | token = session.fetch_token( |
393 | token_url=token_url, | |
376 | token_url=self.credentials.token_url, | |
394 | 377 | client_id=self.credentials.client_id, |
395 | 378 | client_secret=self.credentials.client_secret, |
396 | scope=scope, | |
379 | scope=self.credentials.scope, | |
397 | 380 | timeout=self.TIMEOUT, |
398 | 381 | **token_params, |
399 | 382 | ) |
400 | # Allow the credentials object to update its copy of the new | |
401 | # token, and give the application an opportunity to cache it | |
383 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
384 | # to cache it. | |
402 | 385 | self.credentials.on_token_auto_refreshed(token) |
403 | 386 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
404 | 387 | |
553 | 536 | |
554 | 537 | tz_definition = list(self.get_timezones(timezones=[start.tzinfo], return_full_timezone_data=True))[0] |
555 | 538 | return GetUserAvailability(self).call( |
556 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
557 | 539 | mailbox_data=[ |
558 | 540 | MailboxData( |
559 | 541 | email=account.primary_smtp_address if isinstance(account, Account) else account, |
562 | 544 | ) |
563 | 545 | for account, attendee_type, exclude_conflicts in accounts |
564 | 546 | ], |
547 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
565 | 548 | free_busy_view_options=FreeBusyViewOptions( |
566 | 549 | time_window=TimeWindow(start=start, end=end), |
567 | 550 | merged_free_busy_interval=merged_free_busy_interval, |
1074 | 1057 | session = self.renew_session(session) |
1075 | 1058 | self._session_pool.put(session, block=False) |
1076 | 1059 | |
1077 | @staticmethod | |
1078 | def close_session(session): | |
1060 | def close_session(self, session): | |
1061 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
1062 | self.credentials, OAuth2AuthorizationCodeCredentials | |
1063 | ): | |
1064 | # Reset token if client is of type BackendApplicationClient | |
1065 | self.credentials.access_token = None | |
1079 | 1066 | session.close() |
1080 | 1067 | del session |
1081 | 1068 | |
1138 | 1125 | return session |
1139 | 1126 | |
1140 | 1127 | def create_oauth2_session(self): |
1141 | has_token = False | |
1142 | scope = ["https://outlook.office365.com/.default"] | |
1143 | session_params = {} | |
1128 | session_params = {"token": self.credentials.access_token} # Token may be None | |
1144 | 1129 | token_params = {} |
1145 | 1130 | |
1146 | 1131 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
1147 | # Ask for a refresh token | |
1148 | scope.append("offline_access") | |
1149 | ||
1150 | # We don't know (or need) the Microsoft tenant ID. Use | |
1151 | # common/ to let Microsoft select the appropriate tenant | |
1152 | # for the provided authorization code or refresh token. | |
1153 | # | |
1154 | # Suppress looks-like-password warning from Bandit. | |
1155 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
1156 | ||
1157 | client_params = {} | |
1158 | has_token = self.credentials.access_token is not None | |
1159 | if has_token: | |
1160 | session_params["token"] = self.credentials.access_token | |
1161 | elif self.credentials.authorization_code is not None: | |
1162 | token_params["code"] = self.credentials.authorization_code | |
1163 | self.credentials.authorization_code = None | |
1164 | ||
1165 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
1166 | # If we're given a client ID and secret, we have enough | |
1167 | # to refresh access tokens ourselves. In other cases the | |
1168 | # session will raise TokenExpiredError and we'll need to | |
1169 | # ask the calling application to refresh the token (that | |
1170 | # covers cases where the caller doesn't have access to | |
1171 | # the client secret but is working with a service that | |
1172 | # can provide it refreshed tokens on a limited basis). | |
1132 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
1133 | self.credentials.authorization_code = None # We can only use the code once | |
1134 | ||
1135 | if self.credentials.client_id and self.credentials.client_secret: | |
1136 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
1137 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
1138 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
1139 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
1173 | 1140 | session_params.update( |
1174 | 1141 | { |
1175 | 1142 | "auto_refresh_kwargs": { |
1176 | 1143 | "client_id": self.credentials.client_id, |
1177 | 1144 | "client_secret": self.credentials.client_secret, |
1178 | 1145 | }, |
1179 | "auto_refresh_url": token_url, | |
1146 | "auto_refresh_url": self.credentials.token_url, | |
1180 | 1147 | "token_updater": self.credentials.on_token_auto_refreshed, |
1181 | 1148 | } |
1182 | 1149 | ) |
1183 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
1150 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
1184 | 1151 | else: |
1185 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
1186 | 1152 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
1187 | 1153 | |
1188 | 1154 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
1189 | if not has_token: | |
1155 | if not session.token: | |
1190 | 1156 | # Fetch the token explicitly -- it doesn't occur implicitly |
1191 | 1157 | token = session.fetch_token( |
1192 | token_url=token_url, | |
1158 | token_url=self.credentials.token_url, | |
1193 | 1159 | client_id=self.credentials.client_id, |
1194 | 1160 | client_secret=self.credentials.client_secret, |
1195 | scope=scope, | |
1161 | scope=self.credentials.scope, | |
1196 | 1162 | timeout=self.TIMEOUT, |
1197 | 1163 | **token_params, |
1198 | 1164 | ) |
1199 | # Allow the credentials object to update its copy of the new | |
1200 | # token, and give the application an opportunity to cache it | |
1165 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
1166 | # to cache it. | |
1201 | 1167 | self.credentials.on_token_auto_refreshed(token) |
1202 | 1168 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
1203 | 1169 | |
1276 | 1242 | </dl> |
1277 | 1243 | <h3>Static methods</h3> |
1278 | 1244 | <dl> |
1279 | <dt id="exchangelib.protocol.BaseProtocol.close_session"><code class="name flex"> | |
1280 | <span>def <span class="ident">close_session</span></span>(<span>session)</span> | |
1281 | </code></dt> | |
1282 | <dd> | |
1283 | <div class="desc"></div> | |
1284 | <details class="source"> | |
1285 | <summary> | |
1286 | <span>Expand source code</span> | |
1287 | </summary> | |
1288 | <pre><code class="python">@staticmethod | |
1289 | def close_session(session): | |
1290 | session.close() | |
1291 | del session</code></pre> | |
1292 | </details> | |
1293 | </dd> | |
1294 | 1245 | <dt id="exchangelib.protocol.BaseProtocol.get_adapter"><code class="name flex"> |
1295 | 1246 | <span>def <span class="ident">get_adapter</span></span>(<span>)</span> |
1296 | 1247 | </code></dt> |
1433 | 1384 | break</code></pre> |
1434 | 1385 | </details> |
1435 | 1386 | </dd> |
1387 | <dt id="exchangelib.protocol.BaseProtocol.close_session"><code class="name flex"> | |
1388 | <span>def <span class="ident">close_session</span></span>(<span>self, session)</span> | |
1389 | </code></dt> | |
1390 | <dd> | |
1391 | <div class="desc"></div> | |
1392 | <details class="source"> | |
1393 | <summary> | |
1394 | <span>Expand source code</span> | |
1395 | </summary> | |
1396 | <pre><code class="python">def close_session(self, session): | |
1397 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
1398 | self.credentials, OAuth2AuthorizationCodeCredentials | |
1399 | ): | |
1400 | # Reset token if client is of type BackendApplicationClient | |
1401 | self.credentials.access_token = None | |
1402 | session.close() | |
1403 | del session</code></pre> | |
1404 | </details> | |
1405 | </dd> | |
1436 | 1406 | <dt id="exchangelib.protocol.BaseProtocol.create_oauth2_session"><code class="name flex"> |
1437 | 1407 | <span>def <span class="ident">create_oauth2_session</span></span>(<span>self)</span> |
1438 | 1408 | </code></dt> |
1443 | 1413 | <span>Expand source code</span> |
1444 | 1414 | </summary> |
1445 | 1415 | <pre><code class="python">def create_oauth2_session(self): |
1446 | has_token = False | |
1447 | scope = ["https://outlook.office365.com/.default"] | |
1448 | session_params = {} | |
1416 | session_params = {"token": self.credentials.access_token} # Token may be None | |
1449 | 1417 | token_params = {} |
1450 | 1418 | |
1451 | 1419 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
1452 | # Ask for a refresh token | |
1453 | scope.append("offline_access") | |
1454 | ||
1455 | # We don't know (or need) the Microsoft tenant ID. Use | |
1456 | # common/ to let Microsoft select the appropriate tenant | |
1457 | # for the provided authorization code or refresh token. | |
1458 | # | |
1459 | # Suppress looks-like-password warning from Bandit. | |
1460 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
1461 | ||
1462 | client_params = {} | |
1463 | has_token = self.credentials.access_token is not None | |
1464 | if has_token: | |
1465 | session_params["token"] = self.credentials.access_token | |
1466 | elif self.credentials.authorization_code is not None: | |
1467 | token_params["code"] = self.credentials.authorization_code | |
1468 | self.credentials.authorization_code = None | |
1469 | ||
1470 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
1471 | # If we're given a client ID and secret, we have enough | |
1472 | # to refresh access tokens ourselves. In other cases the | |
1473 | # session will raise TokenExpiredError and we'll need to | |
1474 | # ask the calling application to refresh the token (that | |
1475 | # covers cases where the caller doesn't have access to | |
1476 | # the client secret but is working with a service that | |
1477 | # can provide it refreshed tokens on a limited basis). | |
1420 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
1421 | self.credentials.authorization_code = None # We can only use the code once | |
1422 | ||
1423 | if self.credentials.client_id and self.credentials.client_secret: | |
1424 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
1425 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
1426 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
1427 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
1478 | 1428 | session_params.update( |
1479 | 1429 | { |
1480 | 1430 | "auto_refresh_kwargs": { |
1481 | 1431 | "client_id": self.credentials.client_id, |
1482 | 1432 | "client_secret": self.credentials.client_secret, |
1483 | 1433 | }, |
1484 | "auto_refresh_url": token_url, | |
1434 | "auto_refresh_url": self.credentials.token_url, | |
1485 | 1435 | "token_updater": self.credentials.on_token_auto_refreshed, |
1486 | 1436 | } |
1487 | 1437 | ) |
1488 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
1438 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
1489 | 1439 | else: |
1490 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
1491 | 1440 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
1492 | 1441 | |
1493 | 1442 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
1494 | if not has_token: | |
1443 | if not session.token: | |
1495 | 1444 | # Fetch the token explicitly -- it doesn't occur implicitly |
1496 | 1445 | token = session.fetch_token( |
1497 | token_url=token_url, | |
1446 | token_url=self.credentials.token_url, | |
1498 | 1447 | client_id=self.credentials.client_id, |
1499 | 1448 | client_secret=self.credentials.client_secret, |
1500 | scope=scope, | |
1449 | scope=self.credentials.scope, | |
1501 | 1450 | timeout=self.TIMEOUT, |
1502 | 1451 | **token_params, |
1503 | 1452 | ) |
1504 | # Allow the credentials object to update its copy of the new | |
1505 | # token, and give the application an opportunity to cache it | |
1453 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
1454 | # to cache it. | |
1506 | 1455 | self.credentials.on_token_auto_refreshed(token) |
1507 | 1456 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
1508 | 1457 | |
2165 | 2114 | |
2166 | 2115 | tz_definition = list(self.get_timezones(timezones=[start.tzinfo], return_full_timezone_data=True))[0] |
2167 | 2116 | return GetUserAvailability(self).call( |
2168 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
2169 | 2117 | mailbox_data=[ |
2170 | 2118 | MailboxData( |
2171 | 2119 | email=account.primary_smtp_address if isinstance(account, Account) else account, |
2174 | 2122 | ) |
2175 | 2123 | for account, attendee_type, exclude_conflicts in accounts |
2176 | 2124 | ], |
2125 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
2177 | 2126 | free_busy_view_options=FreeBusyViewOptions( |
2178 | 2127 | time_window=TimeWindow(start=start, end=end), |
2179 | 2128 | merged_free_busy_interval=merged_free_busy_interval, |
2381 | 2330 | |
2382 | 2331 | tz_definition = list(self.get_timezones(timezones=[start.tzinfo], return_full_timezone_data=True))[0] |
2383 | 2332 | return GetUserAvailability(self).call( |
2384 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
2385 | 2333 | mailbox_data=[ |
2386 | 2334 | MailboxData( |
2387 | 2335 | email=account.primary_smtp_address if isinstance(account, Account) else account, |
2390 | 2338 | ) |
2391 | 2339 | for account, attendee_type, exclude_conflicts in accounts |
2392 | 2340 | ], |
2341 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
2393 | 2342 | free_busy_view_options=FreeBusyViewOptions( |
2394 | 2343 | time_window=TimeWindow(start=start, end=end), |
2395 | 2344 | merged_free_busy_interval=merged_free_busy_interval, |
27 | 27 | </summary> |
28 | 28 | <pre><code class="python">import abc |
29 | 29 | import logging |
30 | import traceback | |
31 | 30 | from itertools import chain |
32 | 31 | |
33 | 32 | from .. import errors |
34 | 33 | from ..attachments import AttachmentId |
35 | 34 | from ..credentials import IMPERSONATION, OAuth2Credentials |
36 | 35 | from ..errors import ( |
37 | ErrorAccessDenied, | |
38 | ErrorADUnavailable, | |
39 | 36 | ErrorBatchProcessingStopped, |
40 | 37 | ErrorCannotDeleteObject, |
41 | 38 | ErrorCannotDeleteTaskOccurrence, |
42 | ErrorCannotEmptyFolder, | |
43 | ErrorConnectionFailed, | |
44 | ErrorConnectionFailedTransientError, | |
45 | 39 | ErrorCorruptData, |
46 | ErrorCreateItemAccessDenied, | |
47 | ErrorDelegateNoUser, | |
48 | ErrorDeleteDistinguishedFolder, | |
49 | 40 | ErrorExceededConnectionCount, |
50 | ErrorFolderNotFound, | |
51 | ErrorImpersonateUserDenied, | |
52 | ErrorImpersonationFailed, | |
53 | 41 | ErrorIncorrectSchemaVersion, |
54 | ErrorInternalServerError, | |
55 | ErrorInternalServerTransientError, | |
56 | 42 | ErrorInvalidChangeKey, |
57 | 43 | ErrorInvalidIdMalformed, |
58 | ErrorInvalidLicense, | |
59 | 44 | ErrorInvalidRequest, |
60 | 45 | ErrorInvalidSchemaVersionForMailboxVersion, |
61 | 46 | ErrorInvalidServerVersion, |
62 | ErrorInvalidSubscription, | |
63 | ErrorInvalidSyncStateData, | |
64 | ErrorInvalidWatermark, | |
65 | 47 | ErrorItemCorrupt, |
66 | 48 | ErrorItemNotFound, |
67 | 49 | ErrorItemSave, |
68 | ErrorMailboxMoveInProgress, | |
69 | ErrorMailboxStoreUnavailable, | |
50 | ErrorMailRecipientNotFound, | |
70 | 51 | ErrorMessageSizeExceeded, |
71 | 52 | ErrorMimeContentConversionFailed, |
72 | ErrorNameResolutionMultipleResults, | |
73 | ErrorNameResolutionNoResults, | |
74 | ErrorNonExistentMailbox, | |
75 | ErrorNoPublicFolderReplicaAvailable, | |
76 | ErrorNoRespondingCASInDestinationSite, | |
77 | ErrorNotDelegate, | |
78 | ErrorQuotaExceeded, | |
79 | 53 | ErrorRecurrenceHasNoOccurrence, |
80 | 54 | ErrorServerBusy, |
81 | 55 | ErrorTimeoutExpired, |
83 | 57 | EWSWarning, |
84 | 58 | InvalidTypeError, |
85 | 59 | MalformedResponseError, |
86 | RateLimitError, | |
87 | 60 | SessionPoolMinSizeReached, |
88 | 61 | SOAPError, |
89 | 62 | TransportError, |
90 | UnauthorizedError, | |
91 | 63 | ) |
92 | 64 | from ..folders import BaseFolder, Folder, RootOfHierarchy |
93 | 65 | from ..items import BaseItem |
125 | 97 | PAGE_SIZE = 100 # A default page size for all paging services. This is the number of items we request per page |
126 | 98 | CHUNK_SIZE = 100 # A default chunk size for all services. This is the number of items we send in a single request |
127 | 99 | |
128 | KNOWN_EXCEPTIONS = ( | |
129 | ErrorAccessDenied, | |
130 | ErrorADUnavailable, | |
131 | ErrorBatchProcessingStopped, | |
132 | ErrorCannotDeleteObject, | |
133 | ErrorCannotEmptyFolder, | |
134 | ErrorConnectionFailed, | |
135 | ErrorConnectionFailedTransientError, | |
136 | ErrorCreateItemAccessDenied, | |
137 | ErrorDelegateNoUser, | |
138 | ErrorDeleteDistinguishedFolder, | |
139 | ErrorExceededConnectionCount, | |
140 | ErrorFolderNotFound, | |
141 | ErrorImpersonateUserDenied, | |
142 | ErrorImpersonationFailed, | |
143 | ErrorInternalServerError, | |
144 | ErrorInternalServerTransientError, | |
145 | ErrorInvalidChangeKey, | |
146 | ErrorInvalidLicense, | |
147 | ErrorInvalidSubscription, | |
148 | ErrorInvalidSyncStateData, | |
149 | ErrorInvalidWatermark, | |
150 | ErrorItemCorrupt, | |
151 | ErrorItemNotFound, | |
152 | ErrorMailboxMoveInProgress, | |
153 | ErrorMailboxStoreUnavailable, | |
154 | ErrorNameResolutionMultipleResults, | |
155 | ErrorNameResolutionNoResults, | |
156 | ErrorNonExistentMailbox, | |
157 | ErrorNoPublicFolderReplicaAvailable, | |
158 | ErrorNoRespondingCASInDestinationSite, | |
159 | ErrorNotDelegate, | |
160 | ErrorQuotaExceeded, | |
161 | ErrorTimeoutExpired, | |
162 | RateLimitError, | |
163 | UnauthorizedError, | |
164 | ) | |
165 | ||
166 | 100 | |
167 | 101 | class EWSService(metaclass=abc.ABCMeta): |
168 | 102 | """Base class for all EWS services.""" |
185 | 119 | ErrorRecurrenceHasNoOccurrence, |
186 | 120 | ErrorCorruptData, |
187 | 121 | ErrorItemCorrupt, |
122 | ErrorMailRecipientNotFound, | |
188 | 123 | ) |
189 | 124 | # Similarly, define the warnings we want to return unraised |
190 | 125 | WARNINGS_TO_CATCH_IN_RESPONSE = ErrorBatchProcessingStopped |
359 | 294 | except ErrorServerBusy as e: |
360 | 295 | self._handle_backoff(e) |
361 | 296 | continue |
362 | except KNOWN_EXCEPTIONS: | |
363 | # These are known and understood, and don't require a backtrace. | |
364 | raise | |
365 | 297 | except (ErrorTooManyObjectsOpened, ErrorTimeoutExpired) as e: |
366 | 298 | # ErrorTooManyObjectsOpened means there are too many connections to the Exchange database. This is very |
367 | 299 | # often a symptom of sending too many requests. |
376 | 308 | |
377 | 309 | # Re-raise as an ErrorServerBusy with a default delay of 5 minutes |
378 | 310 | raise ErrorServerBusy(f"Reraised from {e.__class__.__name__}({e})") |
379 | except Exception: | |
380 | # This may run in a thread, which obfuscates the stack trace. Print trace immediately. | |
381 | account = self.account if isinstance(self, EWSAccountService) else None | |
382 | log.warning("Account %s: Exception in _get_elements: %s", account, traceback.format_exc(20)) | |
383 | raise | |
384 | 311 | finally: |
385 | 312 | if self.streaming: |
386 | 313 | self.stop_streaming() |
808 | 735 | def _account_to_impersonate(self): |
809 | 736 | if self.account.access_type == IMPERSONATION: |
810 | 737 | return self.account.identity |
811 | return None | |
738 | return super()._account_to_impersonate | |
812 | 739 | |
813 | 740 | @property |
814 | 741 | def _timezone(self): |
1231 | 1158 | def _account_to_impersonate(self): |
1232 | 1159 | if self.account.access_type == IMPERSONATION: |
1233 | 1160 | return self.account.identity |
1234 | return None | |
1161 | return super()._account_to_impersonate | |
1235 | 1162 | |
1236 | 1163 | @property |
1237 | 1164 | def _timezone(self): |
1503 | 1430 | ErrorRecurrenceHasNoOccurrence, |
1504 | 1431 | ErrorCorruptData, |
1505 | 1432 | ErrorItemCorrupt, |
1433 | ErrorMailRecipientNotFound, | |
1506 | 1434 | ) |
1507 | 1435 | # Similarly, define the warnings we want to return unraised |
1508 | 1436 | WARNINGS_TO_CATCH_IN_RESPONSE = ErrorBatchProcessingStopped |
1677 | 1605 | except ErrorServerBusy as e: |
1678 | 1606 | self._handle_backoff(e) |
1679 | 1607 | continue |
1680 | except KNOWN_EXCEPTIONS: | |
1681 | # These are known and understood, and don't require a backtrace. | |
1682 | raise | |
1683 | 1608 | except (ErrorTooManyObjectsOpened, ErrorTimeoutExpired) as e: |
1684 | 1609 | # ErrorTooManyObjectsOpened means there are too many connections to the Exchange database. This is very |
1685 | 1610 | # often a symptom of sending too many requests. |
1694 | 1619 | |
1695 | 1620 | # Re-raise as an ErrorServerBusy with a default delay of 5 minutes |
1696 | 1621 | raise ErrorServerBusy(f"Reraised from {e.__class__.__name__}({e})") |
1697 | except Exception: | |
1698 | # This may run in a thread, which obfuscates the stack trace. Print trace immediately. | |
1699 | account = self.account if isinstance(self, EWSAccountService) else None | |
1700 | log.warning("Account %s: Exception in _get_elements: %s", account, traceback.format_exc(20)) | |
1701 | raise | |
1702 | 1622 | finally: |
1703 | 1623 | if self.streaming: |
1704 | 1624 | self.stop_streaming() |
38 | 38 | |
39 | 39 | SERVICE_NAME = "GetUserAvailability" |
40 | 40 | |
41 | def call(self, timezone, mailbox_data, free_busy_view_options): | |
41 | def call(self, mailbox_data, timezone, free_busy_view_options): | |
42 | 42 | # TODO: Also supports SuggestionsViewOptions, see |
43 | 43 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
44 | 44 | return self._elems_to_objs( |
45 | self._get_elements( | |
46 | payload=self.get_payload( | |
47 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
48 | ) | |
45 | self._chunked_get_elements( | |
46 | self.get_payload, | |
47 | items=mailbox_data, | |
48 | timezone=timezone, | |
49 | free_busy_view_options=free_busy_view_options, | |
49 | 50 | ) |
50 | 51 | ) |
51 | 52 | |
52 | 53 | def _elem_to_obj(self, elem): |
53 | 54 | return FreeBusyView.from_xml(elem=elem, account=None) |
54 | 55 | |
55 | def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
56 | def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
56 | 57 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
57 | 58 | set_xml_value(payload, timezone, version=self.protocol.version) |
58 | 59 | mailbox_data_array = create_element("m:MailboxDataArray") |
70 | 71 | |
71 | 72 | def _get_elements_in_response(self, response): |
72 | 73 | for msg in response: |
73 | # Just check the response code and raise errors | |
74 | self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
75 | yield from self._get_elements_in_container(container=msg) | |
74 | container_or_exc = self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
75 | if isinstance(container_or_exc, Exception): | |
76 | yield container_or_exc | |
77 | else: | |
78 | yield from self._get_elements_in_container(container=msg) | |
76 | 79 | |
77 | 80 | @classmethod |
78 | 81 | def _get_elements_in_container(cls, container): |
108 | 111 | |
109 | 112 | SERVICE_NAME = "GetUserAvailability" |
110 | 113 | |
111 | def call(self, timezone, mailbox_data, free_busy_view_options): | |
114 | def call(self, mailbox_data, timezone, free_busy_view_options): | |
112 | 115 | # TODO: Also supports SuggestionsViewOptions, see |
113 | 116 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
114 | 117 | return self._elems_to_objs( |
115 | self._get_elements( | |
116 | payload=self.get_payload( | |
117 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
118 | ) | |
118 | self._chunked_get_elements( | |
119 | self.get_payload, | |
120 | items=mailbox_data, | |
121 | timezone=timezone, | |
122 | free_busy_view_options=free_busy_view_options, | |
119 | 123 | ) |
120 | 124 | ) |
121 | 125 | |
122 | 126 | def _elem_to_obj(self, elem): |
123 | 127 | return FreeBusyView.from_xml(elem=elem, account=None) |
124 | 128 | |
125 | def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
129 | def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
126 | 130 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
127 | 131 | set_xml_value(payload, timezone, version=self.protocol.version) |
128 | 132 | mailbox_data_array = create_element("m:MailboxDataArray") |
140 | 144 | |
141 | 145 | def _get_elements_in_response(self, response): |
142 | 146 | for msg in response: |
143 | # Just check the response code and raise errors | |
144 | self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
145 | yield from self._get_elements_in_container(container=msg) | |
147 | container_or_exc = self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
148 | if isinstance(container_or_exc, Exception): | |
149 | yield container_or_exc | |
150 | else: | |
151 | yield from self._get_elements_in_container(container=msg) | |
146 | 152 | |
147 | 153 | @classmethod |
148 | 154 | def _get_elements_in_container(cls, container): |
162 | 168 | <h3>Methods</h3> |
163 | 169 | <dl> |
164 | 170 | <dt id="exchangelib.services.get_user_availability.GetUserAvailability.call"><code class="name flex"> |
165 | <span>def <span class="ident">call</span></span>(<span>self, timezone, mailbox_data, free_busy_view_options)</span> | |
171 | <span>def <span class="ident">call</span></span>(<span>self, mailbox_data, timezone, free_busy_view_options)</span> | |
166 | 172 | </code></dt> |
167 | 173 | <dd> |
168 | 174 | <div class="desc"></div> |
170 | 176 | <summary> |
171 | 177 | <span>Expand source code</span> |
172 | 178 | </summary> |
173 | <pre><code class="python">def call(self, timezone, mailbox_data, free_busy_view_options): | |
179 | <pre><code class="python">def call(self, mailbox_data, timezone, free_busy_view_options): | |
174 | 180 | # TODO: Also supports SuggestionsViewOptions, see |
175 | 181 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
176 | 182 | return self._elems_to_objs( |
177 | self._get_elements( | |
178 | payload=self.get_payload( | |
179 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
180 | ) | |
183 | self._chunked_get_elements( | |
184 | self.get_payload, | |
185 | items=mailbox_data, | |
186 | timezone=timezone, | |
187 | free_busy_view_options=free_busy_view_options, | |
181 | 188 | ) |
182 | 189 | )</code></pre> |
183 | 190 | </details> |
184 | 191 | </dd> |
185 | 192 | <dt id="exchangelib.services.get_user_availability.GetUserAvailability.get_payload"><code class="name flex"> |
186 | <span>def <span class="ident">get_payload</span></span>(<span>self, timezone, mailbox_data, free_busy_view_options)</span> | |
193 | <span>def <span class="ident">get_payload</span></span>(<span>self, mailbox_data, timezone, free_busy_view_options)</span> | |
187 | 194 | </code></dt> |
188 | 195 | <dd> |
189 | 196 | <div class="desc"></div> |
191 | 198 | <summary> |
192 | 199 | <span>Expand source code</span> |
193 | 200 | </summary> |
194 | <pre><code class="python">def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
201 | <pre><code class="python">def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
195 | 202 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
196 | 203 | set_xml_value(payload, timezone, version=self.protocol.version) |
197 | 204 | mailbox_data_array = create_element("m:MailboxDataArray") |
4192 | 4192 | |
4193 | 4193 | SERVICE_NAME = "GetUserAvailability" |
4194 | 4194 | |
4195 | def call(self, timezone, mailbox_data, free_busy_view_options): | |
4195 | def call(self, mailbox_data, timezone, free_busy_view_options): | |
4196 | 4196 | # TODO: Also supports SuggestionsViewOptions, see |
4197 | 4197 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
4198 | 4198 | return self._elems_to_objs( |
4199 | self._get_elements( | |
4200 | payload=self.get_payload( | |
4201 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
4202 | ) | |
4199 | self._chunked_get_elements( | |
4200 | self.get_payload, | |
4201 | items=mailbox_data, | |
4202 | timezone=timezone, | |
4203 | free_busy_view_options=free_busy_view_options, | |
4203 | 4204 | ) |
4204 | 4205 | ) |
4205 | 4206 | |
4206 | 4207 | def _elem_to_obj(self, elem): |
4207 | 4208 | return FreeBusyView.from_xml(elem=elem, account=None) |
4208 | 4209 | |
4209 | def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
4210 | def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
4210 | 4211 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
4211 | 4212 | set_xml_value(payload, timezone, version=self.protocol.version) |
4212 | 4213 | mailbox_data_array = create_element("m:MailboxDataArray") |
4224 | 4225 | |
4225 | 4226 | def _get_elements_in_response(self, response): |
4226 | 4227 | for msg in response: |
4227 | # Just check the response code and raise errors | |
4228 | self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
4229 | yield from self._get_elements_in_container(container=msg) | |
4228 | container_or_exc = self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
4229 | if isinstance(container_or_exc, Exception): | |
4230 | yield container_or_exc | |
4231 | else: | |
4232 | yield from self._get_elements_in_container(container=msg) | |
4230 | 4233 | |
4231 | 4234 | @classmethod |
4232 | 4235 | def _get_elements_in_container(cls, container): |
4246 | 4249 | <h3>Methods</h3> |
4247 | 4250 | <dl> |
4248 | 4251 | <dt id="exchangelib.services.GetUserAvailability.call"><code class="name flex"> |
4249 | <span>def <span class="ident">call</span></span>(<span>self, timezone, mailbox_data, free_busy_view_options)</span> | |
4250 | </code></dt> | |
4251 | <dd> | |
4252 | <div class="desc"></div> | |
4253 | <details class="source"> | |
4254 | <summary> | |
4255 | <span>Expand source code</span> | |
4256 | </summary> | |
4257 | <pre><code class="python">def call(self, timezone, mailbox_data, free_busy_view_options): | |
4252 | <span>def <span class="ident">call</span></span>(<span>self, mailbox_data, timezone, free_busy_view_options)</span> | |
4253 | </code></dt> | |
4254 | <dd> | |
4255 | <div class="desc"></div> | |
4256 | <details class="source"> | |
4257 | <summary> | |
4258 | <span>Expand source code</span> | |
4259 | </summary> | |
4260 | <pre><code class="python">def call(self, mailbox_data, timezone, free_busy_view_options): | |
4258 | 4261 | # TODO: Also supports SuggestionsViewOptions, see |
4259 | 4262 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
4260 | 4263 | return self._elems_to_objs( |
4261 | self._get_elements( | |
4262 | payload=self.get_payload( | |
4263 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
4264 | ) | |
4264 | self._chunked_get_elements( | |
4265 | self.get_payload, | |
4266 | items=mailbox_data, | |
4267 | timezone=timezone, | |
4268 | free_busy_view_options=free_busy_view_options, | |
4265 | 4269 | ) |
4266 | 4270 | )</code></pre> |
4267 | 4271 | </details> |
4268 | 4272 | </dd> |
4269 | 4273 | <dt id="exchangelib.services.GetUserAvailability.get_payload"><code class="name flex"> |
4270 | <span>def <span class="ident">get_payload</span></span>(<span>self, timezone, mailbox_data, free_busy_view_options)</span> | |
4271 | </code></dt> | |
4272 | <dd> | |
4273 | <div class="desc"></div> | |
4274 | <details class="source"> | |
4275 | <summary> | |
4276 | <span>Expand source code</span> | |
4277 | </summary> | |
4278 | <pre><code class="python">def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
4274 | <span>def <span class="ident">get_payload</span></span>(<span>self, mailbox_data, timezone, free_busy_view_options)</span> | |
4275 | </code></dt> | |
4276 | <dd> | |
4277 | <div class="desc"></div> | |
4278 | <details class="source"> | |
4279 | <summary> | |
4280 | <span>Expand source code</span> | |
4281 | </summary> | |
4282 | <pre><code class="python">def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
4279 | 4283 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
4280 | 4284 | set_xml_value(payload, timezone, version=self.protocol.version) |
4281 | 4285 | mailbox_data_array = create_element("m:MailboxDataArray") |
4811 | 4815 | ERRORS_TO_CATCH_IN_RESPONSE = ErrorNameResolutionNoResults |
4812 | 4816 | WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults |
4813 | 4817 | # Note: paging information is returned as attrs on the 'ResolutionSet' element, but this service does not |
4814 | # support the 'IndexedPageItemView' element, so it's not really a paging service. According to docs, at most | |
4815 | # 100 candidates are returned for a lookup. | |
4818 | # support the 'IndexedPageItemView' element, so it's not really a paging service. | |
4816 | 4819 | supports_paging = False |
4820 | # According to the 'Remarks' section of the MSDN documentation referenced above, at most 100 candidates are | |
4821 | # returned for a lookup. | |
4822 | candidates_limit = 100 | |
4817 | 4823 | |
4818 | 4824 | def __init__(self, *args, **kwargs): |
4819 | 4825 | super().__init__(*args, **kwargs) |
4848 | 4854 | ) |
4849 | 4855 | ) |
4850 | 4856 | |
4857 | def _get_element_container(self, message, name=None): | |
4858 | container_or_exc = super()._get_element_container(message=message, name=name) | |
4859 | if isinstance(container_or_exc, Exception): | |
4860 | return container_or_exc | |
4861 | is_last_page = container_or_exc.get("IncludesLastItemInRange").lower() in ("true", "0") | |
4862 | log.debug("Includes last item in range: %s", is_last_page) | |
4863 | if not is_last_page: | |
4864 | warnings.warn( | |
4865 | f"The {self.__class__.__name__} service returns at most {self.candidates_limit} candidates and does " | |
4866 | f"not support paging. You have reached this limit and have not received the exhaustive list of " | |
4867 | f"candidates." | |
4868 | ) | |
4869 | return container_or_exc | |
4870 | ||
4851 | 4871 | def _elem_to_obj(self, elem): |
4852 | 4872 | if self.return_full_contact_data: |
4853 | 4873 | mailbox_elem = elem.find(Mailbox.response_tag()) |
4896 | 4916 | <dt id="exchangelib.services.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE"><code class="name">var <span class="ident">WARNINGS_TO_IGNORE_IN_RESPONSE</span></code></dt> |
4897 | 4917 | <dd> |
4898 | 4918 | <div class="desc"><p>Global error type within this module.</p></div> |
4919 | </dd> | |
4920 | <dt id="exchangelib.services.ResolveNames.candidates_limit"><code class="name">var <span class="ident">candidates_limit</span></code></dt> | |
4921 | <dd> | |
4922 | <div class="desc"></div> | |
4899 | 4923 | </dd> |
4900 | 4924 | <dt id="exchangelib.services.ResolveNames.element_container_name"><code class="name">var <span class="ident">element_container_name</span></code></dt> |
4901 | 4925 | <dd> |
7005 | 7029 | <li><code><a title="exchangelib.services.ResolveNames.SERVICE_NAME" href="#exchangelib.services.ResolveNames.SERVICE_NAME">SERVICE_NAME</a></code></li> |
7006 | 7030 | <li><code><a title="exchangelib.services.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE" href="#exchangelib.services.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE">WARNINGS_TO_IGNORE_IN_RESPONSE</a></code></li> |
7007 | 7031 | <li><code><a title="exchangelib.services.ResolveNames.call" href="#exchangelib.services.ResolveNames.call">call</a></code></li> |
7032 | <li><code><a title="exchangelib.services.ResolveNames.candidates_limit" href="#exchangelib.services.ResolveNames.candidates_limit">candidates_limit</a></code></li> | |
7008 | 7033 | <li><code><a title="exchangelib.services.ResolveNames.element_container_name" href="#exchangelib.services.ResolveNames.element_container_name">element_container_name</a></code></li> |
7009 | 7034 | <li><code><a title="exchangelib.services.ResolveNames.get_payload" href="#exchangelib.services.ResolveNames.get_payload">get_payload</a></code></li> |
7010 | 7035 | <li><code><a title="exchangelib.services.ResolveNames.supports_paging" href="#exchangelib.services.ResolveNames.supports_paging">supports_paging</a></code></li> |
26 | 26 | <span>Expand source code</span> |
27 | 27 | </summary> |
28 | 28 | <pre><code class="python">import logging |
29 | import warnings | |
29 | 30 | |
30 | 31 | from ..errors import ErrorNameResolutionMultipleResults, ErrorNameResolutionNoResults, InvalidEnumValue |
31 | 32 | from ..items import SEARCH_SCOPE_CHOICES, SHAPE_CHOICES, Contact |
45 | 46 | ERRORS_TO_CATCH_IN_RESPONSE = ErrorNameResolutionNoResults |
46 | 47 | WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults |
47 | 48 | # Note: paging information is returned as attrs on the 'ResolutionSet' element, but this service does not |
48 | # support the 'IndexedPageItemView' element, so it's not really a paging service. According to docs, at most | |
49 | # 100 candidates are returned for a lookup. | |
49 | # support the 'IndexedPageItemView' element, so it's not really a paging service. | |
50 | 50 | supports_paging = False |
51 | # According to the 'Remarks' section of the MSDN documentation referenced above, at most 100 candidates are | |
52 | # returned for a lookup. | |
53 | candidates_limit = 100 | |
51 | 54 | |
52 | 55 | def __init__(self, *args, **kwargs): |
53 | 56 | super().__init__(*args, **kwargs) |
81 | 84 | contact_data_shape=contact_data_shape, |
82 | 85 | ) |
83 | 86 | ) |
87 | ||
88 | def _get_element_container(self, message, name=None): | |
89 | container_or_exc = super()._get_element_container(message=message, name=name) | |
90 | if isinstance(container_or_exc, Exception): | |
91 | return container_or_exc | |
92 | is_last_page = container_or_exc.get("IncludesLastItemInRange").lower() in ("true", "0") | |
93 | log.debug("Includes last item in range: %s", is_last_page) | |
94 | if not is_last_page: | |
95 | warnings.warn( | |
96 | f"The {self.__class__.__name__} service returns at most {self.candidates_limit} candidates and does " | |
97 | f"not support paging. You have reached this limit and have not received the exhaustive list of " | |
98 | f"candidates." | |
99 | ) | |
100 | return container_or_exc | |
84 | 101 | |
85 | 102 | def _elem_to_obj(self, elem): |
86 | 103 | if self.return_full_contact_data: |
141 | 158 | ERRORS_TO_CATCH_IN_RESPONSE = ErrorNameResolutionNoResults |
142 | 159 | WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults |
143 | 160 | # Note: paging information is returned as attrs on the 'ResolutionSet' element, but this service does not |
144 | # support the 'IndexedPageItemView' element, so it's not really a paging service. According to docs, at most | |
145 | # 100 candidates are returned for a lookup. | |
161 | # support the 'IndexedPageItemView' element, so it's not really a paging service. | |
146 | 162 | supports_paging = False |
163 | # According to the 'Remarks' section of the MSDN documentation referenced above, at most 100 candidates are | |
164 | # returned for a lookup. | |
165 | candidates_limit = 100 | |
147 | 166 | |
148 | 167 | def __init__(self, *args, **kwargs): |
149 | 168 | super().__init__(*args, **kwargs) |
177 | 196 | contact_data_shape=contact_data_shape, |
178 | 197 | ) |
179 | 198 | ) |
199 | ||
200 | def _get_element_container(self, message, name=None): | |
201 | container_or_exc = super()._get_element_container(message=message, name=name) | |
202 | if isinstance(container_or_exc, Exception): | |
203 | return container_or_exc | |
204 | is_last_page = container_or_exc.get("IncludesLastItemInRange").lower() in ("true", "0") | |
205 | log.debug("Includes last item in range: %s", is_last_page) | |
206 | if not is_last_page: | |
207 | warnings.warn( | |
208 | f"The {self.__class__.__name__} service returns at most {self.candidates_limit} candidates and does " | |
209 | f"not support paging. You have reached this limit and have not received the exhaustive list of " | |
210 | f"candidates." | |
211 | ) | |
212 | return container_or_exc | |
180 | 213 | |
181 | 214 | def _elem_to_obj(self, elem): |
182 | 215 | if self.return_full_contact_data: |
226 | 259 | <dt id="exchangelib.services.resolve_names.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE"><code class="name">var <span class="ident">WARNINGS_TO_IGNORE_IN_RESPONSE</span></code></dt> |
227 | 260 | <dd> |
228 | 261 | <div class="desc"><p>Global error type within this module.</p></div> |
262 | </dd> | |
263 | <dt id="exchangelib.services.resolve_names.ResolveNames.candidates_limit"><code class="name">var <span class="ident">candidates_limit</span></code></dt> | |
264 | <dd> | |
265 | <div class="desc"></div> | |
229 | 266 | </dd> |
230 | 267 | <dt id="exchangelib.services.resolve_names.ResolveNames.element_container_name"><code class="name">var <span class="ident">element_container_name</span></code></dt> |
231 | 268 | <dd> |
344 | 381 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.SERVICE_NAME" href="#exchangelib.services.resolve_names.ResolveNames.SERVICE_NAME">SERVICE_NAME</a></code></li> |
345 | 382 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE" href="#exchangelib.services.resolve_names.ResolveNames.WARNINGS_TO_IGNORE_IN_RESPONSE">WARNINGS_TO_IGNORE_IN_RESPONSE</a></code></li> |
346 | 383 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.call" href="#exchangelib.services.resolve_names.ResolveNames.call">call</a></code></li> |
384 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.candidates_limit" href="#exchangelib.services.resolve_names.ResolveNames.candidates_limit">candidates_limit</a></code></li> | |
347 | 385 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.element_container_name" href="#exchangelib.services.resolve_names.ResolveNames.element_container_name">element_container_name</a></code></li> |
348 | 386 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.get_payload" href="#exchangelib.services.resolve_names.ResolveNames.get_payload">get_payload</a></code></li> |
349 | 387 | <li><code><a title="exchangelib.services.resolve_names.ResolveNames.supports_paging" href="#exchangelib.services.resolve_names.ResolveNames.supports_paging">supports_paging</a></code></li> |
49 | 49 | from pygments import highlight |
50 | 50 | from pygments.formatters.terminal import TerminalFormatter |
51 | 51 | from pygments.lexers.html import XmlLexer |
52 | from requests_oauthlib import OAuth2Session | |
52 | 53 | |
53 | 54 | from .errors import ( |
54 | 55 | InvalidTypeError, |
600 | 601 | class PrettyXmlHandler(logging.StreamHandler): |
601 | 602 | """A steaming log handler that prettifies log statements containing XML when output is a terminal.""" |
602 | 603 | |
603 | @staticmethod | |
604 | def parse_bytes(xml_bytes): | |
604 | def parse_bytes(self, xml_bytes): | |
605 | 605 | return to_xml(xml_bytes) |
606 | 606 | |
607 | @classmethod | |
608 | def prettify_xml(cls, xml_bytes): | |
607 | def prettify_xml(self, xml_bytes): | |
609 | 608 | """Re-format an XML document to a consistent style.""" |
610 | 609 | return ( |
611 | lxml.etree.tostring(cls.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
610 | lxml.etree.tostring(self.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
612 | 611 | .replace(b"\t", b" ") |
613 | 612 | .replace(b" xmlns:", b"\n xmlns:") |
614 | 613 | ) |
866 | 865 | d_start = time.monotonic() |
867 | 866 | # Always create a dummy response for logging purposes, in case we fail in the following |
868 | 867 | r = DummyResponse(url=url, request_headers=headers) |
868 | kwargs = dict(url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream) | |
869 | if isinstance(session, OAuth2Session): | |
870 | # Fix token refreshing bug. Reported as https://github.com/requests/requests-oauthlib/issues/498 | |
871 | kwargs.update(session.auto_refresh_kwargs) | |
869 | 872 | try: |
870 | r = session.post( | |
871 | url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream | |
872 | ) | |
873 | r = session.post(**kwargs) | |
873 | 874 | except TLS_ERRORS as e: |
874 | 875 | # Don't retry on TLS errors. They will most likely be persistent. |
875 | 876 | raise TransportError(str(e)) |
1390 | 1391 | d_start = time.monotonic() |
1391 | 1392 | # Always create a dummy response for logging purposes, in case we fail in the following |
1392 | 1393 | r = DummyResponse(url=url, request_headers=headers) |
1394 | kwargs = dict(url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream) | |
1395 | if isinstance(session, OAuth2Session): | |
1396 | # Fix token refreshing bug. Reported as https://github.com/requests/requests-oauthlib/issues/498 | |
1397 | kwargs.update(session.auto_refresh_kwargs) | |
1393 | 1398 | try: |
1394 | r = session.post( | |
1395 | url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream | |
1396 | ) | |
1399 | r = session.post(**kwargs) | |
1397 | 1400 | except TLS_ERRORS as e: |
1398 | 1401 | # Don't retry on TLS errors. They will most likely be persistent. |
1399 | 1402 | raise TransportError(str(e)) |
2223 | 2226 | <pre><code class="python">class PrettyXmlHandler(logging.StreamHandler): |
2224 | 2227 | """A steaming log handler that prettifies log statements containing XML when output is a terminal.""" |
2225 | 2228 | |
2226 | @staticmethod | |
2227 | def parse_bytes(xml_bytes): | |
2229 | def parse_bytes(self, xml_bytes): | |
2228 | 2230 | return to_xml(xml_bytes) |
2229 | 2231 | |
2230 | @classmethod | |
2231 | def prettify_xml(cls, xml_bytes): | |
2232 | def prettify_xml(self, xml_bytes): | |
2232 | 2233 | """Re-format an XML document to a consistent style.""" |
2233 | 2234 | return ( |
2234 | lxml.etree.tostring(cls.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
2235 | lxml.etree.tostring(self.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
2235 | 2236 | .replace(b"\t", b" ") |
2236 | 2237 | .replace(b" xmlns:", b"\n xmlns:") |
2237 | 2238 | ) |
2298 | 2299 | return highlight(xml_str, XmlLexer(), TerminalFormatter()).rstrip()</code></pre> |
2299 | 2300 | </details> |
2300 | 2301 | </dd> |
2301 | <dt id="exchangelib.util.PrettyXmlHandler.parse_bytes"><code class="name flex"> | |
2302 | <span>def <span class="ident">parse_bytes</span></span>(<span>xml_bytes)</span> | |
2303 | </code></dt> | |
2304 | <dd> | |
2305 | <div class="desc"></div> | |
2306 | <details class="source"> | |
2307 | <summary> | |
2308 | <span>Expand source code</span> | |
2309 | </summary> | |
2310 | <pre><code class="python">@staticmethod | |
2311 | def parse_bytes(xml_bytes): | |
2312 | return to_xml(xml_bytes)</code></pre> | |
2313 | </details> | |
2314 | </dd> | |
2315 | <dt id="exchangelib.util.PrettyXmlHandler.prettify_xml"><code class="name flex"> | |
2316 | <span>def <span class="ident">prettify_xml</span></span>(<span>xml_bytes)</span> | |
2317 | </code></dt> | |
2318 | <dd> | |
2319 | <div class="desc"><p>Re-format an XML document to a consistent style.</p></div> | |
2320 | <details class="source"> | |
2321 | <summary> | |
2322 | <span>Expand source code</span> | |
2323 | </summary> | |
2324 | <pre><code class="python">@classmethod | |
2325 | def prettify_xml(cls, xml_bytes): | |
2326 | """Re-format an XML document to a consistent style.""" | |
2327 | return ( | |
2328 | lxml.etree.tostring(cls.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
2329 | .replace(b"\t", b" ") | |
2330 | .replace(b" xmlns:", b"\n xmlns:") | |
2331 | )</code></pre> | |
2332 | </details> | |
2333 | </dd> | |
2334 | 2302 | </dl> |
2335 | 2303 | <h3>Methods</h3> |
2336 | 2304 | <dl> |
2386 | 2354 | return self.stream.isatty() |
2387 | 2355 | except AttributeError: |
2388 | 2356 | return False</code></pre> |
2357 | </details> | |
2358 | </dd> | |
2359 | <dt id="exchangelib.util.PrettyXmlHandler.parse_bytes"><code class="name flex"> | |
2360 | <span>def <span class="ident">parse_bytes</span></span>(<span>self, xml_bytes)</span> | |
2361 | </code></dt> | |
2362 | <dd> | |
2363 | <div class="desc"></div> | |
2364 | <details class="source"> | |
2365 | <summary> | |
2366 | <span>Expand source code</span> | |
2367 | </summary> | |
2368 | <pre><code class="python">def parse_bytes(self, xml_bytes): | |
2369 | return to_xml(xml_bytes)</code></pre> | |
2370 | </details> | |
2371 | </dd> | |
2372 | <dt id="exchangelib.util.PrettyXmlHandler.prettify_xml"><code class="name flex"> | |
2373 | <span>def <span class="ident">prettify_xml</span></span>(<span>self, xml_bytes)</span> | |
2374 | </code></dt> | |
2375 | <dd> | |
2376 | <div class="desc"><p>Re-format an XML document to a consistent style.</p></div> | |
2377 | <details class="source"> | |
2378 | <summary> | |
2379 | <span>Expand source code</span> | |
2380 | </summary> | |
2381 | <pre><code class="python">def prettify_xml(self, xml_bytes): | |
2382 | """Re-format an XML document to a consistent style.""" | |
2383 | return ( | |
2384 | lxml.etree.tostring(self.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
2385 | .replace(b"\t", b" ") | |
2386 | .replace(b" xmlns:", b"\n xmlns:") | |
2387 | )</code></pre> | |
2389 | 2388 | </details> |
2390 | 2389 | </dd> |
2391 | 2390 | </dl> |
23 | 23 | * [Kerberos and SSPI authentication](#kerberos-and-sspi-authentication) |
24 | 24 | * [Certificate Based Authentication (CBA)](#certificate-based-authentication-cba) |
25 | 25 | * [OAuth authentication](#oauth-authentication) |
26 | * [OAuth on Office 365](#oauth-on-office-365) | |
26 | 27 | * [Caching autodiscover results](#caching-autodiscover-results) |
27 | 28 | * [Proxies and custom TLS validation](#proxies-and-custom-tls-validation) |
28 | 29 | * [User-Agent](#user-agent) |
163 | 164 | |
164 | 165 | # Set up a target account and do an autodiscover lookup to find the EWS endpoint |
165 | 166 | account = Account( |
166 | primary_smtp_address='john@example.com', credentials=credentials, | |
167 | primary_smtp_address='john@example.com', credentials=credentials, | |
167 | 168 | autodiscover=True, access_type=DELEGATE |
168 | 169 | ) |
169 | 170 | |
170 | 171 | # If your credentials have been given impersonation access to the target |
171 | 172 | # account, set a different 'access_type': |
172 | 173 | johns_account = Account( |
173 | primary_smtp_address='john@example.com', credentials=credentials, | |
174 | primary_smtp_address='john@example.com', credentials=credentials, | |
174 | 175 | autodiscover=True, access_type=IMPERSONATION |
175 | 176 | ) |
176 | 177 | ``` |
324 | 325 | from oauthlib.oauth2 import OAuth2Token |
325 | 326 | |
326 | 327 | credentials = OAuth2Credentials( |
327 | ..., identity=Identity(primary_smtp_address='svc_acct@example.com') | |
328 | ..., identity=Identity(primary_smtp_address='svc_acct@example.com') | |
328 | 329 | ) |
329 | 330 | credentials = OAuth2AuthorizationCodeCredentials( |
330 | ..., identity=Identity(upn='svc_acct@subdomain.example.com') | |
331 | ..., identity=Identity(upn='svc_acct@subdomain.example.com') | |
331 | 332 | ) |
332 | 333 | |
333 | 334 | credentials = OAuth2AuthorizationCodeCredentials( |
334 | client_id='MY_ID', client_secret='MY_SECRET', authorization_code='AUTH_CODE' | |
335 | client_id='MY_ID', client_secret='MY_SECRET', authorization_code='AUTH_CODE' | |
335 | 336 | ) |
336 | 337 | credentials = OAuth2AuthorizationCodeCredentials( |
337 | 338 | client_id='MY_ID', client_secret='MY_SECRET', |
338 | access_token=OAuth2Token(access_token='EXISTING_TOKEN') | |
339 | access_token=OAuth2Token(access_token='EXISTING_TOKEN') | |
339 | 340 | ) |
340 | 341 | config = Configuration(credentials=credentials, auth_type=OAUTH2) |
341 | 342 | ``` |
363 | 364 | def refresh(self): |
364 | 365 | self.access_token = ... |
365 | 366 | ``` |
367 | ||
368 | ### OAuth on Office 365 | |
369 | Office 365 is deprecating Basic authentication and switching to MFA for end | |
370 | users and OAuth for everything else. Here's one way to set up an app that can | |
371 | access accounts in your organization. First, log into the | |
372 | [https://admin.microsoft.com](Microsoft 365 Administration) page. Find the link | |
373 | to `Azure Active Directory`. Register a new app, and note down the Directory | |
374 | (tenant) ID, Application (client) ID, and the secret: | |
375 | ![App registration](/exchangelib/assets/img/app_registration.png) | |
376 | ||
377 | Continue to the `API permissions` page, and add the `full_access_as_app` | |
378 | permission: | |
379 | ![API permissions](/exchangelib/assets/img/api_permissions.png) | |
380 | ||
381 | Finally, continue to the `Enterprise applications` page, select your app, | |
382 | continue to the `Permissions` page, and check that your app has the | |
383 | `full_access_as_app` permission: | |
384 | ![API permissions](/exchangelib/assets/img/permissions.png) | |
385 | ||
386 | You should now be able to connect to an account using the `OAuth2Credentials` | |
387 | class as shown above. | |
388 | ||
366 | 389 | |
367 | 390 | ### Caching autodiscover results |
368 | 391 | If you're connecting to the same account very often, you can cache the |
386 | 409 | version=version |
387 | 410 | ) |
388 | 411 | account = Account( |
389 | primary_smtp_address=primary_smtp_address, | |
390 | config=config, autodiscover=False, | |
412 | primary_smtp_address=primary_smtp_address, | |
413 | config=config, autodiscover=False, | |
391 | 414 | access_type=DELEGATE, |
392 | 415 | ) |
393 | 416 | ``` |
749 | 772 | m.reply_all(subject='Re: Daily motivation', body='I agree') |
750 | 773 | m.forward( |
751 | 774 | subject='Fwd: Daily motivation', |
752 | body='Hey, look at this!', | |
775 | body='Hey, look at this!', | |
753 | 776 | to_recipients=['carl@example.com', 'denice@example.com'] |
754 | 777 | ) |
755 | 778 | ``` |
993 | 1016 | # Returns items where subject is exactly 'foo'. Case-sensitive |
994 | 1017 | qs.filter(subject='foo') |
995 | 1018 | # Returns items within range |
996 | qs.filter(start__range=(start, end)) | |
1019 | qs.filter(start__range=(start, end)) | |
997 | 1020 | # Return items where subject is either 'foo' or 'bar' |
998 | 1021 | qs.filter(subject__in=('foo', 'bar')) |
999 | 1022 | # Returns items where subject is not 'foo' |
1351 | 1374 | property_id = 0x00008524 |
1352 | 1375 | property_type = 'String' |
1353 | 1376 | ``` |
1354 | ||
1377 | ||
1355 | 1378 | Extended properties also work with folders. For folders, it's only possible to |
1356 | 1379 | register custom fields on all folder types at once. This is because it's |
1357 | 1380 | difficult to provide a consistent API when some folders have custom fields and |
1556 | 1579 | ): |
1557 | 1580 | # Delete or update random occurrences. This will affect |
1558 | 1581 | # 'modified_occurrences' and 'deleted_occurrences' of the master item. |
1559 | if occurrence.start.milliseconds % 2: | |
1582 | if occurrence.start.microsecond % 2: | |
1560 | 1583 | # We receive timestamps as UTC but want to write back as local timezone |
1561 | 1584 | occurrence.start = occurrence.start.astimezone(a.default_timezone) |
1562 | 1585 | occurrence.start += datetime.timedelta(minutes=30) |
1577 | 1600 | third_occurrence.save(update_fields=['start']) |
1578 | 1601 | |
1579 | 1602 | # Similarly, you can reach the master recurrence from the occurrence |
1580 | master = third_occurrence.master_recurrence() | |
1603 | master = third_occurrence.recurring_master() | |
1581 | 1604 | master.subject = 'An update' |
1582 | 1605 | master.save(update_fields=['subject']) |
1583 | 1606 | ``` |
1698 | 1721 | # SyncFolderItems.CHANGE_TYPES |
1699 | 1722 | pass |
1700 | 1723 | # The next time you call a.inbox.sync_items(), you will only get item changes |
1701 | # since the last .sync_items() call. The sync status is stored in | |
1724 | # since the last .sync_items() call. The sync status is stored in | |
1702 | 1725 | # a.inbox.item_sync_state. |
1703 | 1726 | ``` |
1704 | 1727 | |
1954 | 1977 | You can run either the entire test suite or individual tests. |
1955 | 1978 | |
1956 | 1979 | ```bash |
1980 | # Install dependencies | |
1981 | python -m pip install -r test-requirements.txt | |
1982 | ||
1957 | 1983 | # Full test suite |
1958 | 1984 | python -m unittest |
1959 | 1985 | |
1960 | 1986 | # Single test class or test case |
1961 | 1987 | python -m unittest -k test_folder.FolderTest.test_refresh |
1988 | ||
1962 | 1989 | # If you want extreme levels of debug output: |
1963 | 1990 | DEBUG=1 python -m unittest -k test_folder.FolderTest.test_refresh |
1964 | # Tests can be run in parallel if you install the 'unittest-parallel' package | |
1991 | ||
1992 | # Running tests in parallel using the 'unittest-parallel' dependency | |
1965 | 1993 | unittest-parallel -j 4 --class-fixtures |
1966 | 1994 | ``` |
15 | 15 | ForwardItem, |
16 | 16 | Message, |
17 | 17 | PostItem, |
18 | PostReplyItem, | |
18 | 19 | ReplyAllToItem, |
19 | 20 | ReplyToItem, |
20 | 21 | Task, |
27 | 28 | from .transport import BASIC, CBA, DIGEST, GSSAPI, NTLM, OAUTH2, SSPI |
28 | 29 | from .version import Build, Version |
29 | 30 | |
30 | __version__ = "4.7.2" | |
31 | __version__ = "4.7.6" | |
31 | 32 | |
32 | 33 | __all__ = [ |
33 | 34 | "__version__", |
35 | "AcceptItem", | |
34 | 36 | "Account", |
35 | "Identity", | |
36 | "FileAttachment", | |
37 | "ItemAttachment", | |
38 | "discover", | |
37 | "Attendee", | |
38 | "BASIC", | |
39 | "BaseProtocol", | |
40 | "Body", | |
41 | "Build", | |
42 | "CBA", | |
43 | "CalendarItem", | |
44 | "CancelCalendarItem", | |
39 | 45 | "Configuration", |
46 | "Contact", | |
47 | "Credentials", | |
48 | "DEEP", | |
40 | 49 | "DELEGATE", |
41 | "IMPERSONATION", | |
42 | "Credentials", | |
43 | "OAuth2AuthorizationCodeCredentials", | |
44 | "OAuth2Credentials", | |
50 | "DIGEST", | |
51 | "DLMailbox", | |
52 | "DeclineItem", | |
53 | "DistributionList", | |
45 | 54 | "EWSDate", |
46 | 55 | "EWSDateTime", |
47 | 56 | "EWSTimeZone", |
57 | "ExtendedProperty", | |
58 | "FailFast", | |
59 | "FaultTolerance", | |
60 | "FileAttachment", | |
61 | "Folder", | |
62 | "FolderCollection", | |
63 | "ForwardItem", | |
64 | "GSSAPI", | |
65 | "HTMLBody", | |
66 | "IMPERSONATION", | |
67 | "Identity", | |
68 | "ItemAttachment", | |
69 | "ItemId", | |
70 | "Mailbox", | |
71 | "Message", | |
72 | "NTLM", | |
73 | "NoVerifyHTTPAdapter", | |
74 | "OAUTH2", | |
75 | "OAuth2AuthorizationCodeCredentials", | |
76 | "OAuth2Credentials", | |
77 | "OofSettings", | |
78 | "PostItem", | |
79 | "PostReplyItem", | |
80 | "Q", | |
81 | "ReplyAllToItem", | |
82 | "ReplyToItem", | |
83 | "Room", | |
84 | "RoomList", | |
85 | "RootOfHierarchy", | |
86 | "SHALLOW", | |
87 | "SSPI", | |
88 | "TLSClientAuth", | |
89 | "Task", | |
90 | "TentativelyAcceptItem", | |
91 | "UID", | |
48 | 92 | "UTC", |
49 | 93 | "UTC_NOW", |
50 | "ExtendedProperty", | |
51 | "Folder", | |
52 | "RootOfHierarchy", | |
53 | "FolderCollection", | |
54 | "SHALLOW", | |
55 | "DEEP", | |
56 | "AcceptItem", | |
57 | "TentativelyAcceptItem", | |
58 | "DeclineItem", | |
59 | "CalendarItem", | |
60 | "CancelCalendarItem", | |
61 | "Contact", | |
62 | "DistributionList", | |
63 | "Message", | |
64 | "PostItem", | |
65 | "Task", | |
66 | "ForwardItem", | |
67 | "ReplyToItem", | |
68 | "ReplyAllToItem", | |
69 | "ItemId", | |
70 | "Mailbox", | |
71 | "DLMailbox", | |
72 | "Attendee", | |
73 | "Room", | |
74 | "RoomList", | |
75 | "Body", | |
76 | "HTMLBody", | |
77 | "UID", | |
78 | "FailFast", | |
79 | "FaultTolerance", | |
80 | "BaseProtocol", | |
81 | "NoVerifyHTTPAdapter", | |
82 | "TLSClientAuth", | |
83 | "OofSettings", | |
84 | "Q", | |
85 | "BASIC", | |
86 | "DIGEST", | |
87 | "NTLM", | |
88 | "GSSAPI", | |
89 | "SSPI", | |
90 | "OAUTH2", | |
91 | "CBA", | |
92 | "Build", | |
93 | 94 | "Version", |
94 | 95 | "close_connections", |
96 | "discover", | |
95 | 97 | ] |
96 | 98 | |
97 | 99 | # Set a default user agent, e.g. "exchangelib/3.1.1 (python-requests/2.22.0)" |
25 | 25 | |
26 | 26 | log = logging.getLogger(__name__) |
27 | 27 | |
28 | DNS_LOOKUP_ERRORS = ( | |
29 | dns.name.EmptyLabel, | |
30 | dns.resolver.NXDOMAIN, | |
31 | dns.resolver.NoAnswer, | |
32 | dns.resolver.NoNameservers, | |
33 | ) | |
34 | ||
28 | 35 | |
29 | 36 | def discover(email, credentials=None, auth_type=None, retry_policy=None): |
30 | 37 | ad_response, protocol = Autodiscovery(email=email, credentials=credentials).discover() |
80 | 87 | MAX_REDIRECTS = 10 # Maximum number of URL redirects before we give up |
81 | 88 | DNS_RESOLVER_KWARGS = {} |
82 | 89 | DNS_RESOLVER_ATTRS = { |
83 | "timeout": AutodiscoverProtocol.TIMEOUT, | |
90 | "timeout": AutodiscoverProtocol.TIMEOUT / 2.5, # Timeout for query to a single nameserver | |
84 | 91 | } |
92 | DNS_RESOLVER_LIFETIME = AutodiscoverProtocol.TIMEOUT # Total timeout for a query in case of multiple nameservers | |
85 | 93 | |
86 | 94 | def __init__(self, email, credentials=None): |
87 | 95 | """ |
356 | 364 | def _is_valid_hostname(self, hostname): |
357 | 365 | log.debug("Checking if %s can be looked up in DNS", hostname) |
358 | 366 | try: |
359 | self.resolver.resolve(hostname) | |
360 | except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.name.EmptyLabel): | |
367 | self.resolver.resolve(f"{hostname}.", "A", lifetime=self.DNS_RESOLVER_LIFETIME) | |
368 | except DNS_LOOKUP_ERRORS as e: | |
369 | log.debug("DNS A lookup failure: %s", e) | |
361 | 370 | return False |
362 | 371 | return True |
363 | 372 | |
377 | 386 | log.debug("Attempting to get SRV records for %s", hostname) |
378 | 387 | records = [] |
379 | 388 | try: |
380 | answers = self.resolver.resolve(f"{hostname}.", "SRV") | |
381 | except (dns.resolver.NoNameservers, dns.resolver.NoAnswer, dns.resolver.NXDOMAIN) as e: | |
382 | log.debug("DNS lookup failure: %s", e) | |
389 | answers = self.resolver.resolve(f"{hostname}.", "SRV", lifetime=self.DNS_RESOLVER_LIFETIME) | |
390 | except DNS_LOOKUP_ERRORS as e: | |
391 | log.debug("DNS SRV lookup failure: %s", e) | |
383 | 392 | return records |
384 | 393 | for rdata in answers: |
385 | 394 | try: |
60 | 60 | if auth_type is None: |
61 | 61 | # Set a default auth type for the credentials where this makes sense |
62 | 62 | auth_type = DEFAULT_AUTH_TYPE.get(type(credentials)) |
63 | elif credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
63 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
64 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
65 | if credentials is None and auth_type in CREDENTIALS_REQUIRED: | |
64 | 66 | raise ValueError(f"Auth type {auth_type!r} was detected but no credentials were provided") |
65 | 67 | if server and service_endpoint: |
66 | 68 | raise AttributeError("Only one of 'server' or 'service_endpoint' must be provided") |
67 | if auth_type is not None and auth_type not in AUTH_TYPE_MAP: | |
68 | raise InvalidEnumValue("auth_type", auth_type, AUTH_TYPE_MAP) | |
69 | 69 | if not retry_policy: |
70 | 70 | retry_policy = FailFast() |
71 | 71 | if not isinstance(version, (Version, type(None))): |
107 | 107 | the associated auth code grant type for multi-tenant applications. |
108 | 108 | """ |
109 | 109 | |
110 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None): | |
110 | def __init__(self, client_id, client_secret, tenant_id=None, identity=None, access_token=None): | |
111 | 111 | """ |
112 | 112 | |
113 | 113 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
114 | 114 | :param client_secret: Secret associated with the OAuth application |
115 | 115 | :param tenant_id: Microsoft tenant ID of the account to access |
116 | 116 | :param identity: An Identity object representing the account that these credentials are connected to. |
117 | :param access_token: Previously-obtained access token, as a dict or an oauthlib.oauth2.OAuth2Token | |
117 | 118 | """ |
118 | 119 | super().__init__() |
119 | 120 | self.client_id = client_id |
120 | 121 | self.client_secret = client_secret |
121 | 122 | self.tenant_id = tenant_id |
122 | 123 | self.identity = identity |
123 | # When set, access_token is a dict (or an oauthlib.oauth2.OAuth2Token, which is also a dict) | |
124 | self.access_token = None | |
124 | self.access_token = access_token | |
125 | 125 | |
126 | 126 | def refresh(self, session): |
127 | 127 | # Creating a new session gets a new access token, so there's no work here to refresh the credentials. This |
161 | 161 | res.append(getattr(self, k)) |
162 | 162 | return hash(tuple(res)) |
163 | 163 | |
164 | @property | |
165 | def token_url(self): | |
166 | return f"https://login.microsoftonline.com/{self.tenant_id}/oauth2/v2.0/token" | |
167 | ||
168 | @property | |
169 | def scope(self): | |
170 | return ["https://outlook.office365.com/.default"] | |
171 | ||
164 | 172 | def __repr__(self): |
165 | 173 | return self.__class__.__name__ + repr((self.client_id, "********")) |
166 | 174 | |
173 | 181 | several ways: |
174 | 182 | * Given an authorization code, client ID, and client secret, fetch a token ourselves and refresh it as needed if |
175 | 183 | supplied with a refresh token. |
176 | * Given an existing access token, refresh token, client ID, and client secret, use the access token until it | |
177 | expires and then refresh it as needed. | |
184 | * Given an existing access token, client ID, and client secret, use the access token until it expires and then | |
185 | refresh it as needed. | |
178 | 186 | * Given only an existing access token, use it until it expires. This can be used to let the calling application |
179 | 187 | refresh tokens itself by subclassing and implementing refresh(). |
180 | 188 | |
183 | 191 | tenant. |
184 | 192 | """ |
185 | 193 | |
186 | def __init__(self, authorization_code=None, access_token=None, **kwargs): | |
194 | def __init__(self, authorization_code=None, access_token=None, client_id=None, client_secret=None, **kwargs): | |
187 | 195 | """ |
188 | 196 | |
189 | 197 | :param client_id: ID of an authorized OAuth application, required for automatic token fetching and refreshing |
195 | 203 | :param access_token: Previously-obtained access token. If a token exists and the application will handle |
196 | 204 | refreshing by itself (or opts not to handle it), this parameter alone is sufficient. |
197 | 205 | """ |
198 | super().__init__(**kwargs) | |
206 | super().__init__(client_id=client_id, client_secret=client_secret, **kwargs) | |
199 | 207 | self.authorization_code = authorization_code |
200 | 208 | if access_token is not None and not isinstance(access_token, dict): |
201 | 209 | raise InvalidTypeError("access_token", access_token, OAuth2Token) |
202 | 210 | self.access_token = access_token |
211 | ||
212 | @property | |
213 | def token_url(self): | |
214 | # We don't know (or need) the Microsoft tenant ID. Use common/ to let Microsoft select the appropriate | |
215 | # tenant for the provided authorization code or refresh token. | |
216 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
217 | ||
218 | @property | |
219 | def scope(self): | |
220 | res = super().scope | |
221 | res.append("offline_access") | |
222 | return res | |
203 | 223 | |
204 | 224 | def __repr__(self): |
205 | 225 | return self.__class__.__name__ + repr( |
43 | 43 | |
44 | 44 | def __eq__(self, other): |
45 | 45 | return repr(self) == repr(other) |
46 | ||
47 | def __hash__(self): | |
48 | return hash(str(self)) | |
46 | 49 | |
47 | 50 | |
48 | 51 | # Warnings |
119 | 122 | pass |
120 | 123 | |
121 | 124 | |
122 | class TimezoneDefinitionInvalidForYear(EWSError): | |
123 | pass | |
124 | ||
125 | ||
126 | 125 | class SessionPoolMinSizeReached(EWSError): |
127 | 126 | pass |
128 | 127 | |
1416 | 1415 | pass |
1417 | 1416 | |
1418 | 1417 | |
1418 | class ErrorRecoverableItemsAccessDenied(ResponseMessageError): | |
1419 | pass | |
1420 | ||
1421 | ||
1419 | 1422 | class ErrorRecurrenceEndDateTooBig(ResponseMessageError): |
1420 | 1423 | pass |
1421 | 1424 | |
1690 | 1693 | pass |
1691 | 1694 | |
1692 | 1695 | |
1693 | # Microsoft recommends to cache the autodiscover data around 24 hours and perform autodiscover | |
1696 | # Microsoft recommends caching the autodiscover data around 24 hours and perform autodiscover | |
1694 | 1697 | # immediately following certain error responses from EWS. See more at |
1695 | 1698 | # http://blogs.msdn.com/b/mstehle/archive/2010/11/09/ews-best-practices-use-autodiscover.aspx |
1696 | 1699 |
5 | 5 | AdminAuditLogs, |
6 | 6 | AllContacts, |
7 | 7 | AllItems, |
8 | ApplicationData, | |
8 | 9 | ArchiveDeletedItems, |
9 | 10 | ArchiveInbox, |
10 | 11 | ArchiveMsgFolderRoot, |
13 | 14 | ArchiveRecoverableItemsRoot, |
14 | 15 | ArchiveRecoverableItemsVersions, |
15 | 16 | Audits, |
17 | Birthdays, | |
16 | 18 | Calendar, |
17 | 19 | CalendarLogging, |
18 | 20 | CommonViews, |
21 | 23 | Contacts, |
22 | 24 | ConversationHistory, |
23 | 25 | ConversationSettings, |
26 | CrawlerData, | |
24 | 27 | DefaultFoldersChangeHistory, |
25 | 28 | DeferredAction, |
26 | 29 | DeletedItems, |
27 | 30 | Directory, |
31 | DlpPolicyEvaluation, | |
28 | 32 | Drafts, |
29 | 33 | ExchangeSyncData, |
30 | 34 | Favorites, |
31 | 35 | Files, |
36 | FreeBusyCache, | |
32 | 37 | FreebusyData, |
33 | 38 | Friends, |
34 | 39 | GALContacts, |
59 | 64 | RecoverableItemsPurges, |
60 | 65 | RecoverableItemsRoot, |
61 | 66 | RecoverableItemsVersions, |
67 | RecoveryPoints, | |
62 | 68 | Reminders, |
63 | 69 | RSSFeeds, |
64 | 70 | Schedule, |
68 | 74 | Sharing, |
69 | 75 | Shortcuts, |
70 | 76 | Signal, |
77 | SkypeTeamsMessages, | |
71 | 78 | SmsAndChatsSync, |
72 | 79 | SpoolerQueue, |
80 | SwssItems, | |
73 | 81 | SyncIssues, |
74 | 82 | System, |
75 | 83 | Tasks, |
84 | 92 | from .roots import ArchiveRoot, PublicFoldersRoot, Root, RootOfHierarchy |
85 | 93 | |
86 | 94 | __all__ = [ |
87 | "FolderId", | |
88 | "DistinguishedFolderId", | |
89 | "FolderCollection", | |
90 | "BaseFolder", | |
91 | "Folder", | |
92 | 95 | "AdminAuditLogs", |
93 | 96 | "AllContacts", |
94 | 97 | "AllItems", |
98 | "ApplicationData", | |
95 | 99 | "ArchiveDeletedItems", |
96 | 100 | "ArchiveInbox", |
97 | 101 | "ArchiveMsgFolderRoot", |
99 | 103 | "ArchiveRecoverableItemsPurges", |
100 | 104 | "ArchiveRecoverableItemsRoot", |
101 | 105 | "ArchiveRecoverableItemsVersions", |
106 | "ArchiveRoot", | |
102 | 107 | "Audits", |
108 | "BaseFolder", | |
109 | "Birthdays", | |
103 | 110 | "Calendar", |
104 | 111 | "CalendarLogging", |
105 | 112 | "CommonViews", |
113 | "Companies", | |
106 | 114 | "Conflicts", |
107 | 115 | "Contacts", |
108 | 116 | "ConversationHistory", |
109 | 117 | "ConversationSettings", |
118 | "CrawlerData", | |
119 | "DEEP", | |
110 | 120 | "DefaultFoldersChangeHistory", |
111 | 121 | "DeferredAction", |
112 | 122 | "DeletedItems", |
113 | 123 | "Directory", |
124 | "DistinguishedFolderId", | |
125 | "DlpPolicyEvaluation", | |
114 | 126 | "Drafts", |
115 | 127 | "ExchangeSyncData", |
128 | "FOLDER_TRAVERSAL_CHOICES", | |
116 | 129 | "Favorites", |
117 | 130 | "Files", |
131 | "Folder", | |
132 | "FolderCollection", | |
133 | "FolderId", | |
134 | "FolderQuerySet", | |
135 | "FreeBusyCache", | |
118 | 136 | "FreebusyData", |
119 | 137 | "Friends", |
120 | 138 | "GALContacts", |
130 | 148 | "MsgFolderRoot", |
131 | 149 | "MyContacts", |
132 | 150 | "MyContactsExtended", |
151 | "NON_DELETABLE_FOLDERS", | |
133 | 152 | "NonDeletableFolderMixin", |
134 | 153 | "Notes", |
154 | "OrganizationalContacts", | |
135 | 155 | "Outbox", |
136 | 156 | "ParkedMessages", |
137 | 157 | "PassThroughSearchResults", |
138 | 158 | "PdpProfileV2Secured", |
159 | "PeopleCentricConversationBuddies", | |
139 | 160 | "PeopleConnect", |
161 | "PublicFoldersRoot", | |
140 | 162 | "QuickContacts", |
141 | 163 | "RSSFeeds", |
142 | 164 | "RecipientCache", |
144 | 166 | "RecoverableItemsPurges", |
145 | 167 | "RecoverableItemsRoot", |
146 | 168 | "RecoverableItemsVersions", |
169 | "RecoveryPoints", | |
147 | 170 | "Reminders", |
171 | "Root", | |
172 | "RootOfHierarchy", | |
173 | "SHALLOW", | |
174 | "SOFT_DELETED", | |
148 | 175 | "Schedule", |
149 | 176 | "SearchFolders", |
150 | 177 | "SentItems", |
152 | 179 | "Sharing", |
153 | 180 | "Shortcuts", |
154 | 181 | "Signal", |
182 | "SingleFolderQuerySet", | |
183 | "SkypeTeamsMessages", | |
155 | 184 | "SmsAndChatsSync", |
156 | 185 | "SpoolerQueue", |
186 | "SwssItems", | |
157 | 187 | "SyncIssues", |
158 | 188 | "System", |
159 | 189 | "Tasks", |
163 | 193 | "VoiceMail", |
164 | 194 | "WellknownFolder", |
165 | 195 | "WorkingSet", |
166 | "Companies", | |
167 | "OrganizationalContacts", | |
168 | "PeopleCentricConversationBuddies", | |
169 | "NON_DELETABLE_FOLDERS", | |
170 | "FolderQuerySet", | |
171 | "SingleFolderQuerySet", | |
172 | "FOLDER_TRAVERSAL_CHOICES", | |
173 | "SHALLOW", | |
174 | "DEEP", | |
175 | "SOFT_DELETED", | |
176 | "Root", | |
177 | "ArchiveRoot", | |
178 | "PublicFoldersRoot", | |
179 | "RootOfHierarchy", | |
180 | 196 | ] |
9 | 9 | ErrorDeleteDistinguishedFolder, |
10 | 10 | ErrorFolderNotFound, |
11 | 11 | ErrorItemNotFound, |
12 | ErrorRecoverableItemsAccessDenied, | |
12 | 13 | InvalidTypeError, |
13 | 14 | ) |
14 | 15 | from ..fields import ( |
46 | 47 | |
47 | 48 | log = logging.getLogger(__name__) |
48 | 49 | |
50 | DELETE_FOLDER_ERRORS = ( | |
51 | ErrorAccessDenied, | |
52 | ErrorCannotDeleteObject, | |
53 | ErrorCannotEmptyFolder, | |
54 | ErrorItemNotFound, | |
55 | ) | |
56 | ||
49 | 57 | |
50 | 58 | class BaseFolder(RegisterMixIn, SearchableMixIn, metaclass=EWSMeta): |
51 | 59 | """Base class for all classes that implement a folder.""" |
228 | 236 | :return: |
229 | 237 | """ |
230 | 238 | from .known_folders import ( |
239 | ApplicationData, | |
231 | 240 | Calendar, |
232 | 241 | Contacts, |
233 | 242 | ConversationSettings, |
243 | CrawlerData, | |
244 | DlpPolicyEvaluation, | |
245 | FreeBusyCache, | |
234 | 246 | GALContacts, |
235 | 247 | Messages, |
236 | 248 | RecipientCache, |
249 | RecoveryPoints, | |
237 | 250 | Reminders, |
238 | 251 | RSSFeeds, |
252 | Signal, | |
253 | SwssItems, | |
239 | 254 | Tasks, |
240 | 255 | ) |
241 | 256 | |
242 | 257 | for folder_cls in ( |
258 | ApplicationData, | |
259 | Calendar, | |
260 | Contacts, | |
261 | ConversationSettings, | |
262 | CrawlerData, | |
263 | DlpPolicyEvaluation, | |
264 | FreeBusyCache, | |
265 | GALContacts, | |
243 | 266 | Messages, |
267 | RSSFeeds, | |
268 | RecipientCache, | |
269 | RecoveryPoints, | |
270 | Reminders, | |
271 | Signal, | |
272 | SwssItems, | |
244 | 273 | Tasks, |
245 | Calendar, | |
246 | ConversationSettings, | |
247 | Contacts, | |
248 | GALContacts, | |
249 | Reminders, | |
250 | RecipientCache, | |
251 | RSSFeeds, | |
252 | 274 | ): |
253 | 275 | if folder_cls.CONTAINER_CLASS == container_class: |
254 | 276 | return folder_cls |
401 | 423 | def wipe(self, page_size=None, chunk_size=None, _seen=None, _level=0): |
402 | 424 | # Recursively deletes all items in this folder, and all subfolders and their content. Attempts to protect |
403 | 425 | # distinguished folders from being deleted. Use with caution! |
426 | from .known_folders import Audits | |
427 | ||
404 | 428 | _seen = _seen or set() |
405 | 429 | if self.id in _seen: |
406 | 430 | raise RecursionError(f"We already tried to wipe {self}") |
407 | 431 | if _level > 16: |
408 | 432 | raise RecursionError(f"Max recursion level reached: {_level}") |
409 | 433 | _seen.add(self.id) |
434 | if isinstance(self, Audits): | |
435 | # Shortcircuit because this folder can have many items that are all non-deletable | |
436 | log.warning("Cannot wipe audits folder %s", self) | |
437 | return | |
438 | if self.is_distinguished and "recoverableitems" in self.DISTINGUISHED_FOLDER_ID: | |
439 | log.warning("Cannot wipe recoverable items folder %s", self) | |
440 | return | |
410 | 441 | log.warning("Wiping %s", self) |
411 | 442 | has_distinguished_subfolders = any(f.is_distinguished for f in self.children) |
412 | 443 | try: |
414 | 445 | self.empty(delete_sub_folders=False) |
415 | 446 | else: |
416 | 447 | self.empty(delete_sub_folders=True) |
417 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
448 | except ErrorRecoverableItemsAccessDenied: | |
449 | log.warning("Access denied to %s. Skipping", self) | |
450 | return | |
451 | except DELETE_FOLDER_ERRORS: | |
418 | 452 | try: |
419 | 453 | if has_distinguished_subfolders: |
420 | 454 | raise # We already tried this |
421 | 455 | self.empty(delete_sub_folders=False) |
422 | except (ErrorAccessDenied, ErrorCannotEmptyFolder, ErrorItemNotFound): | |
456 | except DELETE_FOLDER_ERRORS: | |
423 | 457 | log.warning("Not allowed to empty %s. Trying to delete items instead", self) |
424 | 458 | kwargs = {} |
425 | 459 | if page_size is not None: |
428 | 462 | kwargs["chunk_size"] = chunk_size |
429 | 463 | try: |
430 | 464 | self.all().delete(**kwargs) |
431 | except (ErrorAccessDenied, ErrorCannotDeleteObject, ErrorItemNotFound): | |
465 | except DELETE_FOLDER_ERRORS: | |
432 | 466 | log.warning("Not allowed to delete items in %s", self) |
433 | 467 | _level += 1 |
434 | 468 | for f in self.children: |
61 | 61 | supported_item_models = (Message, MeetingRequest, MeetingResponse, MeetingCancellation) |
62 | 62 | |
63 | 63 | |
64 | class CrawlerData(Folder): | |
65 | CONTAINER_CLASS = "IPF.StoreItem.CrawlerData" | |
66 | ||
67 | ||
68 | class DlpPolicyEvaluation(Folder): | |
69 | CONTAINER_CLASS = "IPF.StoreItem.DlpPolicyEvaluation" | |
70 | ||
71 | ||
72 | class FreeBusyCache(Folder): | |
73 | CONTAINER_CLASS = "IPF.StoreItem.FreeBusyCache" | |
74 | ||
75 | ||
76 | class RecoveryPoints(Folder): | |
77 | CONTAINER_CLASS = "IPF.StoreItem.RecoveryPoints" | |
78 | ||
79 | ||
80 | class SwssItems(Folder): | |
81 | CONTAINER_CLASS = "IPF.StoreItem.SwssItems" | |
82 | ||
83 | ||
84 | class SkypeTeamsMessages(Folder): | |
85 | CONTAINER_CLASS = "IPF.SkypeTeams.Message" | |
86 | LOCALIZED_NAMES = { | |
87 | None: ("Team-chat",), | |
88 | } | |
89 | ||
90 | ||
91 | class Birthdays(Folder): | |
92 | CONTAINER_CLASS = "IPF.Appointment.Birthday" | |
93 | LOCALIZED_NAMES = { | |
94 | None: ("Birthdays",), | |
95 | "da_DK": ("Fødselsdage",), | |
96 | } | |
97 | ||
98 | ||
64 | 99 | class Drafts(Messages): |
65 | 100 | DISTINGUISHED_FOLDER_ID = "drafts" |
66 | 101 | |
101 | 136 | "de_DE": ("Postausgang",), |
102 | 137 | "en_US": ("Outbox",), |
103 | 138 | "es_ES": ("Bandeja de salida",), |
104 | "fr_CA": (u"Boîte d'envoi",), | |
139 | "fr_CA": ("Boîte d'envoi",), | |
105 | 140 | "nl_NL": ("Postvak UIT",), |
106 | 141 | "ru_RU": ("Исходящие",), |
107 | 142 | "sv_SE": ("Utkorgen",), |
266 | 301 | |
267 | 302 | DISTINGUISHED_FOLDER_ID = "msgfolderroot" |
268 | 303 | LOCALIZED_NAMES = { |
304 | None: ("Top of Information Store",), | |
305 | "da_DK": ("Informationslagerets øverste niveau",), | |
269 | 306 | "zh_CN": ("信息存储顶部",), |
270 | 307 | } |
271 | 308 | |
380 | 417 | } |
381 | 418 | |
382 | 419 | |
420 | class ApplicationData(NonDeletableFolderMixin, Folder): | |
421 | CONTAINER_CLASS = "IPM.ApplicationData" | |
422 | ||
423 | ||
383 | 424 | class Audits(NonDeletableFolderMixin, Folder): |
384 | 425 | LOCALIZED_NAMES = { |
385 | 426 | None: ("Audits",), |
405 | 446 | CONTAINTER_CLASS = "IPF.Contact.Company" |
406 | 447 | LOCALIZED_NAMES = { |
407 | 448 | None: ("Companies",), |
449 | "da_DK": ("Firmaer",), | |
408 | 450 | } |
409 | 451 | |
410 | 452 | |
618 | 660 | NON_DELETABLE_FOLDERS = [ |
619 | 661 | AllContacts, |
620 | 662 | AllItems, |
663 | ApplicationData, | |
621 | 664 | Audits, |
622 | 665 | CalendarLogging, |
623 | 666 | CommonViews, |
698 | 741 | ArchiveRecoverableItemsRoot, |
699 | 742 | ArchiveRecoverableItemsVersions, |
700 | 743 | ] |
744 | ||
745 | MISC_FOLDERS = [ | |
746 | CrawlerData, | |
747 | DlpPolicyEvaluation, | |
748 | FreeBusyCache, | |
749 | RecoveryPoints, | |
750 | SwssItems, | |
751 | SkypeTeamsMessages, | |
752 | Birthdays, | |
753 | ] |
7 | 7 | from .base import BaseFolder |
8 | 8 | from .collections import FolderCollection |
9 | 9 | from .known_folders import ( |
10 | MISC_FOLDERS, | |
10 | 11 | NON_DELETABLE_FOLDERS, |
11 | 12 | WELLKNOWN_FOLDERS_IN_ARCHIVE_ROOT, |
12 | 13 | WELLKNOWN_FOLDERS_IN_ROOT, |
204 | 205 | :param folder_name: |
205 | 206 | :param locale: a string, e.g. 'da_DK' |
206 | 207 | """ |
207 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS: | |
208 | for folder_cls in cls.WELLKNOWN_FOLDERS + NON_DELETABLE_FOLDERS + MISC_FOLDERS: | |
208 | 209 | if folder_name.lower() in folder_cls.localized_names(locale): |
209 | 210 | return folder_cls |
210 | 211 | raise KeyError() |
409 | 409 | |
410 | 410 | @require_account |
411 | 411 | def send(self, message_disposition=SEND_AND_SAVE_COPY): |
412 | # Some responses contain multiple response IDs, e.g. MeetingRequest.accept(). Return either the single ID or | |
413 | # the list of IDs. | |
414 | 412 | from ..services import CreateItem |
415 | 413 | |
416 | return CreateItem(account=self.account).get( | |
417 | items=[self], | |
418 | folder=self.folder, | |
419 | message_disposition=message_disposition, | |
420 | send_meeting_invitations=SEND_TO_NONE, | |
414 | res = list( | |
415 | CreateItem(account=self.account).call( | |
416 | items=[self], | |
417 | folder=self.folder, | |
418 | message_disposition=message_disposition, | |
419 | send_meeting_invitations=SEND_TO_NONE, | |
420 | ) | |
421 | 421 | ) |
422 | for r in res: | |
423 | if isinstance(r, Exception): | |
424 | raise r | |
425 | # CreateItem may return multiple item IDs when given a meeting reply item. See issue#886. In lack of a better | |
426 | # idea, return either the single ID or the list of IDs here. | |
427 | if len(res) == 1: | |
428 | return res[0] | |
429 | return res | |
422 | 430 | |
423 | 431 | |
424 | 432 | class AcceptItem(BaseMeetingReplyItem): |
36 | 36 | conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) |
37 | 37 | # Rename 'From' to 'author'. We can't use fieldname 'from' since it's a Python keyword. |
38 | 38 | author = MailboxField(field_uri="message:From", is_read_only_after_send=True) |
39 | message_id = CharField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
39 | message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) | |
40 | 40 | is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) |
41 | 41 | is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) |
42 | 42 | references = TextField(field_uri="message:References") |
168 | 168 | from ..services import MarkAsJunk |
169 | 169 | |
170 | 170 | res = MarkAsJunk(account=self.account).get( |
171 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=move_item | |
171 | items=[self], is_junk=is_junk, move_item=move_item, expect_result=None | |
172 | 172 | ) |
173 | 173 | if res is None: |
174 | 174 | return |
6 | 6 | from inspect import getmro |
7 | 7 | from threading import Lock |
8 | 8 | |
9 | from .errors import InvalidTypeError, TimezoneDefinitionInvalidForYear | |
9 | from .errors import InvalidTypeError | |
10 | 10 | from .fields import ( |
11 | 11 | WEEKDAY_NAMES, |
12 | 12 | AssociatedCalendarItemIdField, |
218 | 218 | # Folder class, making the custom field available for subclasses). |
219 | 219 | if local_fields: |
220 | 220 | kwargs["FIELDS"] = fields |
221 | cls = super().__new__(mcs, name, bases, kwargs) | |
222 | cls._slots_keys = mcs._get_slots_keys(cls) | |
223 | return cls | |
221 | klass = super().__new__(mcs, name, bases, kwargs) | |
222 | klass._slots_keys = mcs._get_slots_keys(klass) | |
223 | return klass | |
224 | 224 | |
225 | 225 | @staticmethod |
226 | def _get_slots_keys(cls): | |
226 | def _get_slots_keys(klass): | |
227 | 227 | seen = set() |
228 | 228 | keys = [] |
229 | for c in reversed(getmro(cls)): | |
229 | for c in reversed(getmro(klass)): | |
230 | 230 | if not hasattr(c, "__slots__"): |
231 | 231 | continue |
232 | 232 | for k in c.__slots__: |
579 | 579 | def id_from_xml(cls, elem): |
580 | 580 | item = cls.from_xml(elem=elem, account=None) |
581 | 581 | return item.id, item.changekey |
582 | ||
583 | ||
584 | class OldItemId(ItemId): | |
585 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldfolderid""" | |
586 | ||
587 | ELEMENT_NAME = "OldItemId" | |
588 | ||
589 | ||
590 | class OldFolderId(FolderId): | |
591 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/olditemid""" | |
592 | ||
593 | ELEMENT_NAME = "OldFolderId" | |
594 | ||
595 | ||
596 | class OldParentFolderId(ParentFolderId): | |
597 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/oldparentfolderid""" | |
598 | ||
599 | ELEMENT_NAME = "OldParentFolderId" | |
582 | 600 | |
583 | 601 | |
584 | 602 | class Mailbox(EWSElement): |
1408 | 1426 | """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/responseobjects""" |
1409 | 1427 | |
1410 | 1428 | ELEMENT_NAME = "ResponseObjects" |
1411 | NAMESPACE = EWSElement.NAMESPACE | |
1412 | ||
1413 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=NAMESPACE) | |
1429 | ||
1430 | accept_item = EWSElementField(field_uri="AcceptItem", value_cls="AcceptItem", namespace=TNS) | |
1414 | 1431 | tentatively_accept_item = EWSElementField( |
1415 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=NAMESPACE | |
1416 | ) | |
1417 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=NAMESPACE) | |
1418 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=NAMESPACE) | |
1419 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=NAMESPACE) | |
1420 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=NAMESPACE) | |
1432 | field_uri="TentativelyAcceptItem", value_cls="TentativelyAcceptItem", namespace=TNS | |
1433 | ) | |
1434 | decline_item = EWSElementField(field_uri="DeclineItem", value_cls="DeclineItem", namespace=TNS) | |
1435 | reply_to_item = EWSElementField(field_uri="ReplyToItem", value_cls="ReplyToItem", namespace=TNS) | |
1436 | forward_item = EWSElementField(field_uri="ForwardItem", value_cls="ForwardItem", namespace=TNS) | |
1437 | reply_all_to_item = EWSElementField(field_uri="ReplyAllToItem", value_cls="ReplyAllToItem", namespace=TNS) | |
1421 | 1438 | cancel_calendar_item = EWSElementField( |
1422 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=NAMESPACE | |
1439 | field_uri="CancelCalendarItem", value_cls="CancelCalendarItem", namespace=TNS | |
1423 | 1440 | ) |
1424 | 1441 | remove_item = EWSElementField(field_uri="RemoveItem", value_cls=RemoveItem) |
1425 | post_reply_item = EWSElementField( | |
1426 | field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=EWSElement.NAMESPACE | |
1427 | ) | |
1442 | post_reply_item = EWSElementField(field_uri="PostReplyItem", value_cls="PostReplyItem", namespace=TNS) | |
1428 | 1443 | success_read_receipt = EWSElementField(field_uri="SuppressReadReceipt", value_cls=SuppressReadReceipt) |
1429 | 1444 | accept_sharing_invitation = EWSElementField(field_uri="AcceptSharingInvitation", value_cls=AcceptSharingInvitation) |
1430 | 1445 | |
1704 | 1719 | ITEM = "item" |
1705 | 1720 | |
1706 | 1721 | timestamp = DateTimeField(field_uri="TimeStamp") |
1707 | item_id = EWSElementField(field_uri="ItemId", value_cls=ItemId) | |
1708 | folder_id = EWSElementField(field_uri="FolderId", value_cls=FolderId) | |
1709 | parent_folder_id = EWSElementField(field_uri="ParentFolderId", value_cls=ParentFolderId) | |
1722 | item_id = EWSElementField(value_cls=ItemId) | |
1723 | folder_id = EWSElementField(value_cls=FolderId) | |
1724 | parent_folder_id = EWSElementField(value_cls=ParentFolderId) | |
1710 | 1725 | |
1711 | 1726 | @property |
1712 | 1727 | def event_type(self): |
1720 | 1735 | class OldTimestampEvent(TimestampEvent, metaclass=EWSMeta): |
1721 | 1736 | """Base class for both item and folder copy/move events.""" |
1722 | 1737 | |
1723 | old_item_id = EWSElementField(field_uri="OldItemId", value_cls=ItemId) | |
1724 | old_folder_id = EWSElementField(field_uri="OldFolderId", value_cls=FolderId) | |
1725 | old_parent_folder_id = EWSElementField(field_uri="OldParentFolderId", value_cls=ParentFolderId) | |
1738 | old_item_id = EWSElementField(value_cls=OldItemId) | |
1739 | old_folder_id = EWSElementField(value_cls=OldFolderId) | |
1740 | old_parent_folder_id = EWSElementField(value_cls=OldParentFolderId) | |
1726 | 1741 | |
1727 | 1742 | |
1728 | 1743 | class CopiedEvent(OldTimestampEvent): |
1863 | 1878 | name = CharField(field_uri="Name", is_attribute=True) |
1864 | 1879 | bias = TimeDeltaField(field_uri="Bias", is_attribute=True) |
1865 | 1880 | |
1866 | def _split_id(self): | |
1867 | to_year, to_type = self.id.rsplit("/", 1)[1].split("-") | |
1868 | return int(to_year), to_type | |
1869 | ||
1870 | @property | |
1871 | def year(self): | |
1872 | return self._split_id()[0] | |
1873 | ||
1874 | @property | |
1875 | def type(self): | |
1876 | return self._split_id()[1] | |
1877 | ||
1878 | 1881 | @property |
1879 | 1882 | def bias_in_minutes(self): |
1880 | 1883 | return int(self.bias.total_seconds()) // 60 # Convert to minutes |
1905 | 1908 | def from_xml(cls, elem, account): |
1906 | 1909 | return super().from_xml(elem, account) |
1907 | 1910 | |
1908 | def _get_standard_period(self, for_year): | |
1909 | # Look through periods and pick a relevant period according to the 'for_year' value | |
1910 | valid_period = None | |
1911 | for period in sorted(self.periods, key=lambda p: (p.year, p.type)): | |
1912 | if period.year > for_year: | |
1913 | break | |
1914 | if period.type != "Standard": | |
1911 | def _get_standard_period(self, transitions_group): | |
1912 | # Find the first standard period referenced from transitions_group | |
1913 | standard_periods_map = {p.id: p for p in self.periods if p.name == "Standard"} | |
1914 | for transition in transitions_group.transitions: | |
1915 | try: | |
1916 | return standard_periods_map[transition.to] | |
1917 | except KeyError: | |
1915 | 1918 | continue |
1916 | valid_period = period | |
1917 | if valid_period is None: | |
1918 | raise TimezoneDefinitionInvalidForYear(f"Year {for_year} not included in periods {self.periods}") | |
1919 | return valid_period | |
1919 | raise ValueError(f"No standard period matching any transition in {transitions_group}") | |
1920 | 1920 | |
1921 | 1921 | def _get_transitions_group(self, for_year): |
1922 | 1922 | # Look through the transitions, and pick the relevant transition group according to the 'for_year' value |
1938 | 1938 | if not 0 <= len(transitions_group.transitions) <= 2: |
1939 | 1939 | raise ValueError(f"Expected 0-2 transitions in transitions group {transitions_group}") |
1940 | 1940 | |
1941 | standard_period = self._get_standard_period(for_year) | |
1941 | standard_period = self._get_standard_period(transitions_group) | |
1942 | 1942 | periods_map = {p.id: p for p in self.periods} |
1943 | 1943 | standard_time, daylight_time = None, None |
1944 | 1944 | if len(transitions_group.transitions) == 1: |
244 | 244 | session = self.renew_session(session) |
245 | 245 | self._session_pool.put(session, block=False) |
246 | 246 | |
247 | @staticmethod | |
248 | def close_session(session): | |
247 | def close_session(self, session): | |
248 | if isinstance(self.credentials, OAuth2Credentials) and not isinstance( | |
249 | self.credentials, OAuth2AuthorizationCodeCredentials | |
250 | ): | |
251 | # Reset token if client is of type BackendApplicationClient | |
252 | self.credentials.access_token = None | |
249 | 253 | session.close() |
250 | 254 | del session |
251 | 255 | |
308 | 312 | return session |
309 | 313 | |
310 | 314 | def create_oauth2_session(self): |
311 | has_token = False | |
312 | scope = ["https://outlook.office365.com/.default"] | |
313 | session_params = {} | |
315 | session_params = {"token": self.credentials.access_token} # Token may be None | |
314 | 316 | token_params = {} |
315 | 317 | |
316 | 318 | if isinstance(self.credentials, OAuth2AuthorizationCodeCredentials): |
317 | # Ask for a refresh token | |
318 | scope.append("offline_access") | |
319 | ||
320 | # We don't know (or need) the Microsoft tenant ID. Use | |
321 | # common/ to let Microsoft select the appropriate tenant | |
322 | # for the provided authorization code or refresh token. | |
323 | # | |
324 | # Suppress looks-like-password warning from Bandit. | |
325 | token_url = "https://login.microsoftonline.com/common/oauth2/v2.0/token" # nosec | |
326 | ||
327 | client_params = {} | |
328 | has_token = self.credentials.access_token is not None | |
329 | if has_token: | |
330 | session_params["token"] = self.credentials.access_token | |
331 | elif self.credentials.authorization_code is not None: | |
332 | token_params["code"] = self.credentials.authorization_code | |
333 | self.credentials.authorization_code = None | |
334 | ||
335 | if self.credentials.client_id is not None and self.credentials.client_secret is not None: | |
336 | # If we're given a client ID and secret, we have enough | |
337 | # to refresh access tokens ourselves. In other cases the | |
338 | # session will raise TokenExpiredError and we'll need to | |
339 | # ask the calling application to refresh the token (that | |
340 | # covers cases where the caller doesn't have access to | |
341 | # the client secret but is working with a service that | |
342 | # can provide it refreshed tokens on a limited basis). | |
319 | token_params["code"] = self.credentials.authorization_code # Auth code may be None | |
320 | self.credentials.authorization_code = None # We can only use the code once | |
321 | ||
322 | if self.credentials.client_id and self.credentials.client_secret: | |
323 | # If we're given a client ID and secret, we have enough to refresh access tokens ourselves. In other | |
324 | # cases the session will raise TokenExpiredError, and we'll need to ask the calling application to | |
325 | # refresh the token (that covers cases where the caller doesn't have access to the client secret but | |
326 | # is working with a service that can provide it refreshed tokens on a limited basis). | |
343 | 327 | session_params.update( |
344 | 328 | { |
345 | 329 | "auto_refresh_kwargs": { |
346 | 330 | "client_id": self.credentials.client_id, |
347 | 331 | "client_secret": self.credentials.client_secret, |
348 | 332 | }, |
349 | "auto_refresh_url": token_url, | |
333 | "auto_refresh_url": self.credentials.token_url, | |
350 | 334 | "token_updater": self.credentials.on_token_auto_refreshed, |
351 | 335 | } |
352 | 336 | ) |
353 | client = WebApplicationClient(self.credentials.client_id, **client_params) | |
337 | client = WebApplicationClient(client_id=self.credentials.client_id) | |
354 | 338 | else: |
355 | token_url = f"https://login.microsoftonline.com/{self.credentials.tenant_id}/oauth2/v2.0/token" | |
356 | 339 | client = BackendApplicationClient(client_id=self.credentials.client_id) |
357 | 340 | |
358 | 341 | session = self.raw_session(self.service_endpoint, oauth2_client=client, oauth2_session_params=session_params) |
359 | if not has_token: | |
342 | if not session.token: | |
360 | 343 | # Fetch the token explicitly -- it doesn't occur implicitly |
361 | 344 | token = session.fetch_token( |
362 | token_url=token_url, | |
345 | token_url=self.credentials.token_url, | |
363 | 346 | client_id=self.credentials.client_id, |
364 | 347 | client_secret=self.credentials.client_secret, |
365 | scope=scope, | |
348 | scope=self.credentials.scope, | |
366 | 349 | timeout=self.TIMEOUT, |
367 | 350 | **token_params, |
368 | 351 | ) |
369 | # Allow the credentials object to update its copy of the new | |
370 | # token, and give the application an opportunity to cache it | |
352 | # Allow the credentials object to update its copy of the new token, and give the application an opportunity | |
353 | # to cache it. | |
371 | 354 | self.credentials.on_token_auto_refreshed(token) |
372 | 355 | session.auth = get_auth_instance(auth_type=OAUTH2, client=client) |
373 | 356 | |
522 | 505 | |
523 | 506 | tz_definition = list(self.get_timezones(timezones=[start.tzinfo], return_full_timezone_data=True))[0] |
524 | 507 | return GetUserAvailability(self).call( |
525 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
526 | 508 | mailbox_data=[ |
527 | 509 | MailboxData( |
528 | 510 | email=account.primary_smtp_address if isinstance(account, Account) else account, |
531 | 513 | ) |
532 | 514 | for account, attendee_type, exclude_conflicts in accounts |
533 | 515 | ], |
516 | timezone=TimeZone.from_server_timezone(tz_definition=tz_definition, for_year=start.year), | |
534 | 517 | free_busy_view_options=FreeBusyViewOptions( |
535 | 518 | time_window=TimeWindow(start=start, end=end), |
536 | 519 | merged_free_busy_interval=merged_free_busy_interval, |
0 | 0 | import abc |
1 | 1 | import logging |
2 | import traceback | |
3 | 2 | from itertools import chain |
4 | 3 | |
5 | 4 | from .. import errors |
6 | 5 | from ..attachments import AttachmentId |
7 | 6 | from ..credentials import IMPERSONATION, OAuth2Credentials |
8 | 7 | from ..errors import ( |
9 | ErrorAccessDenied, | |
10 | ErrorADUnavailable, | |
11 | 8 | ErrorBatchProcessingStopped, |
12 | 9 | ErrorCannotDeleteObject, |
13 | 10 | ErrorCannotDeleteTaskOccurrence, |
14 | ErrorCannotEmptyFolder, | |
15 | ErrorConnectionFailed, | |
16 | ErrorConnectionFailedTransientError, | |
17 | 11 | ErrorCorruptData, |
18 | ErrorCreateItemAccessDenied, | |
19 | ErrorDelegateNoUser, | |
20 | ErrorDeleteDistinguishedFolder, | |
21 | 12 | ErrorExceededConnectionCount, |
22 | ErrorFolderNotFound, | |
23 | ErrorImpersonateUserDenied, | |
24 | ErrorImpersonationFailed, | |
25 | 13 | ErrorIncorrectSchemaVersion, |
26 | ErrorInternalServerError, | |
27 | ErrorInternalServerTransientError, | |
28 | 14 | ErrorInvalidChangeKey, |
29 | 15 | ErrorInvalidIdMalformed, |
30 | ErrorInvalidLicense, | |
31 | 16 | ErrorInvalidRequest, |
32 | 17 | ErrorInvalidSchemaVersionForMailboxVersion, |
33 | 18 | ErrorInvalidServerVersion, |
34 | ErrorInvalidSubscription, | |
35 | ErrorInvalidSyncStateData, | |
36 | ErrorInvalidWatermark, | |
37 | 19 | ErrorItemCorrupt, |
38 | 20 | ErrorItemNotFound, |
39 | 21 | ErrorItemSave, |
40 | ErrorMailboxMoveInProgress, | |
41 | ErrorMailboxStoreUnavailable, | |
22 | ErrorMailRecipientNotFound, | |
42 | 23 | ErrorMessageSizeExceeded, |
43 | 24 | ErrorMimeContentConversionFailed, |
44 | ErrorNameResolutionMultipleResults, | |
45 | ErrorNameResolutionNoResults, | |
46 | ErrorNonExistentMailbox, | |
47 | ErrorNoPublicFolderReplicaAvailable, | |
48 | ErrorNoRespondingCASInDestinationSite, | |
49 | ErrorNotDelegate, | |
50 | ErrorQuotaExceeded, | |
51 | 25 | ErrorRecurrenceHasNoOccurrence, |
52 | 26 | ErrorServerBusy, |
53 | 27 | ErrorTimeoutExpired, |
55 | 29 | EWSWarning, |
56 | 30 | InvalidTypeError, |
57 | 31 | MalformedResponseError, |
58 | RateLimitError, | |
59 | 32 | SessionPoolMinSizeReached, |
60 | 33 | SOAPError, |
61 | 34 | TransportError, |
62 | UnauthorizedError, | |
63 | 35 | ) |
64 | 36 | from ..folders import BaseFolder, Folder, RootOfHierarchy |
65 | 37 | from ..items import BaseItem |
97 | 69 | PAGE_SIZE = 100 # A default page size for all paging services. This is the number of items we request per page |
98 | 70 | CHUNK_SIZE = 100 # A default chunk size for all services. This is the number of items we send in a single request |
99 | 71 | |
100 | KNOWN_EXCEPTIONS = ( | |
101 | ErrorAccessDenied, | |
102 | ErrorADUnavailable, | |
103 | ErrorBatchProcessingStopped, | |
104 | ErrorCannotDeleteObject, | |
105 | ErrorCannotEmptyFolder, | |
106 | ErrorConnectionFailed, | |
107 | ErrorConnectionFailedTransientError, | |
108 | ErrorCreateItemAccessDenied, | |
109 | ErrorDelegateNoUser, | |
110 | ErrorDeleteDistinguishedFolder, | |
111 | ErrorExceededConnectionCount, | |
112 | ErrorFolderNotFound, | |
113 | ErrorImpersonateUserDenied, | |
114 | ErrorImpersonationFailed, | |
115 | ErrorInternalServerError, | |
116 | ErrorInternalServerTransientError, | |
117 | ErrorInvalidChangeKey, | |
118 | ErrorInvalidLicense, | |
119 | ErrorInvalidSubscription, | |
120 | ErrorInvalidSyncStateData, | |
121 | ErrorInvalidWatermark, | |
122 | ErrorItemCorrupt, | |
123 | ErrorItemNotFound, | |
124 | ErrorMailboxMoveInProgress, | |
125 | ErrorMailboxStoreUnavailable, | |
126 | ErrorNameResolutionMultipleResults, | |
127 | ErrorNameResolutionNoResults, | |
128 | ErrorNonExistentMailbox, | |
129 | ErrorNoPublicFolderReplicaAvailable, | |
130 | ErrorNoRespondingCASInDestinationSite, | |
131 | ErrorNotDelegate, | |
132 | ErrorQuotaExceeded, | |
133 | ErrorTimeoutExpired, | |
134 | RateLimitError, | |
135 | UnauthorizedError, | |
136 | ) | |
137 | ||
138 | 72 | |
139 | 73 | class EWSService(metaclass=abc.ABCMeta): |
140 | 74 | """Base class for all EWS services.""" |
157 | 91 | ErrorRecurrenceHasNoOccurrence, |
158 | 92 | ErrorCorruptData, |
159 | 93 | ErrorItemCorrupt, |
94 | ErrorMailRecipientNotFound, | |
160 | 95 | ) |
161 | 96 | # Similarly, define the warnings we want to return unraised |
162 | 97 | WARNINGS_TO_CATCH_IN_RESPONSE = ErrorBatchProcessingStopped |
331 | 266 | except ErrorServerBusy as e: |
332 | 267 | self._handle_backoff(e) |
333 | 268 | continue |
334 | except KNOWN_EXCEPTIONS: | |
335 | # These are known and understood, and don't require a backtrace. | |
336 | raise | |
337 | 269 | except (ErrorTooManyObjectsOpened, ErrorTimeoutExpired) as e: |
338 | 270 | # ErrorTooManyObjectsOpened means there are too many connections to the Exchange database. This is very |
339 | 271 | # often a symptom of sending too many requests. |
348 | 280 | |
349 | 281 | # Re-raise as an ErrorServerBusy with a default delay of 5 minutes |
350 | 282 | raise ErrorServerBusy(f"Reraised from {e.__class__.__name__}({e})") |
351 | except Exception: | |
352 | # This may run in a thread, which obfuscates the stack trace. Print trace immediately. | |
353 | account = self.account if isinstance(self, EWSAccountService) else None | |
354 | log.warning("Account %s: Exception in _get_elements: %s", account, traceback.format_exc(20)) | |
355 | raise | |
356 | 283 | finally: |
357 | 284 | if self.streaming: |
358 | 285 | self.stop_streaming() |
780 | 707 | def _account_to_impersonate(self): |
781 | 708 | if self.account.access_type == IMPERSONATION: |
782 | 709 | return self.account.identity |
783 | return None | |
710 | return super()._account_to_impersonate | |
784 | 711 | |
785 | 712 | @property |
786 | 713 | def _timezone(self): |
10 | 10 | |
11 | 11 | SERVICE_NAME = "GetUserAvailability" |
12 | 12 | |
13 | def call(self, timezone, mailbox_data, free_busy_view_options): | |
13 | def call(self, mailbox_data, timezone, free_busy_view_options): | |
14 | 14 | # TODO: Also supports SuggestionsViewOptions, see |
15 | 15 | # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/suggestionsviewoptions |
16 | 16 | return self._elems_to_objs( |
17 | self._get_elements( | |
18 | payload=self.get_payload( | |
19 | timezone=timezone, mailbox_data=mailbox_data, free_busy_view_options=free_busy_view_options | |
20 | ) | |
17 | self._chunked_get_elements( | |
18 | self.get_payload, | |
19 | items=mailbox_data, | |
20 | timezone=timezone, | |
21 | free_busy_view_options=free_busy_view_options, | |
21 | 22 | ) |
22 | 23 | ) |
23 | 24 | |
24 | 25 | def _elem_to_obj(self, elem): |
25 | 26 | return FreeBusyView.from_xml(elem=elem, account=None) |
26 | 27 | |
27 | def get_payload(self, timezone, mailbox_data, free_busy_view_options): | |
28 | def get_payload(self, mailbox_data, timezone, free_busy_view_options): | |
28 | 29 | payload = create_element(f"m:{self.SERVICE_NAME}Request") |
29 | 30 | set_xml_value(payload, timezone, version=self.protocol.version) |
30 | 31 | mailbox_data_array = create_element("m:MailboxDataArray") |
42 | 43 | |
43 | 44 | def _get_elements_in_response(self, response): |
44 | 45 | for msg in response: |
45 | # Just check the response code and raise errors | |
46 | self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
47 | yield from self._get_elements_in_container(container=msg) | |
46 | container_or_exc = self._get_element_container(message=msg.find(f"{{{MNS}}}ResponseMessage")) | |
47 | if isinstance(container_or_exc, Exception): | |
48 | yield container_or_exc | |
49 | else: | |
50 | yield from self._get_elements_in_container(container=msg) | |
48 | 51 | |
49 | 52 | @classmethod |
50 | 53 | def _get_elements_in_container(cls, container): |
0 | 0 | import logging |
1 | import warnings | |
1 | 2 | |
2 | 3 | from ..errors import ErrorNameResolutionMultipleResults, ErrorNameResolutionNoResults, InvalidEnumValue |
3 | 4 | from ..items import SEARCH_SCOPE_CHOICES, SHAPE_CHOICES, Contact |
17 | 18 | ERRORS_TO_CATCH_IN_RESPONSE = ErrorNameResolutionNoResults |
18 | 19 | WARNINGS_TO_IGNORE_IN_RESPONSE = ErrorNameResolutionMultipleResults |
19 | 20 | # Note: paging information is returned as attrs on the 'ResolutionSet' element, but this service does not |
20 | # support the 'IndexedPageItemView' element, so it's not really a paging service. According to docs, at most | |
21 | # 100 candidates are returned for a lookup. | |
21 | # support the 'IndexedPageItemView' element, so it's not really a paging service. | |
22 | 22 | supports_paging = False |
23 | # According to the 'Remarks' section of the MSDN documentation referenced above, at most 100 candidates are | |
24 | # returned for a lookup. | |
25 | candidates_limit = 100 | |
23 | 26 | |
24 | 27 | def __init__(self, *args, **kwargs): |
25 | 28 | super().__init__(*args, **kwargs) |
54 | 57 | ) |
55 | 58 | ) |
56 | 59 | |
60 | def _get_element_container(self, message, name=None): | |
61 | container_or_exc = super()._get_element_container(message=message, name=name) | |
62 | if isinstance(container_or_exc, Exception): | |
63 | return container_or_exc | |
64 | is_last_page = container_or_exc.get("IncludesLastItemInRange").lower() in ("true", "0") | |
65 | log.debug("Includes last item in range: %s", is_last_page) | |
66 | if not is_last_page: | |
67 | warnings.warn( | |
68 | f"The {self.__class__.__name__} service returns at most {self.candidates_limit} candidates and does " | |
69 | f"not support paging. You have reached this limit and have not received the exhaustive list of " | |
70 | f"candidates." | |
71 | ) | |
72 | return container_or_exc | |
73 | ||
57 | 74 | def _elem_to_obj(self, elem): |
58 | 75 | if self.return_full_contact_data: |
59 | 76 | mailbox_elem = elem.find(Mailbox.response_tag()) |
21 | 21 | from pygments import highlight |
22 | 22 | from pygments.formatters.terminal import TerminalFormatter |
23 | 23 | from pygments.lexers.html import XmlLexer |
24 | from requests_oauthlib import OAuth2Session | |
24 | 25 | |
25 | 26 | from .errors import ( |
26 | 27 | InvalidTypeError, |
572 | 573 | class PrettyXmlHandler(logging.StreamHandler): |
573 | 574 | """A steaming log handler that prettifies log statements containing XML when output is a terminal.""" |
574 | 575 | |
575 | @staticmethod | |
576 | def parse_bytes(xml_bytes): | |
576 | def parse_bytes(self, xml_bytes): | |
577 | 577 | return to_xml(xml_bytes) |
578 | 578 | |
579 | @classmethod | |
580 | def prettify_xml(cls, xml_bytes): | |
579 | def prettify_xml(self, xml_bytes): | |
581 | 580 | """Re-format an XML document to a consistent style.""" |
582 | 581 | return ( |
583 | lxml.etree.tostring(cls.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
582 | lxml.etree.tostring(self.parse_bytes(xml_bytes), xml_declaration=True, encoding="utf-8", pretty_print=True) | |
584 | 583 | .replace(b"\t", b" ") |
585 | 584 | .replace(b" xmlns:", b"\n xmlns:") |
586 | 585 | ) |
838 | 837 | d_start = time.monotonic() |
839 | 838 | # Always create a dummy response for logging purposes, in case we fail in the following |
840 | 839 | r = DummyResponse(url=url, request_headers=headers) |
840 | kwargs = dict(url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream) | |
841 | if isinstance(session, OAuth2Session): | |
842 | # Fix token refreshing bug. Reported as https://github.com/requests/requests-oauthlib/issues/498 | |
843 | kwargs.update(session.auto_refresh_kwargs) | |
841 | 844 | try: |
842 | r = session.post( | |
843 | url=url, headers=headers, data=data, allow_redirects=False, timeout=timeout, stream=stream | |
844 | ) | |
845 | r = session.post(**kwargs) | |
845 | 846 | except TLS_ERRORS as e: |
846 | 847 | # Don't retry on TLS errors. They will most likely be persistent. |
847 | 848 | raise TransportError(str(e)) |
36 | 36 | done |
37 | 37 | |
38 | 38 | """ |
39 | from datetime import timedelta, datetime | |
40 | from netrc import netrc | |
41 | 39 | import sys |
42 | 40 | import warnings |
41 | from datetime import datetime, timedelta | |
42 | from netrc import netrc | |
43 | 43 | |
44 | from exchangelib import DELEGATE, Credentials, Account, EWSTimeZone | |
45 | 44 | import sh |
46 | 45 | |
47 | if '--insecure' in sys.argv: | |
46 | from exchangelib import DELEGATE, Account, Credentials, EWSTimeZone | |
47 | ||
48 | if "--insecure" in sys.argv: | |
48 | 49 | # Disable TLS when Office365 can't get their certificate act together |
49 | 50 | from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter |
51 | ||
50 | 52 | BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter |
51 | 53 | # Disable insecure TLS warnings |
52 | 54 | warnings.filterwarnings("ignore") |
53 | 55 | |
54 | 56 | # Use notify-send for email notifications and zenity for calendar notifications |
55 | notify = sh.Command('/usr/bin/notify-send') | |
56 | zenity = sh.Command('/usr/bin/zenity') | |
57 | notify = sh.Command("/usr/bin/notify-send") | |
58 | zenity = sh.Command("/usr/bin/zenity") | |
57 | 59 | |
58 | 60 | # Get the local timezone |
59 | 61 | tz = EWSTimeZone.localzone() |
62 | 64 | now = datetime.now(tz=tz) |
63 | 65 | emails_since = now - timedelta(seconds=sleep) |
64 | 66 | cal_items_before = now + timedelta(seconds=sleep * 4) # Longer notice of upcoming appointments than new emails |
65 | username, _, password = netrc().authenticators('office365') | |
67 | username, _, password = netrc().authenticators("office365") | |
66 | 68 | c = Credentials(username, password) |
67 | 69 | a = Account(primary_smtp_address=c.username, credentials=c, access_type=DELEGATE, autodiscover=True) |
68 | 70 | |
69 | for msg in a.calendar.view(start=now, end=cal_items_before)\ | |
70 | .only('start', 'end', 'subject', 'location')\ | |
71 | .order_by('start', 'end'): | |
71 | for msg in ( | |
72 | a.calendar.view(start=now, end=cal_items_before) | |
73 | .only("start", "end", "subject", "location") | |
74 | .order_by("start", "end") | |
75 | ): | |
72 | 76 | if msg.start < now: |
73 | 77 | continue |
74 | 78 | minutes_to_appointment = int((msg.start - now).total_seconds() / 60) |
75 | subj = f'You have a meeting in {minutes_to_appointment} minutes' | |
76 | body = f"{msg.start.astimezone(tz).strftime('%H:%M')}-{msg.end.astimezone(tz).strftime('%H:%M')}: " \ | |
77 | f"{msg.subject[:150]}\n{msg.location}" | |
78 | zenity(**{'info': None, 'no-markup': None, 'title': subj, 'text': body}) | |
79 | subj = f"You have a meeting in {minutes_to_appointment} minutes" | |
80 | body = ( | |
81 | f"{msg.start.astimezone(tz).strftime('%H:%M')}-{msg.end.astimezone(tz).strftime('%H:%M')}: " | |
82 | f"{msg.subject[:150]}\n{msg.location}" | |
83 | ) | |
84 | zenity(**{"info": None, "no-markup": None, "title": subj, "text": body}) | |
79 | 85 | |
80 | for msg in a.inbox.filter(datetime_received__gt=emails_since, is_read=False)\ | |
81 | .only('datetime_received', 'subject', 'text_body')\ | |
82 | .order_by('datetime_received')[:10]: | |
83 | subj = f'New mail: {msg.subject}' | |
84 | clean_body = '\n'.join(line for line in msg.text_body.split('\n') if line) | |
86 | for msg in ( | |
87 | a.inbox.filter(datetime_received__gt=emails_since, is_read=False) | |
88 | .only("datetime_received", "subject", "text_body") | |
89 | .order_by("datetime_received")[:10] | |
90 | ): | |
91 | subj = f"New mail: {msg.subject}" | |
92 | clean_body = "\n".join(line for line in msg.text_body.split("\n") if line) | |
85 | 93 | notify(subj, clean_body[:200]) |
5 | 5 | import logging |
6 | 6 | import os |
7 | 7 | import time |
8 | ||
8 | 9 | try: |
9 | 10 | import zoneinfo |
10 | 11 | except ImportError: |
12 | 13 | |
13 | 14 | from yaml import safe_load |
14 | 15 | |
15 | from exchangelib import DELEGATE, Configuration, Account, CalendarItem, Credentials, FaultTolerance | |
16 | from exchangelib import DELEGATE, Account, CalendarItem, Configuration, Credentials, FaultTolerance | |
16 | 17 | |
17 | 18 | logging.basicConfig(level=logging.WARNING) |
18 | 19 | |
19 | 20 | try: |
20 | with open(os.path.join(os.path.dirname(__file__), '../settings.yml')) as f: | |
21 | with open(os.path.join(os.path.dirname(__file__), "../settings.yml")) as f: | |
21 | 22 | settings = safe_load(f) |
22 | 23 | except FileNotFoundError: |
23 | print('Copy settings.yml.sample to settings.yml and enter values for your test server') | |
24 | print("Copy settings.yml.sample to settings.yml and enter values for your test server") | |
24 | 25 | raise |
25 | 26 | |
26 | categories = ['perftest'] | |
27 | tz = zoneinfo.ZoneInfo('America/New_York') | |
27 | categories = ["perftest"] | |
28 | tz = zoneinfo.ZoneInfo("America/New_York") | |
28 | 29 | |
29 | verify_ssl = settings.get('verify_ssl', True) | |
30 | verify_ssl = settings.get("verify_ssl", True) | |
30 | 31 | if not verify_ssl: |
31 | 32 | from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter |
33 | ||
32 | 34 | BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter |
33 | 35 | |
34 | 36 | config = Configuration( |
35 | server=settings['server'], | |
36 | credentials=Credentials(settings['username'], settings['password']), | |
37 | server=settings["server"], | |
38 | credentials=Credentials(settings["username"], settings["password"]), | |
37 | 39 | retry_policy=FaultTolerance(), |
38 | 40 | ) |
39 | print(f'Exchange server: {config.service_endpoint}') | |
41 | print(f"Exchange server: {config.service_endpoint}") | |
40 | 42 | |
41 | account = Account(config=config, primary_smtp_address=settings['account'], access_type=DELEGATE) | |
43 | account = Account(config=config, primary_smtp_address=settings["account"], access_type=DELEGATE) | |
42 | 44 | |
43 | 45 | # Remove leftovers from earlier tests |
44 | 46 | account.calendar.filter(categories__contains=categories).delete() |
51 | 53 | tpl_item = CalendarItem( |
52 | 54 | start=start, |
53 | 55 | end=end, |
54 | body=f'This is a performance optimization test of server {account.protocol.server} intended to find the ' | |
55 | f'optimal batch size and concurrent connection pool size of this server.', | |
56 | body=f"This is a performance optimization test of server {account.protocol.server} intended to find the " | |
57 | f"optimal batch size and concurrent connection pool size of this server.", | |
56 | 58 | location="It's safe to delete this", |
57 | 59 | categories=categories, |
58 | 60 | ) |
59 | 61 | for j in range(count): |
60 | 62 | item = copy.copy(tpl_item) |
61 | item.subject = f'Performance optimization test {j} by exchangelib', | |
63 | item.subject = (f"Performance optimization test {j} by exchangelib",) | |
62 | 64 | yield item |
63 | 65 | |
64 | 66 | |
74 | 76 | rate1 = len(ids) / delta1 |
75 | 77 | delta2 = t3 - t2 |
76 | 78 | rate2 = len(ids) / delta2 |
77 | print(f'Time to process {len(ids)} items (batchsize {chunk_size}, poolsize {account.protocol.poolsize}): ' | |
78 | f'{delta1} / {delta2} ({rate1} / {rate2} per sec)') | |
79 | print( | |
80 | f"Time to process {len(ids)} items (batchsize {chunk_size}, poolsize {account.protocol.poolsize}): " | |
81 | f"{delta1} / {delta2} ({rate1} / {rate2} per sec)" | |
82 | ) | |
79 | 83 | |
80 | 84 | |
81 | 85 | # Generate items |
82 | 86 | calitems = list(generate_items(500)) |
83 | 87 | |
84 | print('\nTesting batch size') | |
88 | print("\nTesting batch size") | |
85 | 89 | for i in range(1, 11): |
86 | 90 | chunk_size = 25 * i |
87 | 91 | account.protocol.poolsize = 5 |
88 | 92 | test(calitems, chunk_size) |
89 | 93 | time.sleep(60) # Sleep 1 minute. Performance will deteriorate over time if we give the server tie to recover |
90 | 94 | |
91 | print('\nTesting pool size') | |
95 | print("\nTesting pool size") | |
92 | 96 | for i in range(1, 11): |
93 | 97 | chunk_size = 10 |
94 | 98 | account.protocol.poolsize = i |
0 | from exchangelib.protocol import BaseProtocol | |
0 | 1 | from tests.common import EWSTest |
1 | 2 | |
3 | BaseProtocol.TIMEOUT = 300 # Seconds | |
2 | 4 | t = EWSTest() |
3 | 5 | t.setUpClass() |
4 | 6 | t.wipe_test_account() |
Binary diff not shown
0 | 0 | server: 'example.com' |
1 | 1 | autodiscover_server: 'example.com' |
2 | ||
2 | 3 | username: 'MYWINDOMAIN\myusername' |
3 | 4 | password: 'topsecret' |
5 | ||
6 | # Or, for OAuth: | |
7 | tenant_id: | |
8 | client_id: | |
9 | client_secret: | |
10 | ||
4 | 11 | account: 'john.doe@example.com' # Don't use an account containing valuable data! We're polite, but things may go wrong. |
5 | verify_ssl: True | |
12 | alias: 'john.doe@example.com' # For autodiscover lookups with an alias. Can be the same as 'account'. | |
13 | verify_ssl: True # Must be True for OAuth |
2 | 2 | |
3 | 3 | [metadata] |
4 | 4 | license_file = LICENSE |
5 | ||
6 | [flake8] | |
7 | ignore = E203, W503 | |
8 | max-line-length = 120⏎ |
12 | 12 | import io |
13 | 13 | import os |
14 | 14 | |
15 | from setuptools import setup, find_packages | |
15 | from setuptools import find_packages, setup | |
16 | 16 | |
17 | 17 | |
18 | 18 | def version(): |
19 | with io.open(os.path.join(os.path.dirname(__file__), 'exchangelib/__init__.py'), encoding='utf-8') as f: | |
19 | with io.open(os.path.join(os.path.dirname(__file__), "exchangelib/__init__.py"), encoding="utf-8") as f: | |
20 | 20 | for line in f: |
21 | if not line.startswith('__version__'): | |
21 | if not line.startswith("__version__"): | |
22 | 22 | continue |
23 | return line.split('=')[1].strip(' "\'\n') | |
23 | return line.split("=")[1].strip(" \"'\n") | |
24 | 24 | |
25 | 25 | |
26 | 26 | def read(file_name): |
27 | with io.open(os.path.join(os.path.dirname(__file__), file_name), encoding='utf-8') as f: | |
27 | with io.open(os.path.join(os.path.dirname(__file__), file_name), encoding="utf-8") as f: | |
28 | 28 | return f.read() |
29 | 29 | |
30 | 30 | |
31 | 31 | setup( |
32 | name='exchangelib', | |
32 | name="exchangelib", | |
33 | 33 | version=version(), |
34 | author='Erik Cederstrand', | |
35 | author_email='erik@cederstrand.dk', | |
36 | description='Client for Microsoft Exchange Web Services (EWS)', | |
37 | long_description=read('README.md'), | |
38 | long_description_content_type='text/markdown', | |
39 | license='BSD-2-Clause', | |
40 | keywords='ews exchange autodiscover microsoft outlook exchange-web-services o365 office365', | |
34 | author="Erik Cederstrand", | |
35 | author_email="erik@cederstrand.dk", | |
36 | description="Client for Microsoft Exchange Web Services (EWS)", | |
37 | long_description=read("README.md"), | |
38 | long_description_content_type="text/markdown", | |
39 | license="BSD-2-Clause", | |
40 | keywords="ews exchange autodiscover microsoft outlook exchange-web-services o365 office365", | |
41 | 41 | install_requires=[ |
42 | 42 | 'backports.zoneinfo;python_version<"3.9"', |
43 | 'cached_property', | |
44 | 'defusedxml>=0.6.0', | |
45 | 'dnspython>=2.0.0', | |
46 | 'isodate', | |
47 | 'lxml>3.0', | |
48 | 'oauthlib', | |
49 | 'pygments', | |
50 | 'requests>=2.7', | |
51 | 'requests_ntlm>=0.2.0', | |
52 | 'requests_oauthlib', | |
53 | 'tzdata', | |
54 | 'tzlocal', | |
43 | "cached_property", | |
44 | "defusedxml>=0.6.0", | |
45 | "dnspython>=2.0.0", | |
46 | "isodate", | |
47 | "lxml>3.0", | |
48 | "oauthlib", | |
49 | "pygments", | |
50 | "requests>=2.7", | |
51 | "requests_ntlm>=0.2.0", | |
52 | "requests_oauthlib", | |
53 | "tzdata", | |
54 | "tzlocal", | |
55 | 55 | ], |
56 | 56 | extras_require={ |
57 | 'kerberos': ['requests_gssapi'], | |
58 | 'sspi': ['requests_negotiate_sspi'], # Only for Win32 environments | |
59 | 'complete': ['requests_gssapi', 'requests_negotiate_sspi'], # Only for Win32 environments | |
57 | "kerberos": ["requests_gssapi"], | |
58 | "sspi": ["requests_negotiate_sspi"], # Only for Win32 environments | |
59 | "complete": ["requests_gssapi", "requests_negotiate_sspi"], # Only for Win32 environments | |
60 | 60 | }, |
61 | packages=find_packages(exclude=('tests', 'tests.*')), | |
62 | tests_require=['psutil', 'python-dateutil', 'pytz', 'PyYAML', 'requests_mock'], | |
61 | packages=find_packages(exclude=("tests", "tests.*")), | |
63 | 62 | python_requires=">=3.7", |
64 | test_suite='tests', | |
63 | test_suite="tests", | |
65 | 64 | zip_safe=False, |
66 | url='https://github.com/ecederstrand/exchangelib', | |
65 | url="https://github.com/ecederstrand/exchangelib", | |
67 | 66 | project_urls={ |
68 | 67 | "Bug Tracker": "https://github.com/ecederstrand/exchangelib/issues", |
69 | 68 | "Documentation": "https://ecederstrand.github.io/exchangelib/", |
70 | 69 | "Source Code": "https://github.com/ecederstrand/exchangelib", |
71 | 70 | }, |
72 | 71 | classifiers=[ |
73 | 'Development Status :: 5 - Production/Stable', | |
74 | 'Topic :: Communications', | |
75 | 'License :: OSI Approved :: BSD License', | |
76 | 'Programming Language :: Python :: 3', | |
72 | "Development Status :: 5 - Production/Stable", | |
73 | "Topic :: Communications", | |
74 | "License :: OSI Approved :: BSD License", | |
75 | "Programming Language :: Python :: 3", | |
77 | 76 | ], |
78 | 77 | ) |
25 | 25 | |
26 | 26 | if os.environ.get("DEBUG", "").lower() in ("1", "yes", "true"): |
27 | 27 | logging.basicConfig(level=logging.DEBUG, handlers=[PrettyXmlHandler()]) |
28 | logging.getLogger("requests").setLevel(level=logging.INFO) | |
29 | logging.getLogger("requests_oauthlib").setLevel(level=logging.INFO) | |
28 | 30 | else: |
29 | 31 | logging.basicConfig(level=logging.CRITICAL) |
15 | 15 | except ImportError: |
16 | 16 | from backports import zoneinfo |
17 | 17 | |
18 | from exchangelib.account import Account | |
18 | from exchangelib.account import Account, Identity | |
19 | 19 | from exchangelib.attachments import FileAttachment |
20 | 20 | from exchangelib.configuration import Configuration |
21 | from exchangelib.credentials import DELEGATE, Credentials | |
21 | from exchangelib.credentials import DELEGATE, IMPERSONATION, Credentials, OAuth2Credentials | |
22 | 22 | from exchangelib.errors import UnknownTimeZone |
23 | 23 | from exchangelib.ewsdatetime import EWSTimeZone |
24 | 24 | from exchangelib.fields import ( |
123 | 123 | cls.retry_policy = FaultTolerance(max_wait=600) |
124 | 124 | cls.config = Configuration( |
125 | 125 | server=settings["server"], |
126 | credentials=Credentials(settings["username"], settings["password"]), | |
126 | credentials=cls.credentials(), | |
127 | 127 | retry_policy=cls.retry_policy, |
128 | 128 | ) |
129 | 129 | cls.account = cls.get_account() |
130 | ||
131 | @classmethod | |
132 | def credentials(cls): | |
133 | if cls.settings.get("client_id"): | |
134 | return OAuth2Credentials( | |
135 | client_id=cls.settings["client_id"], | |
136 | client_secret=cls.settings["client_secret"], | |
137 | tenant_id=cls.settings["tenant_id"], | |
138 | identity=Identity(primary_smtp_address=cls.settings["account"]), | |
139 | ) | |
140 | return Credentials(username=cls.settings["username"], password=cls.settings["password"]) | |
130 | 141 | |
131 | 142 | @classmethod |
132 | 143 | def get_account(cls): |
133 | 144 | return Account( |
134 | 145 | primary_smtp_address=cls.settings["account"], |
135 | access_type=DELEGATE, | |
146 | access_type=IMPERSONATION if isinstance(cls.config.credentials, OAuth2Credentials) else DELEGATE, | |
136 | 147 | config=cls.config, |
137 | 148 | locale="da_DK", |
138 | 149 | default_timezone=cls.tz, |
208 | 219 | if isinstance(field, MailboxListField): |
209 | 220 | # email_address must be a real account on the server(?) |
210 | 221 | # TODO: Mailbox has multiple optional args but vals must match server account, so we can't easily test |
211 | if get_random_bool(): | |
212 | return [Mailbox(email_address=self.account.primary_smtp_address)] | |
213 | return [self.account.primary_smtp_address] | |
222 | return [Mailbox(email_address=self.account.primary_smtp_address)] | |
214 | 223 | if isinstance(field, MailboxField): |
215 | 224 | # email_address must be a real account on the server(?) |
216 | 225 | # TODO: Mailbox has multiple optional args but vals must match server account, so we can't easily test |
217 | if get_random_bool(): | |
218 | return Mailbox(email_address=self.account.primary_smtp_address) | |
219 | return self.account.primary_smtp_address | |
226 | return Mailbox(email_address=self.account.primary_smtp_address) | |
220 | 227 | if isinstance(field, AttendeesField): |
221 | 228 | # Attendee must refer to a real mailbox on the server(?). We're only sure to have one |
222 | if get_random_bool(): | |
223 | mbx = Mailbox(email_address=self.account.primary_smtp_address) | |
224 | else: | |
225 | mbx = self.account.primary_smtp_address | |
229 | mbx = Mailbox(email_address=self.account.primary_smtp_address) | |
226 | 230 | with_last_response_time = get_random_bool() |
227 | 231 | if with_last_response_time: |
228 | 232 | return [ |
232 | 236 | last_response_time=get_random_datetime(tz=self.account.default_timezone), |
233 | 237 | ) |
234 | 238 | ] |
235 | if get_random_bool(): | |
236 | return [Attendee(mailbox=mbx, response_type="Accept")] | |
237 | return [self.account.primary_smtp_address] | |
239 | return [Attendee(mailbox=mbx, response_type="Accept")] | |
238 | 240 | if isinstance(field, EmailAddressesField): |
239 | 241 | addrs = [] |
240 | 242 | for label in EmailAddress.get_field_by_fieldname("label").supported_choices(version=self.account.version): |
320 | 322 | |
321 | 323 | def get_random_decimal(min_val=0, max_val=100): |
322 | 324 | precision = 2 |
323 | val = get_random_int(min_val, max_val * 10 ** precision) / 10.0 ** precision | |
325 | val = get_random_int(min_val, max_val * 10**precision) / 10.0**precision | |
324 | 326 | return Decimal(f"{val:.2f}") |
325 | 327 | |
326 | 328 |
4 | 4 | from exchangelib.account import Account |
5 | 5 | from exchangelib.attachments import FileAttachment |
6 | 6 | from exchangelib.configuration import Configuration |
7 | from exchangelib.credentials import DELEGATE, Credentials | |
7 | from exchangelib.credentials import DELEGATE, Credentials, OAuth2Credentials | |
8 | 8 | from exchangelib.errors import ( |
9 | 9 | ErrorAccessDenied, |
10 | 10 | ErrorDelegateNoUser, |
77 | 77 | access_type=DELEGATE, |
78 | 78 | config=Configuration( |
79 | 79 | service_endpoint=self.account.protocol.service_endpoint, |
80 | credentials=Credentials(self.account.protocol.credentials.username, "WRONG_PASSWORD"), | |
80 | credentials=Credentials("john@example.com", "WRONG_PASSWORD"), | |
81 | 81 | version=self.account.version, |
82 | auth_type=self.account.protocol.auth_type, | |
83 | 82 | retry_policy=self.retry_policy, |
84 | 83 | ), |
85 | 84 | autodiscover=False, |
93 | 92 | access_type=DELEGATE, |
94 | 93 | config=Configuration( |
95 | 94 | service_endpoint=self.account.protocol.service_endpoint, |
96 | credentials=Credentials(self.account.protocol.credentials.username, "WRONG_PASSWORD"), | |
95 | credentials=Credentials("john@example.com", "WRONG_PASSWORD"), | |
97 | 96 | version=self.account.version, |
98 | auth_type=self.account.protocol.auth_type, | |
99 | 97 | retry_policy=self.retry_policy, |
100 | 98 | ), |
101 | 99 | autodiscover=False, |
163 | 161 | |
164 | 162 | def test_mail_tips(self): |
165 | 163 | # Test that mail tips work |
166 | self.assertEqual(self.account.mail_tips.recipient_address, self.account.primary_smtp_address) | |
164 | self.assertEqual(self.account.mail_tips.recipient_address.email_address, self.account.primary_smtp_address) | |
167 | 165 | # recipients must not be empty |
168 | 166 | list( |
169 | 167 | GetMailTips(protocol=self.account.protocol).call( |
291 | 289 | access_type=DELEGATE, |
292 | 290 | config=Configuration( |
293 | 291 | service_endpoint=self.account.protocol.service_endpoint, |
294 | credentials=Credentials(self.account.protocol.credentials.username, "WRONG_PASSWORD"), | |
292 | credentials=Credentials("john@example.com", "WRONG_PASSWORD"), | |
295 | 293 | version=self.account.version, |
296 | auth_type=self.account.protocol.auth_type, | |
297 | 294 | retry_policy=self.retry_policy, |
298 | 295 | ), |
299 | 296 | autodiscover=False, |
323 | 320 | with self.assertRaises(AttributeError): |
324 | 321 | account.protocol.config.credentials = self.account.protocol.credentials |
325 | 322 | # Should succeed after credentials update |
323 | account.protocol.config.auth_type = self.account.protocol.config.auth_type | |
326 | 324 | account.protocol.credentials = self.account.protocol.credentials |
327 | 325 | account.root.refresh() |
328 | 326 | |
329 | 327 | def test_protocol_default_values(self): |
330 | 328 | # Test that retry_policy and auth_type always get a value regardless of how we create an Account |
331 | c = Credentials(self.settings["username"], self.settings["password"]) | |
332 | 329 | a = Account( |
333 | 330 | self.account.primary_smtp_address, |
334 | 331 | autodiscover=False, |
335 | 332 | config=Configuration( |
336 | 333 | server=self.settings["server"], |
337 | credentials=c, | |
334 | credentials=self.account.protocol.credentials, | |
338 | 335 | ), |
339 | 336 | ) |
340 | 337 | self.assertIsNotNone(a.protocol.auth_type) |
341 | 338 | self.assertIsNotNone(a.protocol.retry_policy) |
342 | 339 | |
340 | if isinstance(self.account.protocol.credentials, OAuth2Credentials): | |
341 | self.skipTest("OAuth authentication does not work with POX autodiscover") | |
342 | ||
343 | pox_credentials = Credentials(username=self.settings["username"], password=self.settings["password"]) | |
344 | ||
343 | 345 | a = Account( |
344 | self.account.primary_smtp_address, | |
346 | self.settings["alias"], | |
345 | 347 | autodiscover=True, |
346 | 348 | config=Configuration( |
347 | 349 | server=self.settings["server"], |
348 | credentials=c, | |
350 | credentials=pox_credentials, | |
349 | 351 | ), |
350 | 352 | ) |
351 | 353 | self.assertIsNotNone(a.protocol.auth_type) |
352 | 354 | self.assertIsNotNone(a.protocol.retry_policy) |
353 | 355 | |
354 | a = Account(self.account.primary_smtp_address, autodiscover=True, credentials=c) | |
356 | a = Account(self.settings["alias"], autodiscover=True, credentials=pox_credentials) | |
355 | 357 | self.assertIsNotNone(a.protocol.auth_type) |
356 | 358 | self.assertIsNotNone(a.protocol.retry_policy) |
0 | 0 | from exchangelib.attachments import AttachmentId, FileAttachment, ItemAttachment |
1 | from exchangelib.errors import ErrorInvalidIdMalformed, ErrorItemNotFound | |
1 | from exchangelib.errors import ErrorInvalidAttachmentId, ErrorInvalidIdMalformed | |
2 | 2 | from exchangelib.fields import FieldPath |
3 | 3 | from exchangelib.folders import Inbox |
4 | 4 | from exchangelib.items import Item, Message |
168 | 168 | additional_fields=[FieldPath(field=self.ITEM_CLASS.get_field_by_fieldname("body"))], |
169 | 169 | ) |
170 | 170 | self.assertEqual( |
171 | attachment.item.body, | |
172 | '<html>\r\n<head>\r\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\r\n' | |
173 | "</head>\r\n<body>\r\nHello HTML\r\n</body>\r\n</html>\r\n", | |
171 | attachment.item.body.replace("\r\n", ""), | |
172 | '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">' | |
173 | "</head><body>Hello HTML </body></html>", | |
174 | 174 | ) |
175 | 175 | |
176 | 176 | def test_file_attachments(self): |
214 | 214 | |
215 | 215 | def test_streaming_file_attachments(self): |
216 | 216 | item = self.get_test_item(folder=self.test_folder) |
217 | large_binary_file_content = get_random_string(2 ** 10).encode("utf-8") | |
217 | large_binary_file_content = get_random_string(2**10).encode("utf-8") | |
218 | 218 | large_att = FileAttachment(name="my_large_file.txt", content=large_binary_file_content) |
219 | 219 | item.attach(large_att) |
220 | 220 | item.save() |
237 | 237 | def test_streaming_file_attachment_error(self): |
238 | 238 | # Test that we can parse XML error responses in streaming mode. |
239 | 239 | |
240 | # Try to stram an attachment with malformed ID | |
240 | # Try to stream an attachment with malformed ID | |
241 | item = self.get_test_item(folder=self.test_folder).save() | |
241 | 242 | att = FileAttachment( |
242 | parent_item=self.get_test_item(folder=self.test_folder), | |
243 | parent_item=item, | |
243 | 244 | attachment_id=AttachmentId(id="AAMk="), |
244 | 245 | name="dummy.txt", |
245 | 246 | content=b"", |
249 | 250 | fp.read() |
250 | 251 | |
251 | 252 | # Try to stream a non-existent attachment |
252 | att.attachment_id.id = ( | |
253 | "AAMkADQyYzZmYmUxLTJiYjItNDg2Ny1iMzNjLTIzYWE1NDgxNmZhNABGAAAAAADUebQDarW2Q7G2Ji8hKofPBwAl9iKCsfCfS" | |
254 | "a9cmjh+JCrCAAPJcuhjAABioKiOUTCQRI6Q5sRzi0pJAAHnDV3CAAABEgAQAN0zlxDrzlxAteU+kt84qOM=" | |
255 | ) | |
256 | with self.assertRaises(ErrorItemNotFound): | |
253 | att.attachment_id = None | |
254 | att.attach() | |
255 | att_id = att.attachment_id | |
256 | att.detach() | |
257 | att.parent_item = item | |
258 | att.attachment_id = att_id | |
259 | with self.assertRaises(ErrorInvalidAttachmentId): | |
257 | 260 | with att.fp as fp: |
258 | 261 | fp.read() |
259 | 262 |
22 | 22 | from exchangelib.autodiscover.properties import Account as ADAccount |
23 | 23 | from exchangelib.autodiscover.properties import Autodiscover, Error, ErrorResponse, Response |
24 | 24 | from exchangelib.configuration import Configuration |
25 | from exchangelib.credentials import DELEGATE, Credentials | |
25 | from exchangelib.credentials import DELEGATE, Credentials, OAuth2Credentials | |
26 | 26 | from exchangelib.errors import AutoDiscoverCircularRedirect, AutoDiscoverFailed, ErrorNonExistentMailbox |
27 | 27 | from exchangelib.protocol import FailFast, FaultTolerance |
28 | 28 | from exchangelib.transport import NOAUTH, NTLM |
34 | 34 | |
35 | 35 | class AutodiscoverTest(EWSTest): |
36 | 36 | def setUp(self): |
37 | if isinstance(self.account.protocol.credentials, OAuth2Credentials): | |
38 | self.skipTest("OAuth authentication does not work with POX autodiscover") | |
39 | ||
37 | 40 | super().setUp() |
38 | 41 | |
39 | 42 | # Enable retries, to make tests more robust |
48 | 51 | self.dummy_ad_endpoint = f"https://{self.domain}/Autodiscover/Autodiscover.xml" |
49 | 52 | self.dummy_ews_endpoint = "https://expr.example.com/EWS/Exchange.asmx" |
50 | 53 | self.dummy_ad_response = self.settings_xml(self.account.primary_smtp_address, self.dummy_ews_endpoint) |
54 | ||
55 | self.pox_credentials = Credentials(username=self.settings["username"], password=self.settings["password"]) | |
51 | 56 | |
52 | 57 | @staticmethod |
53 | 58 | def settings_xml(address, ews_url): |
131 | 136 | # A live test of the entire process with an empty cache |
132 | 137 | ad_response, protocol = discover( |
133 | 138 | email=self.account.primary_smtp_address, |
134 | credentials=self.account.protocol.credentials, | |
139 | credentials=self.pox_credentials, | |
135 | 140 | retry_policy=self.retry_policy, |
136 | 141 | ) |
137 | 142 | self.assertEqual(ad_response.autodiscover_smtp_address, self.account.primary_smtp_address) |
142 | 147 | self.assertEqual(protocol.version.build, self.account.protocol.version.build) |
143 | 148 | |
144 | 149 | def test_autodiscover_failure(self): |
145 | # A live test that errors can be raised. Here, we try to aútodiscover a non-existing email address | |
150 | # A live test that errors can be raised. Here, we try to autodiscover a non-existing email address | |
146 | 151 | if not self.settings.get("autodiscover_server"): |
147 | 152 | self.skipTest(f"Skipping {self.__class__.__name__} - no 'autodiscover_server' entry in settings.yml") |
148 | 153 | # Autodiscovery may take a long time. Prime the cache with the autodiscover server from the config file |
149 | 154 | ad_endpoint = f"https://{self.settings['autodiscover_server']}/Autodiscover/Autodiscover.xml" |
150 | cache_key = (self.domain, self.account.protocol.credentials) | |
155 | cache_key = (self.domain, self.pox_credentials) | |
151 | 156 | autodiscover_cache[cache_key] = self.get_test_protocol( |
152 | 157 | service_endpoint=ad_endpoint, |
153 | credentials=self.account.protocol.credentials, | |
158 | credentials=self.pox_credentials, | |
154 | 159 | retry_policy=self.retry_policy, |
155 | 160 | ) |
156 | 161 | with self.assertRaises(ErrorNonExistentMailbox): |
157 | 162 | discover( |
158 | 163 | email="XXX." + self.account.primary_smtp_address, |
159 | credentials=self.account.protocol.credentials, | |
164 | credentials=self.pox_credentials, | |
160 | 165 | retry_policy=self.retry_policy, |
161 | 166 | ) |
162 | 167 | |
165 | 170 | Account( |
166 | 171 | primary_smtp_address=self.account.primary_smtp_address, |
167 | 172 | access_type=DELEGATE, |
168 | credentials=Credentials(self.account.protocol.credentials.username, "WRONG_PASSWORD"), | |
173 | credentials=Credentials("john@example.com", "WRONG_PASSWORD"), | |
169 | 174 | autodiscover=True, |
170 | 175 | locale="da_DK", |
171 | 176 | ) |
192 | 197 | m.post(self.dummy_ad_endpoint, status_code=200, content=self.dummy_ad_response) |
193 | 198 | discovery = Autodiscovery( |
194 | 199 | email=self.account.primary_smtp_address, |
195 | credentials=self.account.protocol.credentials, | |
200 | credentials=self.pox_credentials, | |
196 | 201 | ) |
197 | 202 | # Not cached |
198 | 203 | self.assertNotIn(discovery._cache_key, autodiscover_cache) |
203 | 208 | self.assertIn( |
204 | 209 | ( |
205 | 210 | self.account.primary_smtp_address.split("@")[1], |
206 | Credentials(self.account.protocol.credentials.username, self.account.protocol.credentials.password), | |
211 | self.pox_credentials, | |
207 | 212 | True, |
208 | 213 | ), |
209 | 214 | autodiscover_cache, |
265 | 270 | account = Account( |
266 | 271 | primary_smtp_address=self.account.primary_smtp_address, |
267 | 272 | config=Configuration( |
268 | credentials=self.account.protocol.credentials, | |
273 | credentials=self.pox_credentials, | |
269 | 274 | retry_policy=self.retry_policy, |
270 | 275 | version=Version(build=EXCHANGE_2013), |
271 | 276 | ), |
276 | 281 | self.assertEqual(account.protocol.service_endpoint.lower(), self.dummy_ews_endpoint.lower()) |
277 | 282 | # Make sure cache is full |
278 | 283 | self.assertEqual(len(autodiscover_cache), 1) |
279 | self.assertTrue((account.domain, self.account.protocol.credentials, True) in autodiscover_cache) | |
284 | self.assertTrue((account.domain, self.pox_credentials, True) in autodiscover_cache) | |
280 | 285 | # Test that autodiscover works with a full cache |
281 | 286 | account = Account( |
282 | 287 | primary_smtp_address=self.account.primary_smtp_address, |
283 | 288 | config=Configuration( |
284 | credentials=self.account.protocol.credentials, | |
289 | credentials=self.pox_credentials, | |
285 | 290 | retry_policy=self.retry_policy, |
286 | 291 | ), |
287 | 292 | autodiscover=True, |
289 | 294 | ) |
290 | 295 | self.assertEqual(account.primary_smtp_address, self.account.primary_smtp_address) |
291 | 296 | # Test cache manipulation |
292 | key = (account.domain, self.account.protocol.credentials, True) | |
297 | key = (account.domain, self.pox_credentials, True) | |
293 | 298 | self.assertTrue(key in autodiscover_cache) |
294 | 299 | del autodiscover_cache[key] |
295 | 300 | self.assertFalse(key in autodiscover_cache) |
302 | 307 | m.post(self.dummy_ad_endpoint, status_code=200, content=self.dummy_ad_response) |
303 | 308 | discovery = Autodiscovery( |
304 | 309 | email=self.account.primary_smtp_address, |
305 | credentials=self.account.protocol.credentials, | |
310 | credentials=self.pox_credentials, | |
306 | 311 | ) |
307 | 312 | discovery.discover() |
308 | 313 | |
379 | 384 | def test_autodiscover_path_1_2_5(self, m): |
380 | 385 | # Test steps 1 -> 2 -> 5 |
381 | 386 | clear_cache() |
382 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
387 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
383 | 388 | ews_url = f"https://xxx.{self.domain}/EWS/Exchange.asmx" |
384 | 389 | email = f"xxxd@{self.domain}" |
385 | 390 | m.post(self.dummy_ad_endpoint, status_code=501) |
396 | 401 | def test_autodiscover_path_1_2_3_invalid301_4(self, m): |
397 | 402 | # Test steps 1 -> 2 -> 3 -> invalid 301 URL -> 4 |
398 | 403 | clear_cache() |
399 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
404 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
400 | 405 | m.post(self.dummy_ad_endpoint, status_code=501) |
401 | 406 | m.post(f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=501) |
402 | 407 | m.get( |
412 | 417 | @requests_mock.mock(real_http=False) |
413 | 418 | def test_autodiscover_path_1_2_3_no301_4(self, m): |
414 | 419 | # Test steps 1 -> 2 -> 3 -> no 301 response -> 4 |
415 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
420 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
416 | 421 | m.post(self.dummy_ad_endpoint, status_code=501) |
417 | 422 | m.post(f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=501) |
418 | 423 | m.get(f"http://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=200) |
424 | 429 | @requests_mock.mock(real_http=False) |
425 | 430 | def test_autodiscover_path_1_2_3_4_valid_srv_invalid_response(self, m): |
426 | 431 | # Test steps 1 -> 2 -> 3 -> 4 -> invalid response from SRV URL |
427 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
432 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
428 | 433 | redirect_srv = "httpbin.org" |
429 | 434 | m.post(self.dummy_ad_endpoint, status_code=501) |
430 | 435 | m.post(f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=501) |
444 | 449 | @requests_mock.mock(real_http=False) |
445 | 450 | def test_autodiscover_path_1_2_3_4_valid_srv_valid_response(self, m): |
446 | 451 | # Test steps 1 -> 2 -> 3 -> 4 -> 5 |
447 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
452 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
448 | 453 | redirect_srv = "httpbin.org" |
449 | 454 | ews_url = f"https://{redirect_srv}/EWS/Exchange.asmx" |
450 | 455 | redirect_email = f"john@redirected.{redirect_srv}" |
470 | 475 | @requests_mock.mock(real_http=False) |
471 | 476 | def test_autodiscover_path_1_2_3_4_invalid_srv(self, m): |
472 | 477 | # Test steps 1 -> 2 -> 3 -> 4 -> invalid SRV URL |
473 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
478 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
474 | 479 | m.post(self.dummy_ad_endpoint, status_code=501) |
475 | 480 | m.post(f"https://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=501) |
476 | 481 | m.get(f"http://autodiscover.{self.domain}/Autodiscover/Autodiscover.xml", status_code=200) |
488 | 493 | def test_autodiscover_path_1_5_invalid_redirect_url(self, m): |
489 | 494 | # Test steps 1 -> -> 5 -> Invalid redirect URL |
490 | 495 | clear_cache() |
491 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
496 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
492 | 497 | m.post( |
493 | 498 | self.dummy_ad_endpoint, |
494 | 499 | status_code=200, |
503 | 508 | def test_autodiscover_path_1_5_valid_redirect_url_invalid_response(self, m): |
504 | 509 | # Test steps 1 -> -> 5 -> Invalid response from redirect URL |
505 | 510 | clear_cache() |
506 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
511 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
507 | 512 | redirect_url = "https://httpbin.org/Autodiscover/Autodiscover.xml" |
508 | 513 | m.post(self.dummy_ad_endpoint, status_code=200, content=self.redirect_url_xml(redirect_url)) |
509 | 514 | m.head(redirect_url, status_code=501) |
517 | 522 | def test_autodiscover_path_1_5_valid_redirect_url_valid_response(self, m): |
518 | 523 | # Test steps 1 -> -> 5 -> Valid response from redirect URL -> 5 |
519 | 524 | clear_cache() |
520 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.account.protocol.credentials) | |
525 | d = Autodiscovery(email=self.account.primary_smtp_address, credentials=self.pox_credentials) | |
521 | 526 | redirect_hostname = "httpbin.org" |
522 | 527 | redirect_url = f"https://{redirect_hostname}/Autodiscover/Autodiscover.xml" |
523 | 528 | ews_url = f"https://{redirect_hostname}/EWS/Exchange.asmx" |
541 | 546 | |
542 | 547 | class _Mock1: |
543 | 548 | @staticmethod |
544 | def resolve(hostname, cat): | |
549 | def resolve(*args, **kwargs): | |
545 | 550 | class A: |
546 | 551 | @staticmethod |
547 | 552 | def to_text(): |
559 | 564 | |
560 | 565 | class _Mock2: |
561 | 566 | @staticmethod |
562 | def resolve(hostname, cat): | |
567 | def resolve(*args, **kwargs): | |
563 | 568 | class A: |
564 | 569 | @staticmethod |
565 | 570 | def to_text(): |
27 | 27 | for o in ( |
28 | 28 | Identity("XXX", "YYY", "ZZZ", "WWW"), |
29 | 29 | Credentials("XXX", "YYY"), |
30 | OAuth2Credentials("XXX", "YYY", "ZZZZ"), | |
31 | OAuth2Credentials("XXX", "YYY", "ZZZZ", identity=Identity("AAA")), | |
32 | OAuth2AuthorizationCodeCredentials(client_id="WWW", client_secret="XXX"), | |
30 | OAuth2Credentials(client_id="XXX", client_secret="YYY", tenant_id="ZZZZ"), | |
31 | OAuth2Credentials(client_id="XXX", client_secret="YYY", tenant_id="ZZZZ", identity=Identity("AAA")), | |
32 | OAuth2AuthorizationCodeCredentials(client_id="WWW", client_secret="XXX", authorization_code="YYY"), | |
33 | OAuth2AuthorizationCodeCredentials( | |
34 | client_id="WWW", client_secret="XXX", access_token={"access_token": "ZZZ"} | |
35 | ), | |
36 | OAuth2AuthorizationCodeCredentials(access_token={"access_token": "ZZZ"}), | |
33 | 37 | OAuth2AuthorizationCodeCredentials( |
34 | 38 | client_id="WWW", |
35 | 39 | client_secret="XXX", |
341 | 341 | item = self.get_test_item(folder=self.test_folder).save() |
342 | 342 | self.assertEqual(self.test_folder.filter(**{attr_name: getattr(item, attr_name)}).count(), 1) |
343 | 343 | self.assertEqual( |
344 | self.test_folder.filter(**{f"{array_attr_name}__contains": getattr(item, array_attr_name)}).count(), 1 | |
344 | # Does not work in O365 | |
345 | # self.test_folder.filter(**{f"{array_attr_name}__contains": getattr(item, array_attr_name)}).count(), 1 | |
346 | self.test_folder.filter(**{f"{array_attr_name}__in": getattr(item, array_attr_name)}).count(), | |
347 | 1, | |
345 | 348 | ) |
346 | 349 | finally: |
347 | 350 | self.ITEM_CLASS.deregister(attr_name=attr_name) |
7 | 7 | ErrorFolderNotFound, |
8 | 8 | ErrorItemNotFound, |
9 | 9 | ErrorItemSave, |
10 | ErrorNoPublicFolderReplicaAvailable, | |
10 | 11 | ErrorObjectTypeChanged, |
11 | 12 | MultipleObjectsReturned, |
12 | 13 | ) |
16 | 17 | SHALLOW, |
17 | 18 | AllContacts, |
18 | 19 | AllItems, |
20 | ApplicationData, | |
21 | Birthdays, | |
19 | 22 | Calendar, |
20 | 23 | Companies, |
21 | 24 | Contacts, |
22 | 25 | ConversationSettings, |
26 | CrawlerData, | |
23 | 27 | DefaultFoldersChangeHistory, |
24 | 28 | DeletedItems, |
25 | 29 | DistinguishedFolderId, |
30 | DlpPolicyEvaluation, | |
26 | 31 | Drafts, |
27 | 32 | Favorites, |
28 | 33 | Files, |
29 | 34 | Folder, |
30 | 35 | FolderCollection, |
31 | 36 | FolderQuerySet, |
37 | FreeBusyCache, | |
32 | 38 | Friends, |
33 | 39 | GALContacts, |
34 | 40 | GraphAnalytics, |
48 | 54 | PublicFoldersRoot, |
49 | 55 | QuickContacts, |
50 | 56 | RecipientCache, |
57 | RecoveryPoints, | |
51 | 58 | Reminders, |
52 | 59 | RootOfHierarchy, |
53 | 60 | RSSFeeds, |
55 | 62 | Sharing, |
56 | 63 | Signal, |
57 | 64 | SingleFolderQuerySet, |
65 | SkypeTeamsMessages, | |
58 | 66 | SmsAndChatsSync, |
67 | SwssItems, | |
59 | 68 | SyncIssues, |
60 | System, | |
61 | 69 | Tasks, |
62 | 70 | ToDoSearch, |
63 | 71 | VoiceMail, |
123 | 131 | with self.assertRaises(ValueError): |
124 | 132 | self.account.root.get_default_folder(Folder) |
125 | 133 | |
126 | with self.assertRaises(ValueError) as e: | |
127 | Folder(root=self.account.public_folders_root, parent=self.account.inbox) | |
128 | self.assertEqual(e.exception.args[0], "'parent.root' must match 'root'") | |
134 | try: | |
135 | with self.assertRaises(ValueError) as e: | |
136 | Folder(root=self.account.public_folders_root, parent=self.account.inbox) | |
137 | self.assertEqual(e.exception.args[0], "'parent.root' must match 'root'") | |
138 | except ErrorFolderNotFound: | |
139 | pass | |
129 | 140 | with self.assertRaises(ValueError) as e: |
130 | 141 | Folder(parent=self.account.inbox, parent_folder_id="XXX") |
131 | 142 | self.assertEqual(e.exception.args[0], "'parent_folder_id' must match 'parent' ID") |
146 | 157 | |
147 | 158 | def test_public_folders_root(self): |
148 | 159 | # Test account does not have a public folders root. Make a dummy query just to hit .get_children() |
149 | self.assertGreaterEqual( | |
150 | len(list(PublicFoldersRoot(account=self.account, is_distinguished=True).get_children(self.account.inbox))), | |
151 | 0, | |
152 | ) | |
160 | try: | |
161 | self.assertGreaterEqual( | |
162 | len( | |
163 | list( | |
164 | PublicFoldersRoot(account=self.account, is_distinguished=True).get_children(self.account.inbox) | |
165 | ) | |
166 | ), | |
167 | 0, | |
168 | ) | |
169 | except ErrorNoPublicFolderReplicaAvailable: | |
170 | pass | |
153 | 171 | |
154 | 172 | def test_invalid_deletefolder_args(self): |
155 | 173 | with self.assertRaises(ValueError) as e: |
201 | 219 | self.assertGreater(len(folders), 40, sorted(f.name for f in folders)) |
202 | 220 | |
203 | 221 | def test_find_folders_multiple_roots(self): |
204 | coll = FolderCollection(account=self.account, folders=[self.account.root, self.account.public_folders_root]) | |
222 | try: | |
223 | coll = FolderCollection(account=self.account, folders=[self.account.root, self.account.public_folders_root]) | |
224 | except ErrorFolderNotFound as e: | |
225 | self.skipTest(str(e)) | |
205 | 226 | with self.assertRaises(ValueError) as e: |
206 | 227 | list(coll.find_folders(depth="Shallow")) |
207 | 228 | self.assertIn("All folders in 'roots' must have the same root hierarchy", e.exception.args[0]) |
216 | 237 | |
217 | 238 | def test_find_folders_with_restriction(self): |
218 | 239 | # Exact match |
240 | tois_folder_name = self.account.root.tois.name | |
219 | 241 | folders = list( |
220 | FolderCollection(account=self.account, folders=[self.account.root]).find_folders( | |
221 | q=Q(name="Top of Information Store") | |
222 | ) | |
242 | FolderCollection(account=self.account, folders=[self.account.root]).find_folders(q=Q(name=tois_folder_name)) | |
223 | 243 | ) |
224 | 244 | self.assertEqual(len(folders), 1, sorted(f.name for f in folders)) |
225 | 245 | # Startswith |
226 | 246 | folders = list( |
227 | 247 | FolderCollection(account=self.account, folders=[self.account.root]).find_folders( |
228 | q=Q(name__startswith="Top of ") | |
248 | q=Q(name__startswith=tois_folder_name[:6]) | |
229 | 249 | ) |
230 | 250 | ) |
231 | 251 | self.assertEqual(len(folders), 1, sorted(f.name for f in folders)) |
232 | 252 | # Wrong case |
233 | 253 | folders = list( |
234 | 254 | FolderCollection(account=self.account, folders=[self.account.root]).find_folders( |
235 | q=Q(name__startswith="top of ") | |
255 | q=Q(name__startswith=tois_folder_name[:6].lower()) | |
236 | 256 | ) |
237 | 257 | ) |
238 | 258 | self.assertEqual(len(folders), 0, sorted(f.name for f in folders)) |
239 | 259 | # Case insensitive |
240 | 260 | folders = list( |
241 | 261 | FolderCollection(account=self.account, folders=[self.account.root]).find_folders( |
242 | q=Q(name__istartswith="top of ") | |
262 | q=Q(name__istartswith=tois_folder_name[:6].lower()) | |
243 | 263 | ) |
244 | 264 | ) |
245 | 265 | self.assertEqual(len(folders), 1, sorted(f.name for f in folders)) |
299 | 319 | ), |
300 | 320 | ): |
301 | 321 | self.assertEqual(f.folder_class, "IPF.Note") |
322 | elif isinstance(f, ApplicationData): | |
323 | self.assertEqual(f.folder_class, "IPM.ApplicationData") | |
324 | elif isinstance(f, CrawlerData): | |
325 | self.assertEqual(f.folder_class, "IPF.StoreItem.CrawlerData") | |
326 | elif isinstance(f, DlpPolicyEvaluation): | |
327 | self.assertEqual(f.folder_class, "IPF.StoreItem.DlpPolicyEvaluation") | |
328 | elif isinstance(f, FreeBusyCache): | |
329 | self.assertEqual(f.folder_class, "IPF.StoreItem.FreeBusyCache") | |
330 | elif isinstance(f, RecoveryPoints): | |
331 | self.assertEqual(f.folder_class, "IPF.StoreItem.RecoveryPoints") | |
332 | elif isinstance(f, SwssItems): | |
333 | self.assertEqual(f.folder_class, "IPF.StoreItem.SwssItems") | |
334 | elif isinstance(f, PassThroughSearchResults): | |
335 | self.assertEqual(f.folder_class, "IPF.StoreItem.PassThroughSearchResults") | |
336 | elif isinstance(f, GraphAnalytics): | |
337 | self.assertEqual(f.folder_class, "IPF.StoreItem.GraphAnalytics") | |
338 | elif isinstance(f, Signal): | |
339 | self.assertEqual(f.folder_class, "IPF.StoreItem.Signal") | |
340 | elif isinstance(f, PdpProfileV2Secured): | |
341 | self.assertEqual(f.folder_class, "IPF.StoreItem.PdpProfileSecured") | |
302 | 342 | elif isinstance(f, Companies): |
303 | 343 | self.assertEqual(f.folder_class, "IPF.Contact.Company") |
304 | 344 | elif isinstance(f, OrganizationalContacts): |
309 | 349 | self.assertEqual(f.folder_class, "IPF.Contact.GalContacts") |
310 | 350 | elif isinstance(f, RecipientCache): |
311 | 351 | self.assertEqual(f.folder_class, "IPF.Contact.RecipientCache") |
352 | elif isinstance(f, IMContactList): | |
353 | self.assertEqual(f.folder_class, "IPF.Contact.MOC.ImContactList") | |
354 | elif isinstance(f, QuickContacts): | |
355 | self.assertEqual(f.folder_class, "IPF.Contact.MOC.QuickContacts") | |
312 | 356 | elif isinstance(f, Contacts): |
313 | 357 | self.assertEqual(f.folder_class, "IPF.Contact") |
358 | elif isinstance(f, Birthdays): | |
359 | self.assertEqual(f.folder_class, "IPF.Appointment.Birthday") | |
314 | 360 | elif isinstance(f, Calendar): |
315 | 361 | self.assertEqual(f.folder_class, "IPF.Appointment") |
316 | 362 | elif isinstance(f, (Tasks, ToDoSearch)): |
323 | 369 | self.assertEqual(f.folder_class, "IPF.Configuration") |
324 | 370 | elif isinstance(f, Files): |
325 | 371 | self.assertEqual(f.folder_class, "IPF.Files") |
372 | elif isinstance(f, VoiceMail): | |
373 | self.assertEqual(f.folder_class, "IPF.Note.Microsoft.Voicemail") | |
374 | elif isinstance(f, RSSFeeds): | |
375 | self.assertEqual(f.folder_class, "IPF.Note.OutlookHomepage") | |
326 | 376 | elif isinstance(f, Friends): |
327 | 377 | self.assertEqual(f.folder_class, "IPF.Note") |
328 | elif isinstance(f, RSSFeeds): | |
329 | self.assertEqual(f.folder_class, "IPF.Note.OutlookHomepage") | |
330 | elif isinstance(f, IMContactList): | |
331 | self.assertEqual(f.folder_class, "IPF.Contact.MOC.ImContactList") | |
332 | elif isinstance(f, QuickContacts): | |
333 | self.assertEqual(f.folder_class, "IPF.Contact.MOC.QuickContacts") | |
334 | 378 | elif isinstance(f, Journal): |
335 | 379 | self.assertEqual(f.folder_class, "IPF.Journal") |
336 | 380 | elif isinstance(f, Notes): |
337 | 381 | self.assertEqual(f.folder_class, "IPF.StickyNote") |
338 | 382 | elif isinstance(f, DefaultFoldersChangeHistory): |
339 | 383 | self.assertEqual(f.folder_class, "IPM.DefaultFolderHistoryItem") |
340 | elif isinstance(f, PassThroughSearchResults): | |
341 | self.assertEqual(f.folder_class, "IPF.StoreItem.PassThroughSearchResults") | |
384 | elif isinstance(f, SkypeTeamsMessages): | |
385 | self.assertEqual(f.folder_class, "IPF.SkypeTeams.Message") | |
342 | 386 | elif isinstance(f, SmsAndChatsSync): |
343 | 387 | self.assertEqual(f.folder_class, "IPF.SmsAndChatsSync") |
344 | elif isinstance(f, GraphAnalytics): | |
345 | self.assertEqual(f.folder_class, "IPF.StoreItem.GraphAnalytics") | |
346 | elif isinstance(f, Signal): | |
347 | self.assertEqual(f.folder_class, "IPF.StoreItem.Signal") | |
348 | elif isinstance(f, PdpProfileV2Secured): | |
349 | self.assertEqual(f.folder_class, "IPF.StoreItem.PdpProfileSecured") | |
350 | elif isinstance(f, VoiceMail): | |
351 | self.assertEqual(f.folder_class, "IPF.Note.Microsoft.Voicemail") | |
352 | 388 | else: |
353 | 389 | self.assertIn(f.folder_class, (None, "IPF"), (f.name, f.__class__.__name__, f.folder_class)) |
354 | 390 | self.assertIsInstance(f, Folder) |
442 | 478 | folder.refresh() # Must have an id |
443 | 479 | |
444 | 480 | def test_parent(self): |
445 | self.assertEqual(self.account.calendar.parent.name, "Top of Information Store") | |
481 | self.assertEqual(self.account.calendar.parent.name, self.account.root.tois.name) | |
446 | 482 | self.assertEqual(self.account.calendar.parent.parent.name, "root") |
447 | 483 | # Setters |
448 | 484 | parent = self.account.calendar.parent |
458 | 494 | self.assertIsNone(Folder(id=self.account.inbox.id, parent=self.account.inbox).parent) |
459 | 495 | |
460 | 496 | def test_children(self): |
461 | self.assertIn("Top of Information Store", [c.name for c in self.account.root.children]) | |
497 | self.assertIn(self.account.root.tois.name, [c.name for c in self.account.root.children]) | |
462 | 498 | |
463 | 499 | def test_parts(self): |
464 | 500 | self.assertEqual( |
465 | 501 | [p.name for p in self.account.calendar.parts], |
466 | ["root", "Top of Information Store", self.account.calendar.name], | |
502 | ["root", self.account.root.tois.name, self.account.calendar.name], | |
467 | 503 | ) |
468 | 504 | |
469 | 505 | def test_absolute(self): |
470 | self.assertEqual(self.account.calendar.absolute, "/root/Top of Information Store/" + self.account.calendar.name) | |
506 | self.assertEqual( | |
507 | self.account.calendar.absolute, f"/root/{self.account.root.tois.name}/{self.account.calendar.name}" | |
508 | ) | |
471 | 509 | |
472 | 510 | def test_walk(self): |
473 | 511 | self.assertGreaterEqual(len(list(self.account.root.walk())), 20) |
483 | 521 | self.assertGreaterEqual(len(list(self.account.contacts.glob("/"))), 5) |
484 | 522 | self.assertGreaterEqual(len(list(self.account.contacts.glob("../*"))), 5) |
485 | 523 | self.assertEqual(len(list(self.account.root.glob(f"**/{self.account.contacts.name}"))), 1) |
486 | self.assertEqual(len(list(self.account.root.glob(f"Top of*/{self.account.contacts.name}"))), 1) | |
524 | self.assertEqual( | |
525 | len(list(self.account.root.glob(f"{self.account.root.tois.name[:6]}*/{self.account.contacts.name}"))), 1 | |
526 | ) | |
487 | 527 | with self.assertRaises(ValueError) as e: |
488 | 528 | list(self.account.root.glob("../*")) |
489 | 529 | self.assertEqual(e.exception.args[0], "Already at top") |
502 | 542 | |
503 | 543 | def test_div_navigation(self): |
504 | 544 | self.assertEqual( |
505 | (self.account.root / "Top of Information Store" / self.account.calendar.name).id, self.account.calendar.id | |
506 | ) | |
507 | self.assertEqual((self.account.root / "Top of Information Store" / "..").id, self.account.root.id) | |
545 | (self.account.root / self.account.root.tois.name / self.account.calendar.name).id, self.account.calendar.id | |
546 | ) | |
547 | self.assertEqual((self.account.root / self.account.root.tois.name / "..").id, self.account.root.id) | |
508 | 548 | self.assertEqual((self.account.root / ".").id, self.account.root.id) |
509 | 549 | with self.assertRaises(ValueError) as e: |
510 | 550 | _ = self.account.root / ".." |
519 | 559 | |
520 | 560 | # Test normal navigation |
521 | 561 | self.assertEqual( |
522 | (self.account.root // "Top of Information Store" // self.account.calendar.name).id, self.account.calendar.id | |
562 | (self.account.root // self.account.root.tois.name // self.account.calendar.name).id, | |
563 | self.account.calendar.id, | |
523 | 564 | ) |
524 | 565 | self.assertIsNone(self.account.root._subfolders) |
525 | 566 | |
526 | 567 | # Test parent ('..') syntax. Should not work |
527 | 568 | with self.assertRaises(ValueError) as e: |
528 | _ = self.account.root // "Top of Information Store" // ".." | |
569 | _ = self.account.root // self.account.root.tois.name // ".." | |
529 | 570 | self.assertEqual(e.exception.args[0], "Cannot get parent without a folder cache") |
530 | 571 | self.assertIsNone(self.account.root._subfolders) |
531 | 572 |
332 | 332 | matches = qs.filter(**kw).count() |
333 | 333 | if matches == expected: |
334 | 334 | break |
335 | self.skipTest(f"Filter expression {kw} on complex field still failing after multiple retries") | |
335 | 336 | self.assertEqual(matches, expected, (f.name, val, kw, retries)) |
336 | 337 | |
337 | 338 | def test_filter_on_simple_fields(self): |
378 | 379 | for f in fields: |
379 | 380 | val = getattr(item, f.name) |
380 | 381 | # Filter multi-value fields with =, __in and __contains |
381 | filter_kwargs = [{f"{f.name}__in": val}, {f"{f.name}__contains": val}] | |
382 | # Does not work in O365 | |
383 | # filter_kwargs = [{f"{f.name}__in": val}, {f"{f.name}__contains": val}] | |
384 | filter_kwargs = [{f"{f.name}__in": val}] | |
382 | 385 | self._run_filter_tests(common_qs, f, filter_kwargs, val) |
383 | 386 | |
384 | 387 | def test_filter_on_single_field_index_fields(self): |
443 | 446 | |
444 | 447 | def test_text_field_settings(self): |
445 | 448 | # Test that the max_length and is_complex field settings are correctly set for text fields |
446 | item = self.get_test_item().save() | |
447 | 449 | for f in self.ITEM_CLASS.FIELDS: |
448 | 450 | with self.subTest(f=f): |
449 | 451 | if not f.supports_version(self.account.version): |
462 | 464 | if f.name == "categories": |
463 | 465 | # We're filtering on this one, so leave it alone |
464 | 466 | continue |
467 | item = self.get_test_item().save() | |
465 | 468 | old_max_length = getattr(f, "max_length", None) |
466 | 469 | old_is_complex = f.is_complex |
467 | 470 | try: |
496 | 499 | |
497 | 500 | # is_complex=False forces the query to use FindItems which will only get the short value |
498 | 501 | f.is_complex = False |
499 | new_short_item = self.test_folder.all().only(f.name).get(categories__contains=self.categories) | |
502 | new_short_item = { | |
503 | i.id: i | |
504 | for i in self.test_folder.all().only(f.name).filter(categories__contains=self.categories) | |
505 | }[item.id] | |
500 | 506 | new_short = getattr(new_short_item, f.name) |
501 | 507 | |
502 | 508 | if not old_is_complex: |
625 | 631 | if f.name == "mime_content": |
626 | 632 | # This will change depending on other contents fields |
627 | 633 | continue |
628 | old, new = getattr(item, f.name), insert_kwargs[f.name] | |
634 | old, new = insert_kwargs[f.name], getattr(item, f.name) | |
629 | 635 | if f.is_list: |
630 | 636 | old, new = set(old or ()), set(new or ()) |
631 | 637 | self.assertEqual(old, new, (f.name, old, new)) |
0 | 0 | import datetime |
1 | 1 | |
2 | from exchangelib.errors import ErrorInvalidOperation, ErrorItemNotFound, ErrorMissingInformationReferenceItemId | |
2 | from exchangelib.errors import ( | |
3 | ErrorInvalidOperation, | |
4 | ErrorInvalidRecipients, | |
5 | ErrorItemNotFound, | |
6 | ErrorMissingInformationReferenceItemId, | |
7 | ) | |
3 | 8 | from exchangelib.ewsdatetime import UTC |
4 | 9 | from exchangelib.fields import MONDAY, NOVEMBER, THIRD, WEDNESDAY, WEEK_DAY, WEEKEND_DAY |
5 | 10 | from exchangelib.folders import Calendar |
36 | 41 | |
37 | 42 | def test_cancel(self): |
38 | 43 | item = self.get_test_item().save() |
39 | res = item.cancel() # Returns (id, changekey) of cancelled item | |
40 | self.assertIsInstance(res, BulkCreateResult) | |
41 | with self.assertRaises(ErrorItemNotFound): | |
42 | # Item is already cancelled | |
43 | item.cancel() | |
44 | try: | |
45 | res = item.cancel() # Returns (id, changekey) of cancelled item | |
46 | except ErrorInvalidRecipients: | |
47 | # Does not always work in a single-account setup | |
48 | pass | |
49 | else: | |
50 | self.assertIsInstance(res, BulkCreateResult) | |
51 | with self.assertRaises(ErrorItemNotFound): | |
52 | # Item is already cancelled | |
53 | item.cancel() | |
44 | 54 | |
45 | 55 | def test_updating_timestamps(self): |
46 | 56 | # Test that we can update an item without changing anything, and maintain the hidden timezone fields as local |
531 | 531 | self.assertEqual(common_qs.filter(categories__contains=["TESTA"]).count(), 1) # Test case insensitivity |
532 | 532 | self.assertEqual(common_qs.filter(categories__contains=["testa"]).count(), 1) # Test case insensitivity |
533 | 533 | self.assertEqual(common_qs.filter(categories__contains=["TestA"]).count(), 1) # Partial |
534 | self.assertEqual(common_qs.filter(categories__contains=item.categories).count(), 1) # Exact match | |
534 | # Does not work in O365 | |
535 | # self.assertEqual(common_qs.filter(categories__contains=item.categories).count(), 1) # Exact match | |
535 | 536 | with self.assertRaises(TypeError): |
536 | 537 | common_qs.filter(categories__in="ci6xahH1").count() # Plain string is not supported |
537 | 538 | self.assertEqual(common_qs.filter(categories__in=["ci6xahH1"]).count(), 0) # Same, but as list |
186 | 186 | item.mark_as_junk(is_junk=True, move_item=False) |
187 | 187 | self.assertEqual(item.folder, self.test_folder) |
188 | 188 | self.assertEqual(self.test_folder.get(categories__contains=self.categories).id, item.id) |
189 | item.mark_as_junk(is_junk=True, move_item=True) | |
190 | self.assertEqual(item.folder, self.account.junk) | |
191 | self.assertEqual(self.account.junk.get(categories__contains=self.categories).id, item.id) | |
189 | # Does not work in O365 | |
190 | # item.mark_as_junk(is_junk=True, move_item=True) | |
191 | # self.assertEqual(item.folder, self.account.junk) | |
192 | # self.assertEqual(self.account.junk.get(categories__contains=self.categories).id, item.id) | |
192 | 193 | item.mark_as_junk(is_junk=False, move_item=True) |
193 | 194 | self.assertEqual(item.folder, self.account.inbox) |
194 | 195 | self.assertEqual(self.account.inbox.get(categories__contains=self.categories).id, item.id) |
317 | 317 | qs.mark_as_junk(is_junk=True, move_item=False) |
318 | 318 | self.assertEqual(self.test_folder.filter(categories__contains=self.categories).count(), 1) |
319 | 319 | qs.mark_as_junk(is_junk=True, move_item=True) |
320 | self.assertEqual(self.account.junk.filter(categories__contains=self.categories).count(), 1) | |
321 | self.account.junk.filter(categories__contains=self.categories).mark_as_junk(is_junk=False, move_item=True) | |
320 | # Does not work in O365 | |
321 | # self.assertEqual(self.account.junk.filter(categories__contains=self.categories).count(), 1) | |
322 | # self.account.junk.filter(categories__contains=self.categories).mark_as_junk(is_junk=False, move_item=True) | |
322 | 323 | self.assertEqual(self.account.inbox.filter(categories__contains=self.categories).count(), 1) |
323 | 324 | |
324 | 325 | def test_archive_via_queryset(self): |
2 | 2 | from exchangelib.errors import ErrorInvalidSubscription, ErrorSubscriptionNotFound, MalformedResponseError |
3 | 3 | from exchangelib.folders import FolderCollection, Inbox |
4 | 4 | from exchangelib.items import Message |
5 | from exchangelib.properties import CreatedEvent, DeletedEvent, ItemId, ModifiedEvent, Notification, StatusEvent | |
5 | from exchangelib.properties import ( | |
6 | CreatedEvent, | |
7 | DeletedEvent, | |
8 | ItemId, | |
9 | ModifiedEvent, | |
10 | MovedEvent, | |
11 | Notification, | |
12 | StatusEvent, | |
13 | ) | |
6 | 14 | from exchangelib.services import GetStreamingEvents, SendNotification, SubscribeToPull |
7 | 15 | from exchangelib.util import PrettyXmlHandler |
8 | 16 | |
200 | 208 | if item_id is None: |
201 | 209 | events.append(e) |
202 | 210 | continue |
203 | if e.event_type == event_cls.ITEM and e.item_id.id == item_id: | |
204 | events.append(e) | |
211 | if e.event_type == event_cls.ITEM: | |
212 | if isinstance(e, MovedEvent) and e.old_item_id.id == item_id: | |
213 | events.append(e) | |
214 | elif e.item_id.id == item_id: | |
215 | events.append(e) | |
205 | 216 | self.assertEqual(len(events), 1) |
206 | 217 | event = events[0] |
207 | 218 | self.assertIsInstance(event, event_cls) |
234 | 245 | i1.delete() |
235 | 246 | time.sleep(5) # For some reason, events do not trigger instantly |
236 | 247 | notifications = list(test_folder.get_events(subscription_id, watermark)) |
237 | deleted_event, watermark = self._filter_events(notifications, DeletedEvent, i1_id) | |
238 | self.assertEqual(deleted_event.item_id.id, i1_id) | |
248 | try: | |
249 | # On some servers, items are moved to the Recoverable Items on delete | |
250 | moved_event, watermark = self._filter_events(notifications, MovedEvent, i1_id) | |
251 | self.assertEqual(moved_event.old_item_id.id, i1_id) | |
252 | except AssertionError: | |
253 | deleted_event, watermark = self._filter_events(notifications, DeletedEvent, i1_id) | |
254 | self.assertEqual(deleted_event.item_id.id, i1_id) | |
239 | 255 | |
240 | 256 | def test_streaming_notifications(self): |
241 | 257 | # Test that we can create a streaming subscription, make changes and see the events by calling |
271 | 287 | notifications = list( |
272 | 288 | test_folder.get_streaming_events(subscription_id, connection_timeout=1, max_notifications_returned=1) |
273 | 289 | ) |
274 | deleted_event, _ = self._filter_events(notifications, DeletedEvent, i1_id) | |
275 | self.assertEqual(deleted_event.item_id.id, i1_id) | |
290 | try: | |
291 | # On some servers, items are moved to the Recoverable Items on delete | |
292 | moved_event, _ = self._filter_events(notifications, MovedEvent, i1_id) | |
293 | self.assertEqual(moved_event.old_item_id.id, i1_id) | |
294 | except AssertionError: | |
295 | deleted_event, _ = self._filter_events(notifications, DeletedEvent, i1_id) | |
296 | self.assertEqual(deleted_event.item_id.id, i1_id) | |
276 | 297 | |
277 | 298 | def test_streaming_with_other_calls(self): |
278 | 299 | # Test that we can call other EWS operations while we have a streaming subscription open |
404 | 425 | # Invalid status |
405 | 426 | ws.get_payload(status="XXX") |
406 | 427 | self.assertEqual( |
407 | PrettyXmlHandler.prettify_xml(ws.ok_payload()), | |
428 | PrettyXmlHandler().prettify_xml(ws.ok_payload()), | |
408 | 429 | b"""\ |
409 | 430 | <?xml version='1.0' encoding='utf-8'?> |
410 | 431 | <s:Envelope |
420 | 441 | """, |
421 | 442 | ) |
422 | 443 | self.assertEqual( |
423 | PrettyXmlHandler.prettify_xml(ws.unsubscribe_payload()), | |
444 | PrettyXmlHandler().prettify_xml(ws.unsubscribe_payload()), | |
424 | 445 | b"""\ |
425 | 446 | <?xml version='1.0' encoding='utf-8'?> |
426 | 447 | <s:Envelope |
1 | 1 | from itertools import chain |
2 | 2 | |
3 | 3 | from exchangelib.extended_properties import ExternId, Flag |
4 | from exchangelib.fields import InvalidField, InvalidFieldForVersion, TextField | |
4 | from exchangelib.fields import GenericEventListField, InvalidField, InvalidFieldForVersion, TextField, TypeValueField | |
5 | 5 | from exchangelib.folders import Folder, RootOfHierarchy |
6 | 6 | from exchangelib.indexed_properties import PhysicalAddress |
7 | 7 | from exchangelib.items import BulkCreateResult, Item |
59 | 59 | self.assertIn( |
60 | 60 | f.name, all_slots, f"Field name {f.name!r} is not in __slots__ on model {cls.__name__}" |
61 | 61 | ) |
62 | value_cls = f.value_cls # Make sure lazy imports work | |
63 | if not isinstance(f, (TypeValueField, GenericEventListField)): | |
64 | # All other fields must define a value type | |
65 | self.assertIsNotNone(value_cls) | |
62 | 66 | field_names.add(f.name) |
63 | 67 | # Finally, test that all models have a link to MSDN documentation |
64 | 68 | if issubclass(cls, Folder): |
19 | 19 | from exchangelib.credentials import Credentials, OAuth2AuthorizationCodeCredentials, OAuth2Credentials |
20 | 20 | from exchangelib.errors import ( |
21 | 21 | ErrorAccessDenied, |
22 | ErrorMailRecipientNotFound, | |
22 | 23 | ErrorNameResolutionNoResults, |
23 | 24 | RateLimitError, |
24 | 25 | SessionPoolMaxSizeReached, |
25 | 26 | SessionPoolMinSizeReached, |
26 | TimezoneDefinitionInvalidForYear, | |
27 | 27 | TransportError, |
28 | 28 | ) |
29 | 29 | from exchangelib.items import SEARCH_SCOPE_CHOICES, CalendarItem |
31 | 31 | EWS_ID, |
32 | 32 | ID_FORMATS, |
33 | 33 | AlternateId, |
34 | DaylightTime, | |
34 | 35 | DLMailbox, |
35 | 36 | FailedMailbox, |
36 | 37 | FreeBusyView, |
38 | 39 | ItemId, |
39 | 40 | Mailbox, |
40 | 41 | MailboxData, |
42 | Period, | |
41 | 43 | RoomList, |
42 | 44 | SearchableMailbox, |
45 | StandardTime, | |
43 | 46 | TimeZone, |
44 | 47 | ) |
45 | 48 | from exchangelib.protocol import BaseProtocol, FailFast, FaultTolerance, NoVerifyHTTPAdapter, Protocol |
48 | 51 | GetRoomLists, |
49 | 52 | GetRooms, |
50 | 53 | GetSearchableMailboxes, |
54 | GetServerTimeZones, | |
51 | 55 | ResolveNames, |
52 | 56 | SetUserOofSettings, |
53 | 57 | ) |
261 | 265 | for_year=2018, |
262 | 266 | ) |
263 | 267 | self.assertEqual(tz.bias, tz_definition.get_std_and_dst(for_year=2018)[2].bias_in_minutes) |
264 | except TimezoneDefinitionInvalidForYear: | |
268 | except ValueError: | |
265 | 269 | pass |
270 | ||
271 | def test_get_timezones_parsing(self): | |
272 | # Test static XML since it's non-standard | |
273 | xml = b"""\ | |
274 | <?xml version='1.0' encoding='utf-8'?> | |
275 | <soap:Envelope | |
276 | xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" | |
277 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
278 | xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | |
279 | <Header xmlns="http://schemas.xmlsoap.org/soap/envelope/"> | |
280 | <ServerVersionInfo | |
281 | xmlns="http://schemas.microsoft.com/exchange/services/2006/types" | |
282 | MajorVersion="14" | |
283 | MinorVersion="2" | |
284 | MajorBuildNumber="390" | |
285 | MinorBuildNumber="3" | |
286 | Version="Exchange2010_SP2"/> | |
287 | </Header> | |
288 | <soap:Body> | |
289 | <m:GetServerTimeZonesResponse | |
290 | xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" | |
291 | xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"> | |
292 | <m:ResponseMessages> | |
293 | <m:GetServerTimeZonesResponseMessage ResponseClass="Success"> | |
294 | <m:ResponseCode>NoError</m:ResponseCode> | |
295 | <m:TimeZoneDefinitions> | |
296 | <t:TimeZoneDefinition | |
297 | Id="W. Europe Standard Time" | |
298 | Name="(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"> | |
299 | <t:Periods> | |
300 | <t:Period Bias="-PT60M" Name="Standard" Id="std"/> | |
301 | <t:Period Bias="-PT120M" Name="Daylight" Id="dlt"/> | |
302 | </t:Periods> | |
303 | <t:TransitionsGroups> | |
304 | <t:TransitionsGroup Id="0"> | |
305 | <t:RecurringDayTransition> | |
306 | <t:To Kind="Period">std</t:To> | |
307 | <t:TimeOffset>PT180M</t:TimeOffset> | |
308 | <t:Month>10</t:Month> | |
309 | <t:DayOfWeek>Sunday</t:DayOfWeek> | |
310 | <t:Occurrence>-1</t:Occurrence> | |
311 | </t:RecurringDayTransition> | |
312 | <t:RecurringDayTransition> | |
313 | <t:To Kind="Period">dlt</t:To> | |
314 | <t:TimeOffset>PT120M</t:TimeOffset> | |
315 | <t:Month>3</t:Month> | |
316 | <t:DayOfWeek>Sunday</t:DayOfWeek> | |
317 | <t:Occurrence>-1</t:Occurrence> | |
318 | </t:RecurringDayTransition> | |
319 | </t:TransitionsGroup> | |
320 | </t:TransitionsGroups> | |
321 | <t:Transitions> | |
322 | <t:Transition> | |
323 | <t:To Kind="Group">0</t:To> | |
324 | </t:Transition> | |
325 | </t:Transitions> | |
326 | </t:TimeZoneDefinition> | |
327 | </m:TimeZoneDefinitions> | |
328 | </m:GetServerTimeZonesResponseMessage> | |
329 | </m:ResponseMessages> | |
330 | </m:GetServerTimeZonesResponse> | |
331 | </soap:Body> | |
332 | </soap:Envelope>""" | |
333 | ws = GetServerTimeZones(self.account.protocol) | |
334 | timezones = list(ws.parse(xml)) | |
335 | self.assertEqual(1, len(timezones)) | |
336 | (standard_transition, daylight_transition, standard_period) = timezones[0].get_std_and_dst(2022) | |
337 | self.assertEqual( | |
338 | standard_transition, | |
339 | StandardTime(bias=0, time=datetime.time(hour=3), occurrence=5, iso_month=10, weekday=7), | |
340 | ) | |
341 | self.assertEqual( | |
342 | daylight_transition, | |
343 | DaylightTime(bias=-60, time=datetime.time(hour=2), occurrence=5, iso_month=3, weekday=7), | |
344 | ) | |
345 | self.assertEqual( | |
346 | standard_period, | |
347 | Period(id="std", name="Standard", bias=datetime.timedelta(minutes=-60)), | |
348 | ) | |
266 | 349 | |
267 | 350 | def test_get_free_busy_info(self): |
268 | 351 | tz = self.account.default_timezone |
272 | 355 | accounts = [(self.account, "Organizer", False)] |
273 | 356 | |
274 | 357 | with self.assertRaises(TypeError) as e: |
275 | self.account.protocol.get_free_busy_info(accounts=[(123, "XXX", "XXX")], start=start, end=end) | |
358 | list(self.account.protocol.get_free_busy_info(accounts=[(123, "XXX", "XXX")], start=start, end=end)) | |
276 | 359 | self.assertEqual( |
277 | 360 | e.exception.args[0], "Field 'email' value 123 must be of type <class 'exchangelib.properties.Email'>" |
278 | 361 | ) |
279 | 362 | with self.assertRaises(ValueError) as e: |
280 | self.account.protocol.get_free_busy_info(accounts=[(self.account, "XXX", "XXX")], start=start, end=end) | |
363 | list( | |
364 | self.account.protocol.get_free_busy_info(accounts=[(self.account, "XXX", "XXX")], start=start, end=end) | |
365 | ) | |
281 | 366 | self.assertEqual( |
282 | 367 | e.exception.args[0], |
283 | 368 | f"Invalid choice 'XXX' for field 'attendee_type'. Valid choices are {sorted(MailboxData.ATTENDEE_TYPES)}", |
284 | 369 | ) |
285 | 370 | with self.assertRaises(TypeError) as e: |
286 | self.account.protocol.get_free_busy_info(accounts=[(self.account, "Organizer", "X")], start=start, end=end) | |
371 | list( | |
372 | self.account.protocol.get_free_busy_info( | |
373 | accounts=[(self.account, "Organizer", "X")], start=start, end=end | |
374 | ) | |
375 | ) | |
287 | 376 | self.assertEqual(e.exception.args[0], "Field 'exclude_conflicts' value 'X' must be of type <class 'bool'>") |
288 | 377 | with self.assertRaises(ValueError) as e: |
289 | self.account.protocol.get_free_busy_info(accounts=accounts, start=end, end=start) | |
378 | list(self.account.protocol.get_free_busy_info(accounts=accounts, start=end, end=start)) | |
290 | 379 | self.assertIn("'start' must be less than 'end'", e.exception.args[0]) |
291 | 380 | with self.assertRaises(TypeError) as e: |
292 | self.account.protocol.get_free_busy_info( | |
293 | accounts=accounts, start=start, end=end, merged_free_busy_interval="XXX" | |
381 | list( | |
382 | self.account.protocol.get_free_busy_info( | |
383 | accounts=accounts, start=start, end=end, merged_free_busy_interval="XXX" | |
384 | ) | |
294 | 385 | ) |
295 | 386 | self.assertEqual( |
296 | 387 | e.exception.args[0], "Field 'merged_free_busy_interval' value 'XXX' must be of type <class 'int'>" |
297 | 388 | ) |
298 | 389 | with self.assertRaises(ValueError) as e: |
299 | self.account.protocol.get_free_busy_info(accounts=accounts, start=start, end=end, requested_view="XXX") | |
390 | list( | |
391 | self.account.protocol.get_free_busy_info(accounts=accounts, start=start, end=end, requested_view="XXX") | |
392 | ) | |
300 | 393 | self.assertEqual( |
301 | 394 | e.exception.args[0], |
302 | 395 | f"Invalid choice 'XXX' for field 'requested_view'. Valid choices are " |
314 | 407 | accounts=[(self.account.primary_smtp_address, "Organizer", False)], start=start, end=end |
315 | 408 | ): |
316 | 409 | self.assertIsInstance(view_info, FreeBusyView) |
410 | ||
411 | # Test non-existing address | |
412 | for view_info in self.account.protocol.get_free_busy_info( | |
413 | accounts=[(f"unlikely-to-exist-{self.account.primary_smtp_address}", "Organizer", False)], | |
414 | start=start, | |
415 | end=end, | |
416 | ): | |
417 | self.assertIsInstance(view_info, ErrorMailRecipientNotFound) | |
418 | ||
419 | # Test +100 addresses | |
420 | for view_info in self.account.protocol.get_free_busy_info( | |
421 | accounts=[(f"unknown-{i}-{self.account.primary_smtp_address}", "Organizer", False) for i in range(101)], | |
422 | start=start, | |
423 | end=end, | |
424 | ): | |
425 | self.assertIsInstance(view_info, ErrorMailRecipientNotFound) | |
426 | ||
427 | # Test non-existing and existing address | |
428 | view_infos = list( | |
429 | self.account.protocol.get_free_busy_info( | |
430 | accounts=[ | |
431 | (f"unlikely-to-exist-{self.account.primary_smtp_address}", "Organizer", False), | |
432 | (self.account.primary_smtp_address, "Organizer", False), | |
433 | ], | |
434 | start=start, | |
435 | end=end, | |
436 | ) | |
437 | ) | |
438 | self.assertIsInstance(view_infos[0], ErrorMailRecipientNotFound) | |
439 | self.assertIsInstance(view_infos[1], FreeBusyView) | |
317 | 440 | |
318 | 441 | def test_get_roomlists(self): |
319 | 442 | # The test server is not guaranteed to have any room lists which makes this test less useful |
492 | 615 | ws.return_full_contact_data = False |
493 | 616 | self.assertSetEqual({m.email_address for m in ws.parse(xml)}, {"anne@example.com", "john@example.com"}) |
494 | 617 | |
618 | def test_resolvenames_warning(self): | |
619 | # Test warning that the returned candidate list is non-exchaustive | |
620 | xml = b"""\ | |
621 | <?xml version="1.0" encoding="utf-8"?> | |
622 | <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> | |
623 | <s:Body> | |
624 | <m:ResolveNamesResponse | |
625 | xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" | |
626 | xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> | |
627 | <m:ResponseMessages> | |
628 | <m:ResolveNamesResponseMessage ResponseClass="Warning"> | |
629 | <m:MessageText>Multiple results were found.</m:MessageText> | |
630 | <m:ResponseCode>ErrorNameResolutionMultipleResults</m:ResponseCode> | |
631 | <m:DescriptiveLinkKey>0</m:DescriptiveLinkKey> | |
632 | <m:ResolutionSet TotalItemsInView="2" IncludesLastItemInRange="false"> | |
633 | <t:Resolution> | |
634 | <t:Mailbox> | |
635 | <t:Name>John Doe</t:Name> | |
636 | <t:EmailAddress>anne@example.com</t:EmailAddress> | |
637 | <t:RoutingType>SMTP</t:RoutingType> | |
638 | <t:MailboxType>Mailbox</t:MailboxType> | |
639 | </t:Mailbox> | |
640 | </t:Resolution> | |
641 | <t:Resolution> | |
642 | <t:Mailbox> | |
643 | <t:Name>John Deer</t:Name> | |
644 | <t:EmailAddress>john@example.com</t:EmailAddress> | |
645 | <t:RoutingType>SMTP</t:RoutingType> | |
646 | <t:MailboxType>Mailbox</t:MailboxType> | |
647 | </t:Mailbox> | |
648 | </t:Resolution> | |
649 | </m:ResolutionSet> | |
650 | </m:ResolveNamesResponseMessage> | |
651 | </m:ResponseMessages> | |
652 | </m:ResolveNamesResponse> | |
653 | </s:Body> | |
654 | </s:Envelope>""" | |
655 | ws = ResolveNames(self.account.protocol) | |
656 | with warnings.catch_warnings(record=True) as w: | |
657 | warnings.simplefilter("always") | |
658 | list(ws.parse(xml)) | |
659 | self.assertEqual( | |
660 | str(w[0].message), | |
661 | "The ResolveNames service returns at most 100 candidates and does not support paging. You have reached " | |
662 | "this limit and have not received the exhaustive list of candidates.", | |
663 | ) | |
664 | ||
495 | 665 | def test_get_searchable_mailboxes(self): |
496 | 666 | # Insufficient privileges for the test account, so let's just test the exception |
497 | 667 | with self.assertRaises(ErrorAccessDenied): |
498 | 668 | self.account.protocol.get_searchable_mailboxes(search_filter="non_existent_distro@example.com") |
499 | 669 | with self.assertRaises(ErrorAccessDenied): |
500 | 670 | self.account.protocol.get_searchable_mailboxes(expand_group_membership=True) |
501 | ||
502 | xml = b"""\ | |
671 | guid = "33a408fe-2574-4e3b-49f5-5e1e000a3035" | |
672 | email = "LOLgroup@example.com" | |
673 | display_name = "LOLgroup" | |
674 | reference_id = "/o=First/ou=Exchange(FYLT)/cn=Recipients/cn=81213b958a0b5295b13b3f02b812bf1bc-LOLgroup" | |
675 | xml = f"""\ | |
503 | 676 | <?xml version="1.0" encoding="utf-8"?> |
504 | 677 | <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> |
505 | 678 | <s:Body xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" |
508 | 681 | <m:ResponseCode>NoError</m:ResponseCode> |
509 | 682 | <m:SearchableMailboxes> |
510 | 683 | <t:SearchableMailbox> |
511 | <t:Guid>33a408fe-2574-4e3b-49f5-5e1e000a3035</t:Guid> | |
512 | <t:PrimarySmtpAddress>LOLgroup@example.com</t:PrimarySmtpAddress> | |
684 | <t:Guid>{guid}</t:Guid> | |
685 | <t:PrimarySmtpAddress>{email}</t:PrimarySmtpAddress> | |
513 | 686 | <t:IsExternalMailbox>false</t:IsExternalMailbox> |
514 | 687 | <t:ExternalEmailAddress/> |
515 | <t:DisplayName>LOLgroup</t:DisplayName> | |
688 | <t:DisplayName>{display_name}</t:DisplayName> | |
516 | 689 | <t:IsMembershipGroup>true</t:IsMembershipGroup> |
517 | <t:ReferenceId>/o=First/ou=Exchange(FYLT)/cn=Recipients/cn=81213b958a0b5295b13b3f02b812bf1bc-LOLgroup</t:ReferenceId> | |
690 | <t:ReferenceId>{reference_id}</t:ReferenceId> | |
518 | 691 | </t:SearchableMailbox> |
519 | 692 | <t:FailedMailbox> |
520 | 693 | <t:Mailbox>FAILgroup@example.com</t:Mailbox> |
525 | 698 | </m:SearchableMailboxes> |
526 | 699 | </m:GetSearchableMailboxesResponse> |
527 | 700 | </s:Body> |
528 | </s:Envelope>""" | |
701 | </s:Envelope>""".encode() | |
529 | 702 | ws = GetSearchableMailboxes(protocol=self.account.protocol) |
530 | 703 | self.assertListEqual( |
531 | 704 | list(ws.parse(xml)), |
532 | 705 | [ |
533 | 706 | SearchableMailbox( |
534 | guid="33a408fe-2574-4e3b-49f5-5e1e000a3035", | |
535 | primary_smtp_address="LOLgroup@example.com", | |
707 | guid=guid, | |
708 | primary_smtp_address=email, | |
536 | 709 | is_external=False, |
537 | 710 | external_email=None, |
538 | display_name="LOLgroup", | |
711 | display_name=display_name, | |
539 | 712 | is_membership_group=True, |
540 | reference_id="/o=First/ou=Exchange(FYLT)/cn=Recipients/cn=81213b958a0b5295b13b3f02b812bf1bc-LOLgroup", | |
713 | reference_id=reference_id, | |
541 | 714 | ), |
542 | 715 | FailedMailbox( |
543 | 716 | mailbox="FAILgroup@example.com", |
680 | 853 | ).clean(version=None) |
681 | 854 | |
682 | 855 | def test_convert_id(self): |
683 | i = ( | |
684 | "AAMkADQyYzZmYmUxLTJiYjItNDg2Ny1iMzNjLTIzYWE1NDgxNmZhNABGAAAAAADUebQDarW2Q7G2Ji8hKofPBwAl9iKCsfCfSa9cmjh" | |
685 | "+JCrCAAPJcuhjAAB0l+JSKvzBRYP+FXGewReXAABj6DrMAAA=" | |
686 | ) | |
856 | i = self.account.root.id | |
687 | 857 | for fmt in ID_FORMATS: |
688 | 858 | res = list( |
689 | 859 | self.account.protocol.convert_ids( |
727 | 897 | self.assertEqual(ids.count(), len(items)) |
728 | 898 | |
729 | 899 | def test_disable_ssl_verification(self): |
900 | if isinstance(self.account.protocol.credentials, OAuth2Credentials): | |
901 | self.skipTest("OAuth authentication ony works with SSL verification enabled") | |
902 | ||
730 | 903 | # Test that we can make requests when SSL verification is turned off. I don't know how to mock TLS responses |
731 | 904 | if not self.verify_ssl: |
732 | 905 | # We can only run this test if we haven't already disabled TLS |
0 | from exchangelib.credentials import OAuth2Credentials | |
0 | 1 | from exchangelib.errors import ( |
1 | 2 | ErrorAccessDenied, |
2 | 3 | ErrorFolderNotFound, |
12 | 13 | class CommonTest(EWSTest): |
13 | 14 | def test_magic(self): |
14 | 15 | self.assertIn(self.account.protocol.version.api_version, str(self.account.protocol)) |
15 | self.assertIn(self.account.protocol.credentials.username, str(self.account.protocol.credentials)) | |
16 | if isinstance(self.account.protocol.credentials, OAuth2Credentials): | |
17 | self.assertIn(self.account.protocol.credentials.client_id, str(self.account.protocol.credentials)) | |
18 | else: | |
19 | self.assertIn(self.account.protocol.credentials.username, str(self.account.protocol.credentials)) | |
16 | 20 | self.assertIn(self.account.primary_smtp_address, str(self.account)) |
17 | 21 | self.assertIn(str(self.account.version.build.major_version), repr(self.account.version)) |
18 | 22 | for item in ( |
94 | 94 | account = MockAccount(access_type=DELEGATE, identity=None, default_timezone=MockTZ("XXX")) |
95 | 95 | wrapped = wrap(content=content, api_version=api_version, timezone=account.default_timezone) |
96 | 96 | self.assertEqual( |
97 | PrettyXmlHandler.prettify_xml(wrapped), | |
97 | PrettyXmlHandler().prettify_xml(wrapped), | |
98 | 98 | b"""<?xml version='1.0' encoding='utf-8'?> |
99 | 99 | <s:Envelope |
100 | 100 | xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" |
129 | 129 | timezone=account.default_timezone, |
130 | 130 | ) |
131 | 131 | self.assertEqual( |
132 | PrettyXmlHandler.prettify_xml(wrapped), | |
132 | PrettyXmlHandler().prettify_xml(wrapped), | |
133 | 133 | f"""<?xml version='1.0' encoding='utf-8'?> |
134 | 134 | <s:Envelope |
135 | 135 | xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" |