Documentation
Outlook Email CLI
outlook-email-pp-cli
Install
npx -y @mvanhorn/printing-press-library install outlook-emailInstalls the CLI binary and the agent skill for Claude Code, Codex, Cursor, Gemini CLI, Copilot, and more. Add --cli-only or --skill-only for one half. Requires Node.
Documentation
Drive your personal Microsoft 365 inbox from agents — read, send, sync, and run offline triage analytics that Outlook's own UI never exposes.
Personal MSA support via OAuth 2.0 device-code against /common. A local SQLite store synced through messages/delta unlocks followup, senders, since, waiting, digest, stale-unread, and bulk-archive — workflows no other Outlook CLI exposes because they require persisted state. Companion to outlook-calendar with the same auth playbook.
Created by @brennaman (Paul Brennaman).
Authentication
OAuth 2.0 device-code flow against https://login.microsoftonline.com/common. Personal MSAs (Outlook.com, Hotmail, Live) work alongside work/school accounts. Default client id is the Microsoft Graph PowerShell app, so no Azure tenant is needed. BYO Azure AD app via --client-id. Refresh tokens persisted at ~/.config/outlook-email-pp-cli/config.toml; run auth refresh or let commands auto-rotate.
Quick Start
# One-time: sign in with a personal MSA via device-code flow.
outlook-email-pp-cli auth login --device-code --launch
# Pull the full mailbox into the local SQLite store. Subsequent syncs are delta.
outlook-email-pp-cli sync --full
# Catch up on what arrived since last check, grouped by focused/other and sender.
outlook-email-pp-cli since 2h --agent
# Surface emails you sent that nobody replied to.
outlook-email-pp-cli followup --days 7 --agent --select sender,subject,sent_at,days_quiet
# See who's drowning your inbox — input to bulk-archive.
outlook-email-pp-cli senders --window 30d --min 5 --agent
Unique Features
These capabilities aren't available in any other tool for this API.
Local state that compounds
-
followup— List emails you sent more than N days ago that the recipient never replied to — close the loops you forgot about.Sales, PM, and recruiting workflows live and die on follow-up timing. Reach for this when an agent needs to surface stalled threads.
outlook-email-pp-cli followup --days 7 --agent -
senders— Group your inbox by sender over a window: count, unread, last-received, dominant folder — see who's drowning your inbox.Use as the input to bulk-archive or to drive inbox-rule decisions. Agents pruning a flooded inbox start here.
outlook-email-pp-cli senders --window 30d --min 5 --agent --select sender,count,unread,last_received -
since— Show what landed since a timestamp, grouped by focused/other, sender, and folder. Perfect for 'what did I miss while I was heads-down'.The first command an agent should run when joining a session to catch up. Cheap, structured, agent-shaped.
outlook-email-pp-cli since 2h --agent -
flagged— List flagged messages with open due dates, days-overdue, age. The inbox-zero work list Outlook never aggregates.An agent's todo list. Pair with reply/forward to actually close the items.
outlook-email-pp-cli flagged --overdue --agent -
stale-unread— Unread messages older than N days, grouped by folder. Surfaces the unread debt hiding in subfolders.Different from
senders(volume) — answers 'where is unread piling up' so an agent can route folders to bulk-mark-read.outlook-email-pp-cli stale-unread --days 14 --agent -
waiting— Conversations where the last message is not from you and is unread or unanswered for N days. The 'someone's waiting on you' work list.Symmetric to followup. Pair both at start-of-day to see your half and their half of every open thread.
outlook-email-pp-cli waiting --days 3 --agent -
conversations— Conversations ranked by message count, participants, and unread tail. Find the threads burning your attention budget.Helps an agent decide which thread to summarize or mute next.
outlook-email-pp-cli conversations --top 20 --window 30d --agent -
quiet— Senders you used to hear from but who've gone silent for N days. Useful for relationship lapse detection.Sales/PM use case: surface customers or vendors who used to engage and don't anymore.
outlook-email-pp-cli quiet --baseline 90d --silent 30d --agent -
digest— One-shot daily summary: received/sent/unread/flagged counts, top senders, top conversations, focused/other ratio.Run this from a cron or skill loop to produce a Slack-shaped daily summary without making 10+ Graph calls.
outlook-email-pp-cli digest --date 2026-05-12 --agent -
attachments-stale— Attachments older than N days and over a size threshold, sortable by size. The mailbox-quota rescue plan.When the mailbox is near quota, agents need the largest oldest attachments first; this command is that list.
outlook-email-pp-cli attachments-stale --days 90 --min-mb 1 --agent --select sender,received_at,size_mb,name -
dedup— Find probable duplicate threads or messages by conversation_id, internet_message_id, or normalized (subject, from, to).Surfaces newsletter duplicates and cross-folder copies before bulk-archive runs.
outlook-email-pp-cli dedup --by subject-sender --agent
Agent-native plumbing
-
bulk-archive— Read a sender list or query, print a move plan, optionally execute it. Safe by default, no surprises.Pair with
sendersorquietfor end-to-end inbox triage; agents can audit the plan before opting in to --execute.outlook-email-pp-cli bulk-archive --from-senders senders.txt --to-folder Archive --execute
Usage
Run outlook-email-pp-cli --help for the full command reference and flag list.
Commands
attachments
Attachments on a specific message
outlook-email-pp-cli attachments get- Get a single attachment (metadata + base64 contentBytes for fileAttachment)outlook-email-pp-cli attachments list- List attachments on a message (metadata only by default)
categories
Master list of color categories applied across mail and calendar
outlook-email-pp-cli categories create- Create a new color categoryoutlook-email-pp-cli categories delete- Delete a color categoryoutlook-email-pp-cli categories get- Get a category by idoutlook-email-pp-cli categories list- List the master color categories
folders
Mail folders and their hierarchy
outlook-email-pp-cli folders children- List child folders under a parent folderoutlook-email-pp-cli folders create- Create a top-level mail folderoutlook-email-pp-cli folders create-child- Create a child folder under a parentoutlook-email-pp-cli folders delete- Delete a mail folder (moves contents to Deleted Items)outlook-email-pp-cli folders delta- Delta-sync of the mail folder hierarchyoutlook-email-pp-cli folders get- Get a mail folder by id or well-known nameoutlook-email-pp-cli folders list- List top-level mail foldersoutlook-email-pp-cli folders messages- List messages in a specific folderoutlook-email-pp-cli folders update- Rename a mail folder
inference
Focused/Other inbox classification overrides
outlook-email-pp-cli inference create-override- Pin a sender to Focused or Otheroutlook-email-pp-cli inference delete-override- Remove a sender pinoutlook-email-pp-cli inference list-overrides- List sender pins to Focused or Other
mailbox-settings
Mailbox-level settings: timezone, language, signature, automatic replies
outlook-email-pp-cli mailbox-settings get- Get all mailbox settingsoutlook-email-pp-cli mailbox-settings update- Update mailbox settings (automatic replies, timezone, working hours, language)
messages
Outlook mail messages on your default mailbox
outlook-email-pp-cli messages copy- Copy a message into another mail folderoutlook-email-pp-cli messages create-draft- Create a draft message (save without sending)outlook-email-pp-cli messages delete- Delete a message (moves to Deleted Items by default)outlook-email-pp-cli messages delta- Pull incremental message changes since the last delta tokenoutlook-email-pp-cli messages forward- Forward a message to new recipientsoutlook-email-pp-cli messages get- Get a message by idoutlook-email-pp-cli messages list- List messages across all foldersoutlook-email-pp-cli messages move- Move a message to another mail folderoutlook-email-pp-cli messages reply- Send a reply to a message (uses the original sender)outlook-email-pp-cli messages reply-all- Reply to all recipients of a messageoutlook-email-pp-cli messages send-draft- Send a previously-saved draft messageoutlook-email-pp-cli messages update- Update message fields (isRead, categories, flag, importance, subject, body)
rules
Inbox rules that automatically process incoming messages
outlook-email-pp-cli rules create- Create an inbox ruleoutlook-email-pp-cli rules delete- Delete an inbox ruleoutlook-email-pp-cli rules get- Get a single inbox ruleoutlook-email-pp-cli rules list- List inbox rulesoutlook-email-pp-cli rules update- Update an inbox rule
send_mail
Send a brand-new email in one shot (skips the drafts folder)
outlook-email-pp-cli send-mail- Compose and send a message without first saving to drafts
Output Formats
# Human-readable table (default in terminal, JSON when piped)
outlook-email-pp-cli attachments list mock-value
# JSON for scripting and agents
outlook-email-pp-cli attachments list mock-value --json
# Filter to specific fields
outlook-email-pp-cli attachments list mock-value --json --select id,name,status
# Dry run — show the request without sending
outlook-email-pp-cli attachments list mock-value --dry-run
# Agent mode — JSON + compact + no prompts in one flag
outlook-email-pp-cli attachments list mock-value --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--jsonoutput to stdout, errors to stderr - Filterable -
--select id,namereturns only fields you need - Previewable -
--dry-runshows the request without sending - Explicit retries - add
--idempotentto create retries and--ignore-missingto delete retries when a no-op success is acceptable - Confirmable -
--yesfor explicit confirmation of destructive actions - Piped input - write commands can accept structured input when their help lists
--stdin - Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendlyis set
Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.
Health Check
outlook-email-pp-cli doctor
Verifies configuration, credentials, and connectivity to the API.
Configuration
Config file: ~/.config/outlook-email-pp-cli/config.toml
Static request headers can be configured under headers; per-command header overrides take precedence.
Environment variables:
| Name | Kind | Required | Description |
|---|---|---|---|
OUTLOOK_EMAIL_TOKEN | per_call | Yes | Set to your API credential. |
Troubleshooting
Authentication errors (exit code 4)
- Run
outlook-email-pp-cli doctorto check credentials - Verify the environment variable is set:
echo $OUTLOOK_EMAIL_TOKENNot found errors (exit code 3) - Check the resource ID is correct
- Run the
listcommand to see available items
API-specific
- 401 Unauthorized after auth login — Run
outlook-email-pp-cli auth refresh. If still failing,auth statusshows scope and expiry. InvalidAuthenticationTokenmid-sync — Refresh token expired (>90 days). Runauth login --device-codeagain.- Mailbox not enabled for personal MSA — Open Outlook.com once with the account to provision the Exchange mailbox; then retry sync.
- Sync stalls on a folder — Run
sync --folder Inbox --resetto drop the delta token and re-pull the folder. - Search returns nothing but inbox has matches — Local search reads the SQLite FTS5 index — run
syncfirst. Use--serverto force$searchagainst Graph.
Sources & Inspiration
This CLI was built by studying these projects and resources:
- msgcli — Python
- outpost — Go
- outlook-mcp (sajadghawami) — TypeScript
- outlook-mcp (XenoXilus) — TypeScript
- outlook-mcp (ryaker) — TypeScript
- OutlookMCPServer — Python
- cowork-outlook-plugin — Python
- outlook-cli (mhattingpete) — Python
Generated by CLI Printing Press
For agents: pass /documentation/outlook-email/agents.md to install this CLI from a prompt.