---
name: outlook-owa
description: Microsoft Outlook Web Access (OWA) automation using Playwright. No API required - automates the browser to access Outlook on the web.
isolated-context: false
allowed-tools: execute, bash, read_file, write_file
---

# Outlook Web Access (OWA) Automation

## Overview

This skill uses Playwright to automate Outlook Web Access (OWA) in a browser. It works with both New Outlook and Classic Outlook, and doesn't require any API access - it automates the web interface directly using your existing SSO login.

## When to Use

Use this skill when:
- Reading emails through Outlook on the web
- Sending emails via OWA
- Checking calendar events
- Working with corporate Outlook accounts (no API access)
- Using New Outlook for Mac (which lacks AppleScript support)

## Prerequisites

- **Playwright installed**: `pip install playwright`
- **Browser installed**: Chromium (bundled with Playwright)
- **Outlook account**: Your SSO credentials
- **Internet connection**: For accessing OWA

## Installation

```bash
pip install playwright
playwright install chromium
```

## Usage

### Read Emails

```python
from playwright.sync_api import sync_playwright

def read_unread_emails():
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        context = browser.new_context()

        # Navigate to OWA
        page = context.new_page()
        page.goto("https://outlook.office.com/")

        # Wait for user to login (manual SSO)
        page.wait_for_url("outlook.live.com", timeout=60000)

        # Get unread emails
        unread_emails = page.query_selector_all("[data-id='unread-selector']")
        for email in unread_emails:
            subject = email.query_selector(".subject").text_content()
            print(f"Subject: {subject}")

        browser.close()
```

### Send Email

```python
def send_email(to, subject, body):
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)
        page = browser.new_page()

        page.goto("https://outlook.office.com/")

        # Click New Email button
        page.click("[title='New mail'], [aria-label='New mail']")

        # Fill in recipients
        page.fill("[aria-label='To'], [role='textbox']", to)

        # Fill subject
        page.fill("[aria-label='Add a subject'], [role='textbox']", subject)

        # Fill body
        page.frame_locator("iframe[title='Body']").fill(body)

        # Send
        page.click("[aria-label='Send'], [title='Send']")

        browser.close()
```

## Authentication

**First time setup requires manual login:**

1. Run the script with `headless=False` (show browser)
2. Browser will open OWA login page
3. Complete your SSO login manually
4. Script will save cookies/session for future runs

```python
# Save session after login
context.storage_state(path="./owa_session.json")

# Load saved session
browser.new_context(storage_state="./owa_session.json")
```

## Quick Start

### Check Unread Emails

```python
from outlook_owa import check_unread_emails

emails = check_unread_emails(limit=10)
for email in emails:
    print(f"{email['subject']}: {email['sender']}")
```

### Search Emails

```python
from outlook_owa import search_emails

emails = search_emails("quarterly report", limit=5)
```

### Send Email

```python
from outlook_owa import send_email

send_email(
    to="colleague@example.com",
    subject="Meeting Update",
    body="Here's the update on our project..."
)
```

## Common Scenarios

### Scenario 1: Process Morning Emails

```
"检查我 Outlook 的未读邮件"
"列出最新的 10 封邮件"
```

### Scenario 2: Search for Specific Email

```
"搜索包含 'quarterly report' 的邮件"
"查找来自 John 的邮件"
```

### Scenario 3: Send Quick Email

```
"发送邮件给 john@example.com，主题是'项目更新'"
```

## Limitations

- **First login must be manual** - SSO authentication
- **Requires browser** - Uses Playwright with Chromium
- **Slower than API** - Browser automation vs direct API
- **UI dependent** - Breaks if OWA UI changes
- **Rate limits** - May trigger bot detection

## Best Practices

- **Save session** - Store cookies after first login
- **Use wait_for** - Wait for elements to load
- **Handle SSO** - Build in time for manual login
- **Headful mode** - Use headless=False for debugging
- **Error handling** - Handle timeouts and element not found

## Troubleshooting

### Login Issues

If SSO login fails:
1. Run with `headless=False` to see the browser
2. Complete login manually
3. Wait for page to fully load
4. Save session state

### Element Not Found

If selectors don't work:
1. OWA UI may have changed
2. Use browser DevTools to find new selectors
3. Update selectors in the code
4. Test in headful mode first

### Session Expired

If saved session stops working:
1. Delete `owa_session.json`
2. Run headful mode and login again
3. Save new session state

## Integration with Other Skills

- **markitdown**: Convert email content to Markdown
- **docx**: Save email as Word document
- **xlsx**: Export email data to Excel
- **web-search**: Research before composing emails

## Security Notes

- Session files contain authentication cookies
- Store session files securely
- Don't commit session files to git
- Delete session when done if needed

## Resources

- **Playwright**: https://playwright.dev/python/
- **OWA URL**: https://outlook.office.com/
- **OWA URL (China)**: https://outlook.office365.cn/
