User Profile
GarbledSpaceman
Copper Contributor
Joined 4 years ago
User Widgets
Recent Discussions
What OAuth permissions needed for exchangelib?
My end goal is to have a script that moves a single users mail around (archiving stuff etc.). Right now I'm just trying to be able to look at the mail. I'm using a python library called exchangelib. However, I can't seem to get the permissions right. Here's the code I'm using from exchangelib import ( Account, Configuration, OAuth2Credentials, DELEGATE, OAUTH2, ) from os import environ username = environ["USERNAME"] client_id = environ["CLIENT_ID"] tenant_id = environ["TENANT_ID"] secret_value = environ["VALUE"] credentials = OAuth2Credentials( client_id=client_id, tenant_id=tenant_id, client_secret=secret_value ) conf = Configuration( credentials=credentials, server="outlook.office365.com", auth_type=OAUTH2 ) account = Account( primary_smtp_address=username, autodiscover=False, config=conf, access_type=DELEGATE, ) And here's what the permissions look like in AzureAD And here's the error Traceback (most recent call last): File "test.py", line 21, in <module> account = Account( File ".../account.py", line 133, in __init__ self.version = self.protocol.version File ".../protocol.py", line 470, in version self.config.version = Version.guess(self, api_version_hint=self._api_version_hint) File ".../version.py", line 229, in guess list(ResolveNames(protocol=protocol).call(unresolved_entries=[name])) File ".../services/resolve_names.py", line 52, in _elems_to_objs for elem in elems: File ".../services/common.py", line 212, in _chunked_get_elements yield from self._get_elements(payload=payload_func(chunk, **kwargs)) File ".../services/common.py", line 230, in _get_elements yield from self._response_generator(payload=payload) File ".../services/common.py", line 196, in _response_generator response = self._get_response_xml(payload=payload) File ".../services/common.py", line 310, in _get_response_xml r = self._get_response(payload=payload, api_version=api_version) File ".../services/common.py", line 265, in _get_response r, session = post_ratelimited( File ".../util.py", line 877, in post_ratelimited protocol.retry_policy.raise_response_errors(r) # Always raises an exception File ".../protocol.py", line 689, in raise_response_errors raise UnauthorizedError('Invalid credentials for %s' % response.url) exchangelib.errors.UnauthorizedError: Invalid credentials for https://outlook.office365.com/EWS/Exchange.asmx By the way I've looked into a bunch of different methods of moving email but I'm dealing with a few hundred thousand emails and nothing else will do it in a reasonable time (except IMAP but... its IMAP). Specifically: The web interface doesn't allow selecting and moving more than like 100 emails The outlook desktop app wont move more than about 1000 emails at a time without the move crashing. For some reason using the addon interface with C# was also unstable (I got a test to complete once but it failed like 6 times with no exceptions or anything) The powershell command line thing that you connect to with like Connect-ExchangeOnline doesn't allow you to move individual emails. Microsoft Graph rate limits you at 10,000 email moves per day.
Groups
Recent Blog Articles
No content to show