如何通过Python访问Microsoft Exchange账户并读取收件箱(非SMTP)
Hey there! Let's walk through the best ways to access your Microsoft Exchange inbox and read emails with Python, without touching SMTP at all:
1. Exchange Web Services (EWS) via exchangelib
EWS is a legacy but reliable API widely supported for both on-premises Exchange servers and older Microsoft 365 tenants. The exchangelib library wraps EWS in a clean, Pythonic interface—perfect for your core needs of accessing and reading inbox emails.
Steps to implement:
- First, install the library:
pip install exchangelib - Then connect to your account and fetch inbox content:
from exchangelib import Credentials, Account # Set up your account credentials credentials = Credentials( username='your_email@domain.com', password='your_password' # Use an app-specific password if MFA is enabled ) # Connect to the Exchange account (autodiscover handles endpoint detection) account = Account( primary_smtp_address='your_email@domain.com', credentials=credentials, autodiscover=True, access_type='delegate' ) # Access the inbox and pull the latest 10 emails inbox = account.inbox for item in inbox.all().order_by('-datetime_received')[:10]: print(f"Subject: {item.subject}") print(f"Received: {item.datetime_received}") print(f"Sender: {item.sender.name} <{item.sender.email_address}>") print(f"Body preview: {item.body_preview}\n")
Pros & Cons:
- Pros: Mature library with full Exchange feature access, works seamlessly with on-prem servers.
- Cons: Microsoft is phasing out EWS in favor of the Graph API, so long-term support isn't guaranteed.
2. Microsoft Graph API
This is Microsoft's modern, recommended approach for accessing Exchange (and all Microsoft 365 services). It's the future-proof choice if you're working with Microsoft 365 tenants.
Steps to implement:
- First, register an app in the Azure Portal to get authentication credentials (tenant ID, client ID, client secret). Grant the app the
Mail.Readpermission (delegated for user-specific access, application for service-level access). - Install required libraries:
pip install azure-identity msgraph-core - Example code to fetch inbox emails:
from azure.identity import ClientSecretCredential from msgraph_core import GraphClient # Configure authentication details tenant_id = 'your_tenant_id' client_id = 'your_client_id' client_secret = 'your_client_secret' credential = ClientSecretCredential(tenant_id, client_id, client_secret) client = GraphClient(credential=credential) # Fetch the latest 10 inbox messages with key fields response = client.get('/me/mailfolders/inbox/messages?$top=10&$select=subject,receivedDateTime,sender,bodyPreview') messages = response.json()['value'] for msg in messages: print(f"Subject: {msg['subject']}") print(f"Received: {msg['receivedDateTime']}") print(f"Sender: {msg['sender']['emailAddress']['name']} <{msg['sender']['emailAddress']['address']}>") print(f"Body preview: {msg['bodyPreview']}\n")
Note: For user-specific delegated access, replace ClientSecretCredential with UsernamePasswordCredential.
Pros & Cons:
- Pros: Fully supported by Microsoft, integrates with all modern 365 features, better security (MFA support, granular permissions).
- Cons: Requires Azure app registration upfront, which adds a bit of initial setup overhead.
3. IMAP Protocol
Exchange servers typically support IMAP, a standard protocol designed specifically for retrieving emails. This is a simpler option if you only need basic inbox access without advanced Exchange features.
Steps to implement:
- Use Python's built-in
imapliblibrary (or higher-level alternatives likepyzmail):import imaplib import email from email.header import decode_header # Connect to Exchange's IMAP server (adjust for on-prem setups) imap_server = imaplib.IMAP4_SSL('outlook.office365.com') imap_server.login('your_email@domain.com', 'your_password') # Select the inbox folder imap_server.select('INBOX') # Search for all emails and fetch the latest 10 status, messages = imap_server.search(None, 'ALL') email_ids = messages[0].split() for e_id in email_ids[-10:]: status, msg_data = imap_server.fetch(e_id, '(RFC822)') for response_part in msg_data: if isinstance(response_part, tuple): msg = email.message_from_bytes(response_part[1]) # Decode email subject subject, encoding = decode_header(msg['Subject'])[0] if isinstance(subject, bytes): subject = subject.decode(encoding) # Extract sender and body preview sender = msg['From'] if msg.is_multipart(): for part in msg.walk(): if part.get_content_type() == 'text/plain': body_preview = part.get_payload(decode=True).decode()[:200] + "..." break else: body_preview = msg.get_payload(decode=True).decode()[:200] + "..." print(f"Subject: {subject}") print(f"Sender: {sender}") print(f"Body preview: {body_preview}\n") # Log out of the server imap_server.logout()
Pros & Cons:
- Pros: No API registration needed, simple setup, works with most email server configurations.
- Cons: Limited to email retrieval (no access to calendars, contacts, or other Exchange features), may have restrictions on some on-prem Exchange deployments.
内容的提问来源于stack exchange,提问作者Shishir Lakkadi

