Outlook Web Access Skill
This skill provides access to Outlook Web (outlook.office.com) via playwright-cli with persistent session management.
Session Configuration
All commands must use: --session=outlook-web
This ensures cookies and authentication persist between commands.
First-Time Authentication
Microsoft login requires manual intervention. Follow these steps for first-time setup:
Step 1: Open Outlook in headed mode to trigger login
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web --headed
The browser will open visibly and redirect to Microsoft login. Tell the user to complete login manually in the opened browser window.
Step 2: Verify authentication
After user confirms login is complete:
playwright-cli snapshot --session=outlook-web
If successful, the snapshot will show inbox content (email subjects, folders). If it shows a login form, authentication is not complete.
Note: After initial authentication, subsequent commands can run headless (default) since the session cookies persist.
Detecting Session Expiry
Microsoft sessions expire after ~7-14 days. Signs of expiry:
- Snapshot shows login form instead of inbox
- Navigation redirects to login URL
To re-authenticate: Open Outlook in headed mode again:
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web --headed
Complete the login manually in the browser window.
Key URLs
Base: https://outlook.office.com
Email:
- /mail/inbox - Inbox
- /mail/drafts - Drafts folder
- /mail/sentitems - Sent folder
- /mail/deleteditems - Deleted/Trash
- /mail/archive - Archive
- /mail/junkemail - Junk/Spam
- /mail/search?q=TERM - Search results
- /mail/deeplink/compose - New email composer
Calendar:
- /calendar - Calendar view
- /calendar/view/day - Day view
- /calendar/view/week - Week view
- /calendar/view/month - Month view
Email Operations
View Inbox
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web
playwright-cli snapshot --session=outlook-web
Read an Email
Navigate to inbox, then click on an email row to select it:
playwright-cli click "EMAIL_SUBJECT_OR_SELECTOR" --session=outlook-web
playwright-cli snapshot --session=outlook-web
The reading pane will show the email content.
Compose New Email (Draft by Default)
playwright-cli open "https://outlook.office.com/mail/deeplink/compose" --session=outlook-web
playwright-cli snapshot --session=outlook-web
Fill in fields:
# Add recipient
playwright-cli fill "[aria-label='To']" "recipient@example.com" --session=outlook-web
# Add subject
playwright-cli fill "[aria-label='Add a subject']" "Subject line" --session=outlook-web
# Add body (the editor area)
playwright-cli fill "[aria-label='Message body']" "Email content here" --session=outlook-web
IMPORTANT: By default, save as draft instead of sending:
# Save as draft (Ctrl+S or close the compose window)
playwright-cli keyboard "Control+s" --session=outlook-web
Only send if user explicitly requests:
# Send email (only when explicitly requested by user)
playwright-cli click "[aria-label='Send']" --session=outlook-web
Reply to an Email
Method 1: Via Reading Pane (Simple)
With an email open in the reading pane:
# Click Reply button
playwright-cli click "[aria-label='Reply']" --session=outlook-web
# Fill reply message
playwright-cli fill "[aria-label='Message body']" "Your reply text here" --session=outlook-web
# Save as draft (auto-saves, or use Ctrl+S)
playwright-cli press "Control+s" --session=outlook-web
Method 2: Complete Reply Flow
From inbox to draft reply:
# 1. Navigate to inbox
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web
# 2. Click the email (get ref from snapshot)
playwright-cli snapshot --session=outlook-web
playwright-cli click <email-ref> --session=outlook-web
# 3. Click Reply button
playwright-cli snapshot --session=outlook-web
playwright-cli click <reply-button-ref> --session=outlook-web
# 4. Fill reply
playwright-cli fill <message-body-ref> "Your reply message" --session=outlook-web
# 5. Save draft (Ctrl+S or Escape)
playwright-cli press "Control+s" --session=outlook-web
Method 3: Fast Batch Reply
Using run-code for speed:
playwright-cli run-code "
await page.goto('https://outlook.office.com/mail/inbox');
await page.getByRole('option').first().click();
await page.getByRole('button', { name: 'Reply', exact: true }).click();
await page.getByRole('textbox', { name: 'Message body' }).fill('Your reply');
await page.keyboard.press('Control+s');
" --session=outlook-web
Note: Replies are auto-saved as drafts and have "Re: [Original Subject]" format.
Forward an Email
playwright-cli click "[aria-label='Forward']" --session=outlook-web
playwright-cli snapshot --session=outlook-web
# Add recipient and content
Delete an Email
With an email selected:
playwright-cli click "[aria-label='Delete']" --session=outlook-web
Search Emails
playwright-cli open "https://outlook.office.com/mail/search?q=YOUR_SEARCH_TERM" --session=outlook-web
playwright-cli snapshot --session=outlook-web
Or use the search box:
playwright-cli click "[aria-label='Search']" --session=outlook-web
playwright-cli fill "[aria-label='Search']" "search query" --session=outlook-web
playwright-cli keyboard "Enter" --session=outlook-web
playwright-cli snapshot --session=outlook-web
Navigate Folders
# Drafts
playwright-cli open "https://outlook.office.com/mail/drafts" --session=outlook-web
# Sent
playwright-cli open "https://outlook.office.com/mail/sentitems" --session=outlook-web
# Deleted
playwright-cli open "https://outlook.office.com/mail/deleteditems" --session=outlook-web
Calendar Operations
View Calendar
playwright-cli open "https://outlook.office.com/calendar" --session=outlook-web
playwright-cli snapshot --session=outlook-web
View Specific Time Range
# Day view
playwright-cli open "https://outlook.office.com/calendar/view/day" --session=outlook-web
# Week view
playwright-cli open "https://outlook.office.com/calendar/view/week" --session=outlook-web
# Month view
playwright-cli open "https://outlook.office.com/calendar/view/month" --session=outlook-web
View Event Details
Click on an event in the calendar view:
playwright-cli click "EVENT_TITLE_OR_SELECTOR" --session=outlook-web
playwright-cli snapshot --session=outlook-web
Best Practices
- Always snapshot after navigation - Outlook loads asynchronously; snapshot confirms content is ready
- Wait if needed - If snapshot shows loading state, wait and snapshot again:
playwright-cli wait 2000 --session=outlook-web playwright-cli snapshot --session=outlook-web - Use ARIA labels - Outlook has good ARIA labeling; prefer
[aria-label='...']selectors - Check for errors - If an operation fails, snapshot to see current state
- Default to drafts - Never send emails without explicit user confirmation
Advanced Usage & Optimizations
Batch Operations with run-code
For faster programmatic operations, batch multiple commands using run-code:
playwright-cli run-code "
// Open inbox and reply to first email
await page.goto('https://outlook.office.com/mail/inbox');
await page.getByRole('option').first().click();
await page.getByRole('button', { name: 'Reply', exact: true }).click();
await page.getByRole('textbox', { name: 'Message body' }).fill('Your reply text');
await page.keyboard.press('Control+s');
" --session=outlook-web
Benefits: 60-70% faster than individual commands, single process invocation.
Direct Email Navigation
If you have an email ID (from URL or previous snapshot), navigate directly:
# Instead of: inbox → find → click
playwright-cli open "https://outlook.office.com/mail/inbox/id/AAQkAGMxODI1MWVlLTgy..." --session=outlook-web
Email IDs are found in URLs when emails are open: /mail/inbox/id/<EMAIL_ID>
Skip Unnecessary Snapshots
For programmatic use, only snapshot when you need to extract data:
# Fast: No intermediate snapshots
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web
playwright-cli click e600 --session=outlook-web
playwright-cli click "Reply" --session=outlook-web
playwright-cli fill "Message body" "Text" --session=outlook-web
# Only snapshot if you need to verify or extract data
Resource Blocking for Speed (Advanced)
Block images, fonts, and analytics to speed up page loads by 30-50%:
playwright-cli run-code "
// Block non-essential resources
await page.route('**/*', (route) => {
const url = route.request().url();
if (url.includes('browser.events.data.microsoft.com') ||
url.includes('csp.microsoft.com') ||
url.match(/\\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf)$/)) {
route.abort();
} else {
route.continue();
}
});
// Then navigate
await page.goto('https://outlook.office.com/mail/inbox');
" --session=outlook-web
Note: Test thoroughly as blocking resources may affect functionality.
Trust Auto-Save
Outlook Web auto-saves drafts every few seconds. For programmatic workflows:
- Skip navigating to drafts folder for verification
- Trust that draft saved if no error occurred
- Only verify when explicitly needed
Efficient Content Extraction for LLMs
Problem: Full page snapshots include 60-95% UI chrome (toolbars, navigation, wrappers) and only 5-40% actual content.
Solution: Use run-code to extract just the text you need:
# Extract email list as text (no YAML overhead)
playwright-cli run-code "
const listbox = await page.locator('[role=\"listbox\"]');
return await listbox.innerText();
" --session=outlook-web
# Extract just message body text
playwright-cli run-code "
const body = await page.locator('[role=\"document\"]').first();
return await body.innerText();
" --session=outlook-web
# Extract structured data as JSON
playwright-cli run-code "
const emails = await page.locator('[role=\"option\"]')
.evaluateAll(opts => opts.slice(0, 10).map(o => ({
text: o.textContent.trim(),
unread: o.textContent.includes('Unread')
})));
return JSON.stringify(emails, null, 2);
" --session=outlook-web
Benefits:
- 70-90% reduction in tokens
- Faster LLM processing
- Cleaner output (text or JSON vs YAML)
When to use:
- Full snapshots: Interactive exploration, getting element refs
- Text extraction: Reading email content, processing messages
- JSON extraction: Bulk operations, data analysis
Troubleshooting
"Browser is already in use" error
Close the existing playwright session:
playwright-cli close --session=outlook-web
Then retry the command.
Login page appears unexpectedly
Session has expired. Re-authenticate:
playwright-cli open "https://outlook.office.com/mail/inbox" --session=outlook-web --headed
# User completes login in the opened browser window
Content not loading
Wait and retry:
playwright-cli wait 3000 --session=outlook-web
playwright-cli snapshot --session=outlook-web
UI Pattern Reference
See references/ui-patterns.md for discovered element selectors and patterns specific to Outlook Web.