I need to write a python script which checks for incoming e-mail in a shared mailbox hosted on office 365.
I have used python exchangelib 4.7.3:
Code
#!/usr/bin/env python3
import logging
from exchangelib import Credentials, Account, Configuration, DELEGATE
def list_mails():
credentials = Credentials('user@company.com', 'SecretPassword')
config = Configuration(server='outlook.office365.com', credentials=credentials)
account = Account(primary_smtp_address='sharedmailbox@company.com', config=config, autodiscover=False, access_type=DELEGATE)
for item in account.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.datetime_received)
def main():
list_mails()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
main()
Issue
Regardless of the different tries, the following error is showing up:
DEBUG:exchangelib.protocol:No retry: no fail-fast policy
DEBUG:exchangelib.protocol:Server outlook.office365.com: Retiring session 87355
DEBUG:exchangelib.protocol:Server outlook.office365.com: Created session 82489
DEBUG:exchangelib.protocol:Server outlook.office365.com: Releasing session 82489
Traceback (most recent call last):
File "/Users/test/Code/./orderalert.py", line 24, in <module>
main()
File "/Users/test/Code/./orderalert.py", line 20, in main
list_mails()
File "/Userstest/Code/./orderalert.py", line 11, in list_mails
account = Account(primary_smtp_address='sharedmailbox@company.com', config=config, autodiscover=False, access_type=DELEGATE)
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/account.py", line 204, in __init__
self.version = self.protocol.version.copy()
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/protocol.py", line 483, in version
self.config.version = Version.guess(self, api_version_hint=self._api_version_hint)
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/version.py", line 233, in guess
list(ResolveNames(protocol=protocol).call(unresolved_entries=[name]))
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 187, in _elems_to_objs
for elem in elems:
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 245, in _chunked_get_elements
yield from self._get_elements(payload=payload_func(chunk, **kwargs))
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 265, in _get_elements
yield from self._response_generator(payload=payload)
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 227, in _response_generator
response = self._get_response_xml(payload=payload)
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 343, in _get_response_xml
r = self._get_response(payload=payload, api_version=api_version)
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/services/common.py", line 297, in _get_response
r, session = post_ratelimited(
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/util.py", line 917, in post_ratelimited
protocol.retry_policy.raise_response_errors(r) # Always raises an exception
File "/opt/homebrew/lib/python3.9/site-packages/exchangelib/protocol.py", line 688, in raise_response_errors
raise UnauthorizedError(f"Invalid credentials for {response.url}")
exchangelib.errors.UnauthorizedError: Invalid credentials for https://outlook.office365.com/EWS/Exchange.asmx
DEBUG:exchangelib.protocol:Server outlook.office365.com: Closing sessions
Tried solutions (no luck with them)
- The user@company.com credentials are valid, I can log myself in the web interface (no MFA or other enforced)
- I have tried the auto discovery:
account = Account('sharedmailbox@company.com', credentials=credentials, autodiscover=True, access_type=DELEGATE)
- Disable TLS Validation when connecting
- As suggested added a "on" subdomain on on.company.com for the emails addresses.
- Tested the overall setup for autodiscovery on testconnectivity.microsoft.com
- On the Office 365 Azure AD admin web interface, I can see a successful login performed by the script.