Outlook Email Skill
Read and summarize emails from Microsoft Outlook using the Microsoft Graph API.
Authentication
The access token is stored in the OUTLOOK_ACCESS_TOKEN environment variable. All requests must include the header:
Authorization: Bearer $OUTLOOK_ACCESS_TOKEN
Base URL
https://graph.microsoft.com/v1.0
Setup Instructions
Getting Your Access Token
Register an App in Azure AD (One-time setup):
- Go to https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
- Click "New registration"
- Name: "Claude Outlook Integration"
- Supported account types: "Accounts in any organizational directory and personal Microsoft accounts"
- Redirect URI:
https://login.microsoftonline.com/common/oauth2/nativeclient(Public client/native) - Click "Register"
- Note the Application (client) ID
Configure API Permissions:
- In your app, go to "API permissions"
- Click "Add a permission" → "Microsoft Graph" → "Delegated permissions"
- Add these permissions:
Mail.Read- Read user mailMail.ReadBasic- Read basic mail infoUser.Read- Sign in and read user profile
- Click "Add permissions"
Get Access Token (Using Device Code Flow):
# Step 1: Request device code TENANT_ID="common" CLIENT_ID="your-client-id-here" SCOPE="https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/User.Read offline_access" curl -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/devicecode" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=$CLIENT_ID&scope=$SCOPE"This will return a
user_codeanddevice_code. Open the verification URL and enter the user code.# Step 2: Poll for token (after completing device authentication) DEVICE_CODE="device-code-from-step-1" curl -X POST "https://login.microsoftonline.com/$TENANT_ID/oauth2/v2.0/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=$CLIENT_ID&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=$DEVICE_CODE"Save the
access_tokento your environment:export OUTLOOK_ACCESS_TOKEN="your-access-token-here" # Add to your ~/.zshrc or ~/.bashrc to persist
Token Refresh
Tokens expire after 1 hour. Save the refresh_token and use it to get a new access token:
curl -X POST "https://login.microsoftonline.com/common/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=$CLIENT_ID&grant_type=refresh_token&refresh_token=$REFRESH_TOKEN&scope=$SCOPE"
Reading Emails
List Messages from Inbox
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Query Parameters:
$top=N- Limit number of messages (default: 10, max: 999)$skip=N- Skip N messages (pagination)$select=field1,field2- Select specific fields$filter=- Filter messages (e.g.,isRead eq false)$orderby=- Sort messages (e.g.,receivedDateTime desc)$search="query"- Search messages
Common field selections:
$select=id,subject,from,toRecipients,receivedDateTime,isRead,hasAttachments,bodyPreview,body
List Unread Messages
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?\$filter=isRead eq false&\$top=20" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
List Recent Messages
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?\$orderby=receivedDateTime desc&\$top=10" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Get a Specific Message
curl -s "https://graph.microsoft.com/v1.0/me/messages/{message_id}" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Get Message Body as Plain Text
curl -s "https://graph.microsoft.com/v1.0/me/messages/{message_id}?\$select=body" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN" \
-H "Prefer: outlook.body-content-type='text'"
Search Messages
# Search by keyword
curl -s "https://graph.microsoft.com/v1.0/me/messages?\$search=\"project update\"" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
# Search from specific sender
curl -s "https://graph.microsoft.com/v1.0/me/messages?\$filter=from/emailAddress/address eq 'sender@example.com'" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Mark as Read
curl -s -X PATCH "https://graph.microsoft.com/v1.0/me/messages/{message_id}" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"isRead": true}'
Mail Folders
List All Mail Folders
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Common Folder Names
inbox- Inbox foldersentitems- Sent Itemsdeleteditems- Deleted Itemsdrafts- Draftsjunkemail- Junk Email
Get Messages from Specific Folder
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/{folder_id}/messages" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Attachments
List Attachments
curl -s "https://graph.microsoft.com/v1.0/me/messages/{message_id}/attachments" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Download Attachment
curl -s "https://graph.microsoft.com/v1.0/me/messages/{message_id}/attachments/{attachment_id}" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Email Summarization Workflow
When asked to summarize emails, follow this workflow:
List recent emails with subject, sender, and preview:
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?\$top=20&\$orderby=receivedDateTime desc&\$select=id,subject,from,receivedDateTime,bodyPreview,isRead" \ -H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"For each email to summarize, get the full body:
curl -s "https://graph.microsoft.com/v1.0/me/messages/{message_id}?\$select=subject,from,receivedDateTime,body" \ -H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN" \ -H "Prefer: outlook.body-content-type='text'"Summarize by:
- Grouping by sender or topic
- Highlighting important messages (from key people, with urgent keywords)
- Extracting action items
- Identifying unread messages
Urgent Email Identification Workflow
When asked to identify urgent emails, find emails that need attention, or check for important messages, follow this workflow:
Step 1: Fetch Recent Unread Emails
Get unread emails from the last 48 hours:
# Calculate datetime for 48 hours ago (ISO 8601 format)
SINCE=$(date -u -v-48H +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -d "48 hours ago" +"%Y-%m-%dT%H:%M:%SZ")
curl -s "https://graph.microsoft.com/v1.0/me/mailFolders/inbox/messages?\$filter=isRead eq false and receivedDateTime ge $SINCE&\$top=50&\$orderby=receivedDateTime desc&\$select=id,subject,from,receivedDateTime,bodyPreview,importance,hasAttachments" \
-H "Authorization: Bearer $OUTLOOK_ACCESS_TOKEN"
Step 2: AI-Powered Urgency Analysis
Analyze each email using these criteria to determine urgency:
Sender Signals:
- Executives, managers, or leadership (titles like CEO, VP, Director, Manager)
- External clients or partners
- IT/Security teams (potential incidents)
- HR (time-sensitive policies or requests)
Subject Line Keywords:
- URGENT, ASAP, ACTION REQUIRED, IMMEDIATE
- Deadline, EOD, COB, by end of day
- Response needed, Please respond, Waiting on
- Time-sensitive, Critical, Important
- FYI with your name mentioned
Content Analysis:
- Direct questions requiring your response
- Explicit requests for action or deliverables
- Escalations or follow-ups on previous requests
- Meeting requests with deadlines within 24 hours
- Mentions of your name or asks for your input specifically
Importance Indicators:
importance: "high"flag set by senderhasAttachments: truecombined with action keywords- Short, direct emails (often more urgent than long ones)
Recency Weighting:
- Last 4 hours: Higher urgency
- Last 24 hours: Medium urgency boost
- 24-48 hours: Standard assessment
Step 3: Categorize and Present Results
Present emails in priority order using these categories:
CRITICAL - Requires immediate attention:
- High importance flag + action keywords
- Sender is executive or external client with deadline
- Security/IT incidents
- Missed meeting or urgent follow-up
IMPORTANT - Should address today:
- Direct questions or requests for action
- Deadlines within 24-48 hours
- Follow-ups on items you own
- External communications
REVIEW - Worth checking when available:
- FYI emails that mention you
- Team updates you should be aware of
- Lower-priority requests
Step 4: Offer Actions
After presenting the summary, offer to:
- Show the full content of any specific email
- Mark emails as read after review
- Search for related emails or threads
Response Format
All responses are in JSON format. Key fields:
id- Unique message IDsubject- Email subjectfrom- Sender information ({ "emailAddress": { "name": "...", "address": "..." }})toRecipients- Array of recipientsreceivedDateTime- ISO 8601 timestampisRead- BooleanhasAttachments- BooleanbodyPreview- First 255 characters of bodybody- Full email body ({ "contentType": "html|text", "content": "..." })importance- "low", "normal", or "high"
Error Handling
Common errors:
401 Unauthorized- Token expired or invalid, refresh token403 Forbidden- Missing required permissions404 Not Found- Invalid message or folder ID429 Too Many Requests- Rate limited, wait and retry
Rate Limits
- Microsoft Graph API has throttling limits
- For mail operations: typically 10,000 requests per 10 minutes per app per user
- If throttled (429 response), check
Retry-Afterheader
Privacy & Security
- Access tokens grant access to user's email - handle securely
- Never log or expose access tokens
- Tokens should be stored in environment variables, not in code
- Use refresh tokens to get new access tokens when they expire