Microsoft Graph API Email: Send, Read and Sync (2026 Guide)

Microsoft Graph API

Microsoft Graph API Email: Complete Integration Guide for Developers (2026)

18 min read 17 Apr 2026 Python / Node.js / REST

The Microsoft Graph API is the unified REST endpoint for accessing Outlook and Exchange email data: read, send, search, and receive webhooks for every mailbox event. This guide walks you through OAuth 2.0 setup, live code examples, rate limits, and how to unify Microsoft Graph with Gmail and IMAP under a single SDK.

Microsoft Graph API OAuth 2.0 Outlook Email MSAL Webhooks
read_outlook_emails.py
import requests # Unipile Unified Email API # Reads Outlook emails via Microsoft Graph BASE = "https://api.unipile.com:13465/api/v1" HEADERS = { "X-API-KEY": "YOUR_ACCESS_TOKEN", "Accept": "application/json" } def get_outlook_emails(account_id, limit=20): r = requests.get( f"{BASE}/emails", headers=HEADERS, params={ "account_id": account_id, "limit": limit } ) return r.json()["emails"] emails = get_outlook_emails("acc_outlook_123") for e in emails: print(e["subject"], e["from"])
20 emails fetched from Outlook - via Microsoft Graph
Works with: Outlook logo Gmail logo IMAP logo
Building an email integration?

Read our Complete Email API Guide - OAuth flows, sync, send, and provider comparison.

Definition

What Is the Microsoft Graph API for Email?

The Microsoft Graph API is the unified REST gateway for all Microsoft 365 services, including email, calendar, contacts, and files. For email specifically, it exposes the /v1.0/me/messages endpoint, giving developers programmatic access to every Outlook and Exchange mailbox. It replaced legacy protocols (Basic Auth, EWS) and is now the only officially supported way to access Outlook email programmatically using OAuth 2.0.

Developer definition

The Microsoft Graph API for email is the RESTful interface exposing Microsoft 365 mailbox data - including messages, folders, attachments, and mailbox settings - under the https://graph.microsoft.com/v1.0/me/messages endpoint. It authenticates through Azure Active Directory OAuth 2.0, supports delegated and application permissions, and enables real-time events via change notification subscriptions (webhooks). It is the recommended replacement for all deprecated Basic Authentication flows.

Microsoft Graph API is the recommended replacement for deprecated Basic Authentication - all Outlook and Exchange email access now requires OAuth 2.0 via Graph. Basic Auth was fully retired in October 2022.

Criterion Microsoft Graph API Direct SMTP / IMAP
Authentication OAuth 2.0 (MSAL) Username + password (deprecated)
Rate limits 10,000 requests / 10 min per app No standard limit (server-dependent)
Features Full: read, send, search, webhooks, folders Limited: basic send/receive only
Complexity OAuth flow + Azure App Registration Low setup, high maintenance
Unipile support Native - no OAuth flow needed Native - IMAP fallback
Advantages

Why Use Microsoft Graph API for Email Integration?

Building on Microsoft Graph gives your application secure, token-based access to the world's largest enterprise email ecosystem - over 400 million Outlook and Exchange mailboxes. Here are the four core reasons developers choose the microsoft graph api email endpoint.

Unified OAuth 2.0 Authentication

One Azure App Registration covers all Outlook, Exchange, and Microsoft 365 mailboxes. Delegated permissions let users consent once; application permissions enable unattended server-side access without any user interaction.

Full Mailbox Access

Read, send, reply, move, and delete messages. Manage folders, search the entire mailbox, handle attachments, and set mail rules - all via the same REST interface with a predictable JSON response schema.

Real-Time Webhooks

Subscribe to mailbox change notifications and receive an HTTP POST to your endpoint whenever a new email arrives, a message is read, or a folder changes. No polling, no delays - events delivered in near real time.

Exchange, Outlook, and M365 Support

A single API endpoint covers personal Outlook accounts, business Microsoft 365 tenants, and on-premises Exchange servers (via hybrid). One integration handles the entire Microsoft email ecosystem without separate code paths.

Setting Up Microsoft OAuth for Outlook API - Unipile

Setting Up Microsoft OAuth for Outlook API

Microsoft OAuth Docs

By default, your integration uses Unipile's OAuth credentials. To get a full white-label experience when end users connect their Microsoft account, create your own app in Microsoft Entra ID. Follow the 7 steps below to register your app, configure permissions, and connect it to Unipile.

1
2
3
4
5
6
7
01

Create a Microsoft Entra ID Account

If you don't already have one, create a free Microsoft Entra ID account (previously Azure Active Directory). This is the admin portal where you will register your OAuth application.

02

Register a New App in Azure Portal

Log in to portal.azure.com, go to Microsoft Entra ID, and click New registration.

  • Name your app: this name will be visible to your end users during the OAuth consent screen.
  • Supported account types: select "Accounts in any organizational directory (Any Microsoft Entra ID, Multitenant) and personal Microsoft accounts" to support both business and personal Office 365 accounts.
Azure Active Directory service
New App Registration
03

Add Redirect URIs

Go to the Authentication panel and click Add URI under the Web section. Add 2 redirect URIs using your Unipile DSN (available in the Unipile Dashboard, top right):

https://{{YOUR_DSN}}/api/v1/hosted/microsoft_auth_request_callback
https://{{YOUR_DSN_less_port}}/api/v1/hosted/microsoft_auth_request_callback/port{{YOUR_PORT}}
04

Configure API Permissions

Go to API Permissions > Add a permission > Microsoft Graph, then add the following Delegated permissions:

Mail.Read
Mail.ReadWrite
Mail.Send

For Calendar features, also add: Calendars.ReadWrite, Calendars.Read, Calendars.Read.Shared, Calendars.ReadWrite.Shared. Add them in your Unipile Dashboard scopes settings too.

Add API Permission
Choose Microsoft Graph
Add Delegated Permissions
Application Permissions Screen
05

Create a Client Secret

Go to Certificates & secrets, click New client secret. Name the secret and set an expiration of 730 days (24 months), then click "Add".

Important: Copy the secret value immediately. You won't be able to retrieve it from this page afterward. Set a calendar reminder before expiration to avoid service interruption.
New Client Secret
Set Expiration Date
Copy Secret Value
06

Connect to Unipile Dashboard

Go to the Unipile Dashboard, navigate to Settings > Microsoft OAuth.

  • Copy-paste the Application (Client) ID from the Azure Overview page.
  • Paste the secret value from the Certificates & secrets page.
  • Click Save.
You are now set to start connecting Microsoft accounts to Unipile. Your end users will see your app name and logo in the OAuth consent screen.
07

Test the Connection

From the Unipile Dashboard, trigger a new Microsoft account link to verify that your custom OAuth credentials work properly. You should see your app name and branding in the Microsoft consent prompt instead of Unipile's defaults.

Microsoft Consent Prompt with Verified Publisher
Optional, For production apps
8
Become a Verified Publisher
Recommended for production, removes the "unverified" warning in the consent screen

With verification, a blue checkmark appears in the consent prompt. Without it, professional accounts may see an "unverified publisher" warning.

Step 1: Join the Microsoft Partner Network

Step 2: Verify your domain

Create a file named microsoft-identity-association.json and host it at:

https://yourdomain.com/.well-known/microsoft-identity-association.json

Step 3: Link your Partner Global Account (PGA) ID

  • Find your PGA ID via Partner Center.
  • In Azure Portal, go to App Registrations > Your App > Branding & properties, enter the PGA ID, and save.

For full details, see the Microsoft Publisher Verification documentation.

9
Handling "Administrator Approval Required"
When end users see a consent block from their IT admin

If a user sees "Administrator approval required", the required consent has not been granted at the tenant level. Two methods to resolve this:

Method 1: Admin Consent Request in Microsoft Entra

A Microsoft administrator must review and approve the pending admin consent request. See the Microsoft documentation on reviewing admin consent requests.

Method 2: OAuth login as admin with tenant-wide consent

  • The admin starts the OAuth login flow from your app.
  • During Microsoft authorization, the admin must tick: "Consent on behalf of your organization".
  • This grants consent for all users in the organization and prevents the prompt for future users.

Full details in the Microsoft consent troubleshooting guide.

Use Cases

Microsoft Graph API Email Use Cases

The microsoft graph api email endpoint powers a wide range of SaaS applications that rely on Outlook and Exchange mailboxes. These are the three most common integration patterns used by teams building on the Graph API today.

CRM - Contact and Email Sync

Sync Outlook email threads and contacts directly into your CRM. Match senders to existing deal records, log every conversation automatically, and surface relationship history without any manual copy-paste from Outlook.

Email API Guide
ATS - Application Tracking

Track candidate email threads across Outlook mailboxes. Parse incoming application emails, extract attachments, and route them to the right job pipeline - all via the microsoft graph api email endpoint with zero manual intervention.

Send Email API
Support Tools - Ticket Routing

Convert incoming Outlook emails into support tickets. Use Graph webhooks to receive real-time new-email events, classify by subject or sender domain, and route to the right team queue - replacing manual triage with automated logic.

Unified Email API
Features

Key Features of Microsoft Graph API Email

The Microsoft Graph API for email exposes a comprehensive set of capabilities well beyond basic send and receive. Here are the six most important features every developer should know before building on the Microsoft Graph API email stack.

Read, Send, and Reply

Fetch individual messages or paginated lists. Send new emails or reply inline. Move messages between folders or mark as read/unread.

GET /v1.0/me/messages
Attachments

Upload, download, and list file attachments on any message. Supports inline (embedded) attachments and large file uploads via upload sessions for files over 3 MB.

GET /v1.0/me/messages/{id}/attachments
Folders and Labels

Create, rename, and delete mail folders. List all mailFolders, move messages between them, and manage child folder hierarchies, identical to what users see in Outlook.

GET /v1.0/me/mailFolders
Search and Filter

Use OData query parameters ($filter, $search, $orderby) to find emails by sender, subject, date range, or keyword. Supports KQL for advanced full-text search.

GET /me/messages?$search="project"
Webhook Subscriptions

Subscribe to change notifications for mailbox events. Receive near real-time HTTP POST callbacks when new emails arrive, messages are read, or folders change.

POST /v1.0/subscriptions
Batch Requests

Combine up to 20 individual Graph API requests into a single HTTP call using the $batch endpoint. Dramatically reduces round-trips for operations like bulk email reads.

POST /v1.0/$batch
Code Examples

How to Send, Read & Sync Emails with Microsoft Graph API

Three production-ready patterns covering the core operations every developer needs: sending email, reading messages with filters, and incremental delta sync for real-time mailbox monitoring.

POST /v1.0/me/sendMail — Python via Unipile
send_outlook_email.py
import requests # Unipile Unified Email API # Sends via Microsoft Graph — no direct OAuth required BASE = "https://api.unipile.com:13465/api/v1" HEADERS = { "X-API-KEY": "YOUR_ACCESS_TOKEN", "Content-Type": "application/json" } def send_outlook_email(account_id, to, subject, body): payload = { "account_id": account_id, "to": [{"identifier": to}], "subject": subject, "body": body } r = requests.post(f"{BASE}/emails", headers=HEADERS, json=payload) return r.json() # Example usage send_outlook_email( "acc_outlook_123", to="recipient@company.com", subject="Meeting follow-up", body="Hi, following up on our call..." )
Email sent via Microsoft Graph — Outlook account acc_outlook_123
Direct Graph API equivalent: POST https://graph.microsoft.com/v1.0/me/sendMail with message.toRecipients, message.subject, and message.body.content. Unipile abstracts the OAuth token refresh and MIME handling. See the Send Email API guide for attachment support and reply-threading.
GET /v1.0/me/messages — filter, select, paginate
read_outlook_emails.py
import requests # Read Outlook emails with filters via Unipile BASE = "https://api.unipile.com:13465/api/v1" HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"} def list_outlook_emails(account_id, sender_filter=None, limit=20): params = { "account_id": account_id, "limit": limit } if sender_filter: # Maps to $filter=from/emailAddress/address eq '...' params["from"] = sender_filter r = requests.get(f"{BASE}/emails", headers=HEADERS, params=params) return r.json().get("items", []) # Fetch last 20 emails from a specific sender emails = list_outlook_emails("acc_outlook_123", sender_filter="hr@acme.com") for e in emails: print(e["subject"], e["from"], e["date"])
20 messages fetched from Outlook — filtered by sender domain
OData filters supported natively: $filter, $search, $select, $orderby, $top. Use $search="subject:invoice" for KQL full-text search. Attachments over 3MB require an upload session (POST /createUploadSession) — not a single multipart request.
GET /v1.0/me/mailFolders/inbox/messages/delta — incremental sync
delta_sync_outlook.py
import requests # Delta Sync — only fetch emails NEW since last sync # Unipile handles the deltaToken lifecycle automatically BASE = "https://api.unipile.com:13465/api/v1" HEADERS = {"X-API-KEY": "YOUR_ACCESS_TOKEN"} def sync_new_emails(account_id, cursor=None): """ Returns only emails received since last call. cursor = opaque pagination token (store between calls). """ params = {"account_id": account_id} if cursor: params["cursor"] = cursor r = requests.get(f"{BASE}/emails/sync", headers=HEADERS, params=params) data = r.json() return data.get("items", []), data.get("cursor") # First sync — no cursor emails, next_cursor = sync_new_emails("acc_outlook_123") # Store next_cursor in your DB, use it for subsequent calls print(f"{len(emails)} new emails — next cursor saved")
Delta sync complete — 0 API calls wasted on already-seen messages
How delta works natively on Graph: GET /me/mailFolders/inbox/messages/delta returns a @odata.deltaLink on the first call. Store it and use it next time — Graph returns only the diff. No polling full mailbox = 10x fewer API calls vs standard GET /messages. Unipile's /emails/sync endpoint wraps this pattern with automatic token management.
Real-Time

Microsoft Graph API Webhooks for Email Events

Microsoft Graph subscriptions (webhooks) let your server receive HTTP POST notifications the moment an email arrives, is read, moved, or deleted. Below is a complete Python example for subscribing to Inbox events, plus details on lifecycle management.

A Graph webhook subscription has two required fields: changeType (what events to watch) and notificationUrl (your HTTPS endpoint). Microsoft sends a validationToken query parameter on first subscription. Your endpoint must echo it back as plain text within 10 seconds to confirm ownership.

Graph subscriptions expire after a maximum of 4230 minutes (~3 days) for mail resources. Your server must renew before expiry via PATCH /v1.0/subscriptions/{id} or you will stop receiving notifications silently.

1 Lifecycle Notifications
Microsoft Graph sends lifecycle notifications to a separate lifecycleNotificationUrl when a subscription is about to expire or has been revoked. Your server must respond with HTTP 202 to acknowledge. Failure to respond causes subscription termination.
2 validationToken Handshake
When you POST to /v1.0/subscriptions, Microsoft immediately calls your notificationUrl with a GET request containing ?validationToken=XXX. You must return the token as plain text (Content-Type: text/plain) with HTTP 200 within 10 seconds. Timeout means subscription creation fails.
3 Subscription Expiration
Mail subscriptions expire after at most 4230 minutes. Use a background job or cron to PATCH the expirationDateTime before it lapses. You can also re-create a subscription from scratch. Microsoft does not charge extra for renewals.
create_subscription.py
import requests, datetime ACCESS_TOKEN = "YOUR_GRAPH_TOKEN" ENDPOINT = "https://graph.microsoft.com/v1.0/subscriptions" # Expiry: max 4230 min from now for mail resources expiry = ( datetime.datetime.utcnow() + datetime.timedelta(minutes=4200) ).isoformat() + "Z" payload = { "changeType": "created", "notificationUrl": "https://yourdomain.com/webhook", "resource": "me/mailFolders('Inbox')/messages", "expirationDateTime": expiry, "clientState": "mySecretState" } r = requests.post( ENDPOINT, json=payload, headers={ "Authorization": f"Bearer {ACCESS_TOKEN}", "Content-Type": "application/json" } ) print(r.json()["id"]) # sub_xxxxxxxx-xxxx-xxxx-xxxx
201 Created, subscription active for Inbox events
Unipile

Skip the Complexity - Use Unipile's Unified Email API

Connect Microsoft Graph, Gmail, and IMAP with one SDK. No per-provider OAuth flows, no token refresh logic, no webhook infrastructure to maintain. Your team ships email features in days, not weeks.

Start for Free

No credit card required. SOC 2 Type II compliant.

Limits

Microsoft Graph API Rate Limits and Error Handling

The microsoft graph api email endpoint applies throttling at multiple levels: per user, per application, and per tenant. Understanding these limits before you go to production prevents silent failures and degraded reliability in your integration.

When throttled, Microsoft Graph returns HTTP 429 Too Many Requests with a Retry-After header specifying seconds to wait. Always read this header and back off accordingly - hammering after a 429 will extend the throttle window, not shorten it.

HTTP Code Error name Cause Fix
429 TooManyRequests Rate limit exceeded (10,000 req / 10 min per app or 1,000 req / 1 min per user) Read Retry-After header. Implement exponential backoff. Use $batch to combine requests.
401 Unauthorized Access token expired or missing Authorization header Refresh token via MSAL. Check token expiry before each request. Use token caching.
403 Forbidden Missing Mail.Read or Mail.Send permission in Azure App Registration Add required Graph permissions in Azure Portal and re-consent (or admin-consent for app permissions).
404 ResourceNotFound Message ID or folder ID does not exist (deleted or wrong tenant) Verify IDs via GET before acting on them. Handle 404 gracefully as a soft delete signal.
500 InternalServerError Transient Microsoft server error Retry with exponential backoff (1s, 2s, 4s). Log the request-id header for Microsoft support.
Multi-Provider

Beyond Microsoft Graph: Unified Email API for Gmail, Outlook and IMAP

Managing the microsoft graph api email integration is only the beginning. Most SaaS products need to support Gmail, Outlook, and IMAP simultaneously - meaning three separate OAuth flows, three token refresh loops, and three webhook systems. Unipile's unified email API abstracts all three providers behind a single endpoint.

Gmail logoGmail API Outlook logoMicrosoft Graph IMAP logoIMAP / SMTP

With Unipile's unified email API integration, you write one integration and instantly support all three provider types. Linked accounts are managed by Unipile - your backend only talks to one REST endpoint regardless of whether the user's mailbox runs on Microsoft Graph, Gmail, or IMAP.

No OAuth flows to manage - Unipile handles token acquisition, refresh, and revocation for Microsoft Graph and Gmail on your behalf.

Unified webhook events - one notificationUrl receives email events from all providers with a normalized JSON schema. No per-provider subscription management.

SOC 2 Type II compliant - all email data in transit is encrypted. Unipile does not store email content beyond what your integration requires.

Supported email providers
Outlook / Microsoft 365
via Microsoft Graph API
Active
Gmail
via Gmail API (Google)
Active
IMAP / SMTP
Universal email fallback
Active
Get Started

Start Integrating Microsoft Graph Email in Minutes

Join 200+ SaaS teams using Unipile to connect Outlook, Gmail, and IMAP under a single API. No vendor lock-in. SOC 2 compliant.

FAQ

Frequently Asked Questions

Everything developers ask before building on the microsoft graph api email endpoint - from authentication to rate limits to provider coverage.

01
What is Microsoft Graph API for email?
The Microsoft Graph API for email is the official REST endpoint provided by Microsoft for accessing Outlook and Exchange mailbox data. It lives at https://graph.microsoft.com/v1.0/me/messages and uses OAuth 2.0 authentication via Azure Active Directory. It supports reading, sending, searching, and managing emails, as well as receiving real-time change notifications via webhook subscriptions.
02
How does OAuth 2.0 work with Microsoft Graph?
Microsoft Graph uses Azure Active Directory (Entra ID) for authentication. You register an application in the Azure portal, configure the required Graph API permissions (like Mail.Read and Mail.Send), and use the Microsoft Authentication Library (MSAL) to acquire access tokens. There are two main flows: delegated (user signs in interactively) and application (server-to-server, no user interaction). Tokens expire after 1 hour and must be refreshed automatically.
03
Does Microsoft Graph API support IMAP?
Microsoft Graph API does not use IMAP internally - it is a REST API that abstracts the underlying mail protocol. However, Outlook accounts can still be accessed via IMAP (with OAuth 2.0, since Basic Auth was retired). For Outlook email integration, Microsoft strongly recommends using Graph API over IMAP because it offers more features, better performance, and full webhook support. For non-Microsoft mailboxes, IMAP remains the universal fallback. For more on this, comparison of Microsoft Graph and other email API providers.
04
What are the rate limits for Microsoft Graph email API?
Microsoft Graph enforces throttling at multiple levels. The general limit is 10,000 requests per 10 minutes per application. Per-user limits can be lower depending on the operation type. When throttled, the API returns HTTP 429 with a Retry-After header. Best practices: implement exponential backoff, use $batch to combine up to 20 requests into one HTTP call, and cache frequently accessed data to minimize redundant calls. For more details, see Microsoft Graph free quota in our free email API guide.
05
How do I set up webhooks with Microsoft Graph API?
POST to /v1.0/subscriptions with a changeType (e.g., "created"), a notificationUrl pointing to your HTTPS endpoint, and a resource (e.g., "me/mailFolders('Inbox')/messages"). Microsoft immediately sends a GET request with a validationToken - your server must echo it back as plain text within 10 seconds. Subscriptions expire after 4230 minutes maximum and must be renewed via PATCH before expiry.
06
Can I send emails on behalf of a user with Microsoft Graph?
Yes. With delegated permissions (Mail.Send), you can send email on behalf of the signed-in user from their own mailbox. With application permissions (Mail.Send), you can send on behalf of any user in the tenant without them being signed in - useful for automated notifications or CRM integrations. See also: Send Email on Behalf of User API guide.
07
What is the difference between Microsoft Graph API and EWS?
Exchange Web Services (EWS) is a SOAP-based API Microsoft built for on-premises Exchange. Microsoft Graph API is the modern REST replacement and is the only recommended approach for new integrations. EWS is in maintenance mode - no new features are being added and Microsoft has announced plans to retire it for Exchange Online. If you still use EWS, migrate to Graph API now. For legacy on-premises Exchange (2013/2016), EWS may still be your only option, but Unipile's email API can help bridge the gap.
Still have questions? Our team is here to help you integrate the microsoft graph api email endpoint into your product.
Talk to an expert
en_USEN