Last active
April 9, 2024 20:33
-
-
Save mvelazc0/9d6ec23139cd10c9481d356e01e660dc to your computer and use it in GitHub Desktop.
Read M365 emails using the Exchange Web Services API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
from xml.etree import ElementTree as ET | |
# https://github.com/3gstudent/Homework-of-Python/blob/master/ewsManage.py | |
# Authentication details | |
client_id = '' | |
client_secret = '' | |
tenant_id = '' | |
mailbox = '[email protected]' | |
# Acquire token (similar to the PowerShell script) | |
# Token request endpoint | |
token_url = f'https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token' | |
# Token request payload | |
data = { | |
'grant_type': 'client_credentials', | |
'client_id': client_id, | |
'client_secret': client_secret, | |
'scope': 'https://outlook.office365.com/.default' | |
} | |
# Requesting the token | |
response = requests.post(token_url, data=data) | |
access_token = response.json().get('access_token') | |
# Function to create SOAP request for FindItem | |
def create_find_item_soap_request(mailbox): | |
return f""" | |
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> | |
<soap:Header> | |
<t:RequestServerVersion Version="Exchange2013"/> | |
<t:ExchangeImpersonation> | |
<t:ConnectingSID> | |
<t:PrimarySmtpAddress>{mailbox}</t:PrimarySmtpAddress> | |
</t:ConnectingSID> | |
</t:ExchangeImpersonation> | |
</soap:Header> | |
<soap:Body> | |
<FindItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" | |
Traversal="Shallow"> | |
<ItemShape> | |
<t:BaseShape>IdOnly</t:BaseShape> | |
</ItemShape> | |
<ParentFolderIds> | |
<t:DistinguishedFolderId Id="inbox"/> | |
</ParentFolderIds> | |
</FindItem> | |
</soap:Body> | |
</soap:Envelope> | |
""" | |
# Function to create SOAP request for getting emails | |
def create_get_item_soap_request(item_id, mailbox): | |
return f""" | |
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> | |
<soap:Header> | |
<t:RequestServerVersion Version="Exchange2013"/> | |
<t:ExchangeImpersonation> | |
<t:ConnectingSID> | |
<t:PrimarySmtpAddress>{mailbox}</t:PrimarySmtpAddress> | |
</t:ConnectingSID> | |
</t:ExchangeImpersonation> | |
</soap:Header> | |
<soap:Body> | |
<GetItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> | |
<ItemShape> | |
<t:BaseShape>Default</t:BaseShape> | |
<t:BodyType>Text</t:BodyType> | |
</ItemShape> | |
<ItemIds> | |
<t:ItemId Id="{item_id}"/> | |
</ItemIds> | |
</GetItem> | |
</soap:Body> | |
</soap:Envelope> | |
""" | |
# EWS URL | |
ews_url = "https://outlook.office365.com/EWS/Exchange.asmx" | |
# Headers | |
headers = { | |
"Authorization": f"Bearer {access_token}", | |
"Content-Type": "text/xml; charset=utf-8" | |
} | |
# Step 1: FindItem request to get email IDs | |
find_item_request = create_find_item_soap_request(mailbox) | |
find_item_response = requests.post(ews_url, headers=headers, data=find_item_request) | |
find_item_root = ET.fromstring(find_item_response.content) | |
# Extract ItemIds from FindItem response (update based on actual XML structure) | |
item_ids = [] | |
for elem in find_item_root.findall('.//{http://schemas.microsoft.com/exchange/services/2006/types}ItemId'): | |
item_ids.append(elem.attrib['Id']) | |
# Step 2: GetItem requests to read emails | |
for item_id in item_ids: | |
get_item_request = create_get_item_soap_request(item_id, mailbox) | |
get_item_response = requests.post(ews_url, headers=headers, data=get_item_request) | |
get_item_root = ET.fromstring(get_item_response.content) | |
# Extract email details from GetItem response (update based on actual XML structure) | |
for message in get_item_root.findall('.//{http://schemas.microsoft.com/exchange/services/2006/types}Message'): | |
subject = message.find('{http://schemas.microsoft.com/exchange/services/2006/types}Subject').text | |
body = message.find('{http://schemas.microsoft.com/exchange/services/2006/types}Body').text | |
print(f"Subject: {subject}\nBody: {body}\n") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment