Manage Outlook email, including drafting, sending, organizing, rules, vacation replies, and inbox analysis
assistant skills install outlookThis skill provides Outlook-specific operations beyond the shared messaging skill. For cross-platform messaging (send, read, search, reply), use the messaging skill. Outlook operations depend on the messaging skill's provider infrastructure - load messaging first if Outlook is not yet connected.
All operations use CLI scripts that return JSON:
{ "ok": true, "data": ... }{ "ok": false, "error": "..." }| Script | Operation | Description |
|---|---|---|
outlook-email.ts | draft | Create email drafts in the Drafts folder (including reply drafts) |
outlook-email.ts | send-draft | Send an existing draft (requires explicit user confirmation) |
outlook-email.ts | forward | Create forward drafts, preserving attachments |
outlook-email.ts | trash | Move messages to Deleted Items |
outlook-manage.ts | categories | Manage message categories (add, remove, list available) |
outlook-manage.ts | follow-up | Track messages with Outlook's native flag system |
outlook-manage.ts | attachments | List and download email attachments |
outlook-manage.ts | rules | Create, list, and delete server-side inbox message rules |
outlook-manage.ts | vacation | Get, enable, or disable auto-reply (out-of-office) settings |
outlook-manage.ts | unsubscribe | Unsubscribe from mailing lists (requires explicit user confirmation) |
outlook-scan.ts | sender-digest | Scan inbox and group messages by sender for declutter workflows |
outlook-scan.ts | outreach-scan | Identify cold outreach senders (no List-Unsubscribe header) |
# Draft an email
bun run scripts/outlook-email.ts draft --to "user@example.com" --subject "Hello" --body "Message body"
# Send an existing draft (REQUIRES user confirmation before execution)
bun run scripts/outlook-email.ts send-draft --draft-id "AAMk..."
# Forward a message
bun run scripts/outlook-email.ts forward --message-id "AAMk..." --to "recipient@example.com" --comment "FYI"
# Trash a message
bun run scripts/outlook-email.ts trash --message-id "AAMk..."
# Categories - add categories to a message
bun run scripts/outlook-manage.ts categories --action add --message-id "AAMk..." --categories "Blue Category,Important"
# Follow-up - flag a message for follow-up
bun run scripts/outlook-manage.ts follow-up --action track --message-id "AAMk..."
# Attachments - list attachments on a message
bun run scripts/outlook-manage.ts attachments --action list --message-id "AAMk..."
# Rules - create a server-side inbox rule
bun run scripts/outlook-manage.ts rules --action create --name "Archive newsletters" --conditions '{"senderContains":["newsletter"]}' --actions '{"moveToFolder":"Archive"}'
# Vacation - enable auto-reply
bun run scripts/outlook-manage.ts vacation --action enable --internal-message "I'm out of office" --external-message "I'm currently away"
# Unsubscribe from a mailing list (REQUIRES user confirmation before execution)
bun run scripts/outlook-manage.ts unsubscribe --message-id "AAMk..."
# Sender digest - scan inbox grouped by sender
bun run scripts/outlook-scan.ts sender-digest [--query "..."] [--time-range "90d"] [--account "..."]
# Outreach scan - identify cold outreach senders
bun run scripts/outlook-scan.ts outreach-scan [--time-range "90d"] [--account "..."]
Scan scripts store message IDs in the daemon's in-memory cache (via assistant cache) and return a lightweight summary with a cache_key. This keeps thousands of message IDs out of the conversation context. To retrieve cached message IDs for a specific sender:
assistant cache get <cache_key> --json
# Returns: { "ok": true, "data": { "sender@example.com": ["msgId1", "msgId2", ...], ... } }
When the user mentions "email" - sending, reading, checking, decluttering, drafting, or anything else - always default to the user's own email (Outlook) unless they explicitly ask about the assistant's own email address (e.g., "set up your email", "send from your address", "check your inbox"). The vast majority of email requests are about the user's Outlook, not the assistant's @vellum.me address.
Do not offer the assistant's own email as an option unless the user specifically asks. If Outlook is not connected, guide them through Outlook setup.
assistant oauth ping outlook. This checks whether the user's Outlook/Microsoft account is connected and the token is valid.vellum-oauth-integrations skill. The skill will evaluate whether managed or your-own mode is appropriate and guide the user accordingly.When an Outlook script fails with a token or authorization error:
assistant oauth ping outlook. This often resolves expired tokens automatically.vellum-oauth-integrations skill. The user came to you to get something done, not to troubleshoot - make it seamless.Two operations are high-risk and require explicit user confirmation before execution:
send-draft: Always show the user what will be sent (recipients, subject, body summary) and wait for explicit confirmation ("yes", "send it", etc.) before running the send-draft script. Never auto-send.unsubscribe: Always tell the user which mailing list will be unsubscribed from and wait for explicit confirmation before running the unsubscribe script. Unsubscribe actions cannot be undone.If the user has not explicitly confirmed, do not execute these operations. A general instruction like "clean up my inbox" is not confirmation to unsubscribe - it means scan and present options.
Outlook uses a draft-first workflow where appropriate:
draft operation creates a draft in the Outlook Drafts folder for user review before sending.forward operation creates a forward draft, preserving attachments.When the user asks to "draft" or "compose" an email, use the draft script. When they say "send", use the messaging skill's send. If ambiguous, prefer drafting so the user can review first.
Outlook and Gmail have different organizational models. Keep these distinctions in mind:
| Concept | Gmail | Outlook |
|---|---|---|
| Organization | Labels (multiple per message) | Folders (one per message) + Categories (multiple per message) |
| Categorization | Labels serve dual purpose | Categories are color-coded tags independent of folder location |
| Follow-up | Label-based tracking | Native flag system (flagged, complete, notFlagged) |
| Inbox rules | Gmail filters | Outlook inbox rules (server-side) |
| Archive | Remove INBOX label | Move to Archive folder |
Categories are Outlook's tagging system for organizing messages. Unlike Gmail labels, categories are independent of folder structure - a message can be in any folder and have multiple categories. Categories are color-coded (Blue, Green, Orange, Purple, Red, Yellow, or custom names). Use categories to tag and organize messages without moving them between folders.
Outlook uses a native flag system for follow-up tracking:
flagged - message is marked for follow-upcomplete - follow-up is donenotFlagged - no follow-up trackingThis replaces Gmail's label-based follow-up approach. Use the Outlook flag system directly rather than creating custom folder-based workarounds.
Outlook inbox rules run server-side and support conditions like sender, subject, body keywords, and importance level. Actions include moving to folders, categorizing, flagging, forwarding, and deleting. When a user asks to "filter" or "auto-sort" email, use the rules operation - do not try to replicate Gmail's label-based filtering with Outlook folders.
Gmail uses labels - a message can have multiple labels and removing the INBOX label archives it. Outlook uses folders - a message lives in exactly one folder at a time. Moving a message to Archive removes it from Inbox. To tag a message with multiple categories without moving it, use the categories operation. Do not create folder hierarchies to simulate Gmail's multi-label system.
When a user asks to declutter, clean up, or organize their email - start scanning immediately. Don't ask what kind of cleanup they want or request permission to read their inbox. Go straight to scanning - but once results are ready, always present them and let the user choose actions before archiving or unsubscribing.
CRITICAL: Never archive, unsubscribe, or take similar bulk actions unless the user has explicitly confirmed for that specific batch. Each batch of results requires its own explicit user confirmation. If the user says "keep going" or "keep decluttering," that means scan and present new results - NOT auto-archive. Previous batch approvals do not carry forward, but deselections DO carry forward: when the user deselects senders from a cleanup batch, record those as user preferences and exclude them from future cleanup batches.
bun run scripts/outlook-scan.ts sender-digest. The script returns a cache_key plus a lightweight sender summary (counts, unsubscribe availability, sample subjects). Message IDs are stored daemon-side — do NOT ask for them unless needed for archiving.messaging_archive_by_sender with from:<email> queries to archive selected senders. For unsubscribe, run the unsubscribe script for senders with hasUnsubscribe: true. If you need specific message IDs (e.g., for targeted operations), retrieve them via assistant cache get <cache_key> --json.--action create for each sender.truncated is true (message cap reached or time budget exceeded), the top senders are still captured. Present whatever results were collected - do not retry or continue. Tell the user: "Scanned [N] messages - here are your top senders."bun run scripts/outlook-scan.ts sender-digest to scan for newsletters and promotionsbun run scripts/outlook-manage.ts rules --action create --name "..." --conditions '...' --actions '...'bun run scripts/outlook-manage.ts vacation --action enable --internal-message "..." --external-message "..."bun run scripts/outlook-manage.ts follow-up --action track --message-id "..."bun run scripts/outlook-manage.ts follow-up --action listbun run scripts/outlook-manage.ts follow-up --action complete --message-id "..."bun run scripts/outlook-scan.ts outreach-scan to find senders without unsubscribe headersMedium and high risk operations require a confidence score between 0 and 1: