Comments (29)
To everyone hitting this bug: can you please test out 3ee351a? I believe it fixes the issue.
from exchangelib.
This is unrelated to the original issue. Please open a new issue instead.
from exchangelib.
Thanks for the report! Can you please post the code that leads to this error?
from exchangelib.
this is fragment of initialization code
exchange_config = Configuration(
auth_type=SSPI,
retry_policy=FaultTolerance(max_wait=3600),
server=config['exchnage_server']
)
accounts_names = config.get('accounts', [])
accounts = list([Account(
primary_smtp_address=account_name, config=exchange_config,
autodiscover=False, access_type=DELEGATE
) for account_name in accounts_names])
this is fragments telegram bot that interact with exchange
number, account_for_process = get_call_info(call) #get information for account and numbers of message to see
if account_for_process:
mails = list(account_for_process.inbox.all().order_by('-datetime_received')[:int(number)])
# for debug print to console
print(f"GET LAST {number} MAILS FOR ACCOUNT {account_for_process}")
if mails:
# for debug print to console
for mail in mails:
print(mail.id)
send_mail_info(bot, [call.message.chat.id], mails, account_for_process) #send mail info to telegram chart
for example a have [email protected] (this is my) and [email protected] (external account that I have access rights)
prior version 5.1 when I select account2 see mail from his inbox
but in version 5.1 when I select account2 see mail from account1 inbox
For debug I compare exchange message id, in version 5.1 is identical for account1 and account2
Test is code like this:
mail_account1 = list(account[0].inbox.all().order_by('-datetime_received')[-1])
mail_account2 = list(account[1].inbox.all().order_by('-datetime_received')[-1])
assert mail_account1.id != mail_account2.id, "Access to same inbox"
from exchangelib.
Thanks for the example!
I currently don't have a test setup with multiple accounts, so it's difficult for me to test. It may take me a while to get to. If you can do any debugging on your own, that would be most helpful. Thanks!
from exchangelib.
Hello,
I have basically the same Issue.
Prior to and including 5.0.3 it works fine, after 5.1.0 it doesnt work as expected.
I have access to 2 Mailboxes, a normal one and a shared one.
In 5.0.3 I can change between the mailboxes by changing the primary_smtp_address variable.
def makeAccount(smtp_adress):
account = Account(primary_smtp_address=smtp_adress, access_type=DELEGATE, config=config)
In 5.1.0 if I print(account)
it prints the correct shared mailbox adress, but it always connects as the normal one.
The root.tree()
is from the normal one and it sends emails as the normal one.
If i can be in any help diagnosing this or helping you just let me know.
from exchangelib.
I'm having the same issue. I've narrowed it down to this commit. Before that commit root.tree()
returns the (correct) shared mailbox folder structure. Afterwards it returns the (faulty) normal one.
May be somewhat related to this earlier bug?
If I can do some further tests, just let me know.
from exchangelib.
Same issue here. Makes 5.1 unusable.
from exchangelib.
Confirmed. I am seeing the same behavior. Rolled back to previous versions.
from exchangelib.
i've done some bisecting and seems to me commit 9d45d79 introduced this bug. maybe that helps @ecederstrand ?
from exchangelib.
Yeah, platinops found out as well in #1222 (comment)
It's a large commit and not obvious to me how that broke the functionality described in this issue. And I don't have easy access to a multi-account test setup where I can debug.
from exchangelib.
I tried but failed to reproduce this issue with a credential that has access to multiple accounts:
from exchangelib import (
OAuth2Credentials,
Account,
Configuration,
OAUTH2,
Identity,
Mailbox,
IMPERSONATION,
)
from exchangelib.folders import SingleFolderQuerySet, DistinguishedFolderId, Calendar
credentials = OAuth2Credentials(
client_id="XXX",
client_secret="YYY",
tenant_id="ZZZ",
identity=Identity(primary_smtp_address="[email protected]")
)
config = Configuration(server="outlook.office365.com", auth_type=OAUTH2, credentials=credentials)
accounts = "[email protected]", "[email protected]"
for email, shared_email in zip(accounts, reversed(accounts)):
a = Account(primary_smtp_address=email, access_type=IMPERSONATION, config=config, autodiscover=False)
print(a.primary_smtp_address, a.calendar.all().count(), a.calendar.all().order_by('-start')[0].id)
other_folder = DistinguishedFolderId(
id=Calendar.DISTINGUISHED_FOLDER_ID,
mailbox=Mailbox(email_address=shared_email)
)
c = SingleFolderQuerySet(account=a, folder=other_folder).resolve()
print(shared_email, c.all().count(), c.all().order_by('-start')[0].id)
This prints two different accounts, and two different counts and IDs. For SingleFolderQuerySet, it correctly prints the ID in the shared_email calendar. What am I missing?
from exchangelib.
no office365 here, on premise exchange installation: stripped down code:
credentials = Credentials('domain\userid', 'password')
config = Configuration(server='the.exchange.server.url', credentials=credentials)
account = Account(primary_smtp_address = '[email protected]', config = config, autodiscover = False, access_type = DELEGATE)
folder = account.inbox
print(folder.tree())
where the [email protected]
is not the personal mailbox of domain\userid
but a shared one. And: up to (and including 5.0.3) it worked and presented the inbox tree of desired-mailbox
, with 5.1.0 it shows the inbox of domain\userid
from exchangelib.
Very similar code as your code here, @ecederstrand. Except that we use access_type=DELEGATE instead of IMPERSONATION. It works with 5.0.3. We tried changing access_type to IMPERSONATION but then we get "exchangelib.errors.ErrorImpersonateUserDenied: The account does not have permission to impersonate the requested user."
from exchangelib.
Ok. I don't have a multi-account setup with DELEGATE access, unfortunately. You'll need to debug this on your own.
I would start by enabling debug logging (see https://ecederstrand.github.io/exchangelib/#troubleshooting) to check the difference between a successful 5.03 and a failing 5.1.0 request. Posting the differences here would be useful.
from exchangelib.
My setup is affected by the problem as well. We are running an on premise Exchange server. I did the following test to compare the differences between version 5.0.3 and 5.1.0.
import exchangelib
import logging
logging.basicConfig(level = logging.DEBUG, handlers = [exchangelib.PrettyXmlHandler()])
logging.getLogger().setLevel(logging.DEBUG)
creds = exchangelib.Credentials(username = 'username', password = 'password')
config = exchangelib.Configuration(service_endpoint = 'https://server.domain/EWS/Exchange.asmx', credentials = creds, version = exchangelib.Version(build = exchangelib.Build(15, 2, 0, 0)))
account = exchangelib.Account(primary_smtp_address = 'mail@domain', autodiscover = False, config = config, access_type = exchangelib.DELEGATE)
account.identity.upn = 'upn@domain'
list(account.calendar.all())
The working version 5.0.3 resulted in the following output.
DEBUG "Starting new HTTPS connection (1): server.domain:443"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "Starting new HTTPS connection (1): server.domain:443"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "NTLM step input: "
DEBUG "NTLM step output: REDACTED"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "NTLM step input: REDACTED"
DEBUG "NTLM step output: REDACTED"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 500 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
The non-working version 5.1.0. resulted in the following output.
DEBUG "Starting new HTTPS connection (1): server.domain:443"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "Starting new HTTPS connection (1): server.domain:443"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "NTLM step input: "
DEBUG "NTLM step output: REDACTED"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 401 0"
DEBUG "NTLM step input: REDACTED"
DEBUG "NTLM step output: REDACTED"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
DEBUG "https://server.domain:443 "POST /EWS/Exchange.asmx HTTP/1.1" 200 None"
Two requests are missing. Is there a possibility to trace the requests in more detail?
But maybe this information is already enough to isolate the point in 9d45d79 where a necessary request is skipped.
from exchangelib.
There must be more logging output than that. PrettyXmlHandler prints out the full XML request and response documents, colored and pretty-printed even. Did you perhaps log to a file or filter the log output somehow?
There's a lot going on in the pinpointed commit, and it's not clear what caused the regression. It also contains necessary fixes for other issues, so we can't just roll it back.
from exchangelib.
just tried it - goal is to do a print(folder.tree()) (see code above: #1222 (comment))
bug-test-error is the erroneous log, bug-test-ok.log the one which behaves as expected.
the only difference is the bug-test-ok was on exchangelib 5.0.3, bug-test-error with exchangelib 5.1.0
maybe it helps you - I would be glad if i can help to track down the problem
bug-test-error.log
bug-test-ok.log
from exchangelib.
Hi,
simple solution, we have to use DistinguishedFolderId as @ecederstrand showed us in his example
from exchangelib import ( OAuth2Credentials, Account, Configuration, OAUTH2, Identity, Mailbox, IMPERSONATION, ) from exchangelib.folders import SingleFolderQuerySet, DistinguishedFolderId, Calendar credentials = OAuth2Credentials( client_id="XXX", client_secret="YYY", tenant_id="ZZZ", identity=Identity(primary_smtp_address="[email protected]") ) config = Configuration(server="outlook.office365.com", auth_type=OAUTH2, credentials=credentials) accounts = "[email protected]", "[email protected]" for email, shared_email in zip(accounts, reversed(accounts)): a = Account(primary_smtp_address=email, access_type=IMPERSONATION, config=config, autodiscover=False) print(a.primary_smtp_address, a.calendar.all().count(), a.calendar.all().order_by('-start')[0].id) other_folder = DistinguishedFolderId( id=Calendar.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=shared_email) ) c = SingleFolderQuerySet(account=a, folder=other_folder).resolve() print(shared_email, c.all().count(), c.all().order_by('-start')[0].id)This prints two different accounts, and two different counts and IDs. For SingleFolderQuerySet, it correctly prints the ID in the shared_email calendar. What am I missing?
you can also take a look at this comment:
#1254 (comment)
and this issue:
#1202
BR
Takalele
from exchangelib.
simple solution, we have to use DistinguishedFolderId as @ecederstrand showed us in his example
This example solves a different problem. There are two distinct ways to access a foreign mailbox:
- Impersonation
- Delegate access
Impersonation requires a user who has a special role assignment to be able to access all mailboxes of the organization acting as the user the mailbox belongs to. There is no further permission check. This is, that your code refers to. If the accessing user (A) for example will create a calendar item in a foreign mailbox F on behalf of the use F, the organizer of this calendar item will be F.
When performing delegate access, the accessing user A needs access permission for the foreign mailbox F, but it accesses F acting under it's own identity A. This is what this issue refers to.
You can even combine the two approaches to access a mailbox M, shared with user U using the credentials of the impersonating user I.
Unfortunately the distinguished folder approach doesn't work with delegate access.
from exchangelib.
Unfortunately the distinguished folder approach doesn't work with delegate access.
for me it works, i tested contacts with write, read and delete as you can see in the comment i mention above:
from exchangelib.
@baloo66 Your bug-test-ok.log ends with a stack trace right when it gets interesting:
Traceback (most recent call last):
File "C:\workit\Python\cert-tracking\bug-test.py", line 22, in <module>
print(folder.tree())
File "C:\Users\userid\AppData\Local\Programs\Python\Python310\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 13-15: character maps to <undefined>
DEBUG:exchangelib.protocol:Server the.exchange.server.url: Closing sessions
Can you provide a new log file from a successful run?
from exchangelib.
I'd still like to fix this, but I'll need the requested debug info from someone, or access to a server with delegate access between two accounts.
from exchangelib.
Hi Erik,
See logs below - hope this may help somehow.
exchangelib_5.0.3_20240105-125334.log
[email protected] 1492 AAMkADA4MDI2MzFlLTE3NWQtNGVmOC1iNDdmLWY1MmFiZTliZWQzNgBGAAAAAABG0Gu6gfdVTbF/Y4esqfBfBwA3JihwWhSiRZcyeq/ZL3eiAAAAieCyAACm7+ifw6dbS7o9J46MA/UVAASImNK6AAA=
2024-01-05 13:53:34.955 | DEBUG | productiontools | test_exchangelib |
[email protected] 3 AAMkADEzNTdmN2NhLWU1YmMtNGU2OC1hYjA3LTVjMjg1OTIwYzFkMwBGAAAAAADH8dnHbvUTQZmIv1CeJwjkBwBBqX592Au9R7r5jZ1twiMIAAAAkZZBAABOq58edH4mToxueqYeGIkxAAT7XX4/AAA=
exchangelib_5.1.0_20240105-125402.log
[email protected] 1492 AAMkADA4MDI2MzFlLTE3NWQtNGVmOC1iNDdmLWY1MmFiZTliZWQzNgBGAAAAAABG0Gu6gfdVTbF/Y4esqfBfBwA3JihwWhSiRZcyeq/ZL3eiAAAAieCyAACm7+ifw6dbS7o9J46MA/UVAASImNK6AAA=
2024-01-05 13:54:03.718 | DEBUG | productiontools | test_exchangelib |
[email protected] 1492 AAMkADA4MDI2MzFlLTE3NWQtNGVmOC1iNDdmLWY1MmFiZTliZWQzNgBGAAAAAABG0Gu6gfdVTbF/Y4esqfBfBwA3JihwWhSiRZcyeq/ZL3eiAAAAieCyAACm7+ifw6dbS7o9J46MA/UVAASImNK6AAA=
Code I ran:
import exchangelib as el
import logging
DATETIME_FORMAT = "%Y%m%d-%H%M%S"
file_path = f"exchangelib_{el.__version__}_{dt.datetime.utcnow().strftime(DATETIME_FORMAT)}.log"
file_handler = logging.FileHandler(file_path)
# xml_handler = el.util.PrettyXmlHandler()
logging.basicConfig(level=logging.DEBUG, handlers=[file_handler])
logging.getLogger().setLevel(logging.DEBUG)
credentials = el.Credentials(username=username, password=password)
config = el.Configuration(server=server, credentials=credentials)
for email_address in [email_address_personal, email_address_shared]:
logger.debug(f"========={email_address}=========")
account = el.Account(
primary_smtp_address=email_address,
autodiscover=False,
config=config,
access_type=el.DELEGATE,
)
print(
account.primary_smtp_address,
account.calendar.all().count(),
account.calendar.all().order_by("-start")[0].id,
)
with open(file_path, "r") as file:
text = file.read()
text = text.replace(email_address_personal, "[email protected]")
text = text.replace(email_address_shared, "[email protected]")
text = text.replace(domain, "domain.com")
with open(file_path, "w") as file:
file.write(text)
from exchangelib.
Yes it solves the issue 👍 (for me at least). Thanks a lot !
from exchangelib.
Yes,I had the same problem with acessing external accounts and this commit also works on our System. 👍
from exchangelib.
Also fixed here, thanks!
from exchangelib.
Cool! I'm closing the issue and will release a new version in the next days.
from exchangelib.
For me it seems there is still an issue left. Now the target mailbox instead of the account holders mailbox is accessed. So the original issue is resolved. But now I get an ErrorAccessDenied
execption.
The following code ...
import exchangelib
creds = exchangelib.Credentials(username = 'username', password = 'password')
config = exchangelib.Configuration(service_endpoint = 'https://server.domain/EWS/Exchange.asmx', credentials = creds, version = exchangelib.Version(build = exchangelib.Build(15, 2, 0, 0)))
account = exchangelib.Account(primary_smtp_address = 'mail@domain', autodiscover = False, config = config, access_type = exchangelib.DELEGATE)
account.identity.upn = 'upn@domain'
list(account.calendar.all())
... yields
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/cached_property.py:70, in threaded_cached_property.__get__(self, obj, cls)
68 try:
69 # check if the value was computed before the lock was acquired
---> 70 return obj_dict[name]
72 except KeyError:
73 # if not, do the calculation and release the lock
KeyError: 'calendar'
During handling of the above exception, another exception occurred:
KeyError Traceback (most recent call last)
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/cached_property.py:70, in threaded_cached_property.__get__(self, obj, cls)
68 try:
69 # check if the value was computed before the lock was acquired
---> 70 return obj_dict[name]
72 except KeyError:
73 # if not, do the calculation and release the lock
KeyError: 'root'
During handling of the above exception, another exception occurred:
ErrorAccessDenied Traceback (most recent call last)
Cell In[1], line 9
6 account = exchangelib.Account(primary_smtp_address = 'mail@domain', autodiscover = False, config = config, access_type = exchangelib.DELEGATE)
7 account.identity.upn = 'upn@domain'
----> 9 list(account.calendar.all())
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/cached_property.py:74, in threaded_cached_property.__get__(self, obj, cls)
70 return obj_dict[name]
72 except KeyError:
73 # if not, do the calculation and release the lock
---> 74 return obj_dict.setdefault(name, self.func(obj))
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/account.py:254, in Account.calendar(self)
248 @threaded_cached_property
249 def calendar(self):
250 # If the account contains a shared calendar from a different user, that calendar will be in the folder list.
251 # Attempt not to return one of those. An account may not always have a calendar called "Calendar", but a
252 # Calendar folder with a localized name instead. Return that, if it's available, but always prefer any
253 # distinguished folder returned by the server.
--> 254 return self.root.get_default_folder(Calendar)
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/cached_property.py:74, in threaded_cached_property.__get__(self, obj, cls)
70 return obj_dict[name]
72 except KeyError:
73 # if not, do the calculation and release the lock
---> 74 return obj_dict.setdefault(name, self.func(obj))
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/account.py:350, in Account.root(self)
348 @threaded_cached_property
349 def root(self):
--> 350 return Root.get_distinguished(account=self)
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/folders/roots.py:113, in RootOfHierarchy.get_distinguished(cls, account)
111 raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value")
112 try:
--> 113 return cls.resolve(
114 account=account,
115 folder=DistinguishedFolderId(
116 id=cls.DISTINGUISHED_FOLDER_ID,
117 mailbox=Mailbox(email_address=account.primary_smtp_address),
118 ),
119 )
120 except MISSING_FOLDER_ERRORS:
121 raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}")
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/folders/base.py:516, in BaseFolder.resolve(cls, account, folder)
513 @classmethod
514 def resolve(cls, account, folder):
515 # Resolve a single folder
--> 516 folders = list(FolderCollection(account=account, folders=[folder]).resolve())
517 if not folders:
518 raise ErrorFolderNotFound(f"Could not find folder {folder!r}")
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/folders/collections.py:335, in FolderCollection.resolve(self)
333 # Fetch all properties for the remaining folders of folder IDs
334 additional_fields = self.get_folder_fields(target_cls=self._get_target_cls())
--> 335 yield from self.__class__(account=self.account, folders=resolveable_folders).get_folders(
336 additional_fields=additional_fields
337 )
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/folders/collections.py:403, in FolderCollection.get_folders(self, additional_fields)
398 # Add required fields
399 additional_fields.update(
400 (FieldPath(field=BaseFolder.get_field_by_fieldname(f)) for f in self.REQUIRED_FOLDER_FIELDS)
401 )
--> 403 yield from GetFolder(account=self.account).call(
404 folders=self.folders,
405 additional_fields=additional_fields,
406 shape=ID_ONLY,
407 )
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/services/get_folder.py:43, in GetFolder._elems_to_objs(self, elems)
42 def _elems_to_objs(self, elems):
---> 43 for folder, elem in zip(self.folders, elems):
44 if isinstance(elem, Exception):
45 yield elem
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/services/common.py:287, in EWSService._chunked_get_elements(self, payload_func, items, **kwargs)
285 for i, chunk in enumerate(chunkify(filtered_items, self.chunk_size), start=1):
286 log.debug("Processing chunk %s containing %s items", i, len(chunk))
--> 287 yield from self._get_elements(payload=payload_func(chunk, **kwargs))
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/services/common.py:308, in EWSService._get_elements(self, payload)
304 while True:
305 try:
306 # Create a generator over the response elements so exceptions in response elements are also raised
307 # here and can be handled.
--> 308 yield from self._response_generator(payload=payload)
309 # TODO: Restore session pool size on succeeding request?
310 return
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/services/common.py:684, in EWSService._get_elements_in_response(self, response)
659 """Take a list of 'SomeServiceResponseMessage' elements and return the elements in each response message that
660 we want the service to return. With e.g. 'CreateItem', we get a list of 'CreateItemResponseMessage' elements
661 and return the 'Message' elements.
(...)
681 :return: a generator of items as returned by '_get_elements_in_container()
682 """
683 for msg in response:
--> 684 container_or_exc = self._get_element_container(message=msg, name=self.element_container_name)
685 if isinstance(container_or_exc, (bool, Exception)):
686 yield container_or_exc
File ~/virtenv/msxcalendar/lib/python3.11/site-packages/exchangelib/services/common.py:606, in EWSService._get_element_container(self, message, name)
604 # response_class == 'Error', or 'Success' and not 'NoError'
605 try:
--> 606 raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml)
607 except self.ERRORS_TO_CATCH_IN_RESPONSE as e:
608 return e
ErrorAccessDenied: Der Zugriff wird verweigert. Überprüfen Sie die Anmeldeinformationen, und versuchen Sie es dann erneut., Der zugrunde liegende MAPI-Stream hat eine Ausnahme ausgelöst
The user has permission to the calendar folder of the mailbox, but not to the root folder. For some reason the code tries to access the root folder (which is not necessary) and fails there. In 5.0.0 it worked fine. How can I help debugging this issue?
from exchangelib.
Related Issues (20)
- Problem when access delegate inbox. HOT 1
- Incorrect "field_uri" in BaseFolder._distinguished_id HOT 1
- error in function to_xml in fields.AppointmentStateField HOT 7
- Error creating inbox rules HOT 4
- Multiple Email address inbox Stream subscription HOT 1
- Unnable to access shared calendar without permission on the mailbox root folder HOT 6
- Error in conver rule from xml
- Typo in Exchange 2019 version HOT 1
- Can't browse public_folders_root anymore HOT 32
- exchangelib.errors.ErrorAccessDenied: Not allowed to access Non IPM folder. HOT 23
- Can junk mail rules be created by exchangelib? HOT 1
- Validation rule error when manage inbox rules HOT 3
- `folder.parts` no longer returns root of hierarchy in list of parts (5.2.1) HOT 9
- `ErrorNonExistentMailbox` in version 5.2.1 but not in 5.2.0 HOT 6
- exchangelib.errors.UnauthorizedError: Invalid credentials for https://[domain].de/EWS/Exchange.asmx HOT 6
- Create calendar appointment in another account as access data, the appointment is created in the access account. HOT 3
- Get all Public Folders HOT 23
- ErrorInvalidSchemaVersionForMailboxVersion with exchangelib v5.2.1 and Exchange server version 15.2.1544.4 HOT 45
- EOF occurred in violation of protocol HOT 4
- ValueError trying to delete a rule HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from exchangelib.