Outlook native
Query, search, and extract Outlook email content, compose rich HTML Outlook drafts with inline images, and organize a mailbox with folders and server-side rules. Use this skill whenever the user wants to search their Outlook mailbox, extract or export emails (查邮件/提取邮件/导出邮件), parse .ost or .pst files, summarize email threads, draft/backfill an Outlook email (回填邮件/生成草稿/写邮件到Outlook), or tidy up their inbox (整理邮箱/建文件夹/建规则/归档邮件). Trigger even if the user only mentions "my Outlook", "mailbox", an .ost/.pst file path, or pasting HTML into an email that broke its formatting.From its SKILL.md
npx -y skills add mc856/outlook-native --skill outlook-nativeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 25 days oldThe repository was created 25 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
11.8 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
Outlook Mail: Query, Compose & Organize
Three capabilities, each with environment-appropriate backends:
- Query — search/extract email content (subject, body, sender, recipients, dates, attachments)
- Compose — create an Outlook draft with Word-engine-safe HTML and inline images (never auto-send)
- Organize — create Inbox subfolders + server-side rules, and file the existing backlog
Step 0: Route by environment
Detect first — do not assume:
powershell -Command "(New-Object -ComObject Outlook.Application).Name" # succeeds => live COM
On a Linux/macOS shell, skip the probe and go straight to the offline path.
| Environment | Query | Compose | Organize |
|---|---|---|---|
| Windows PC, classic Outlook installed (Claude Code, Codex, any local agent) | scripts/query_com.ps1 — live, fast, complete | scripts/create_draft.ps1 — draft opens in Outlook | scripts/organize_mailbox.ps1 |
| Linux/macOS sandbox (Cowork, remote) — no Outlook process | scripts/query_ost.py against a mounted .ost/.pst | emit HTML + images + create_draft.ps1 to a user-visible folder; user right-clicks → "Run with PowerShell" | not possible — OST parsing is read-only; hand the user the config + script to run locally |
| New Outlook only, no classic | no OST exists to parse — ask the user to install/enable classic Outlook, or drive OWA | paste-via-Word (references/outlook-html.md) | user does it in the New Outlook UI |
PowerShell here is Windows PowerShell 5.1, not 7 — see the BOM and stream-pollution traps in references/troubleshooting.md before writing any .ps1 with non-ASCII in it.
Finding the data files — never hardcode the path
%LOCALAPPDATA%\Microsoft\Outlook\*.ost is only the default. Enterprises routinely relocate the
whole store with group policy — e.g. onto a D:\ data drive.
Resolve it in this order:
# 1. Authoritative, when Outlook is reachable: ask it.
$ns.Stores | ForEach-Object { "{0} | type={1} | {2}" -f $_.DisplayName, [int]$_.ExchangeStoreType, $_.FilePath }
# ExchangeStoreType 0 = Exchange mailbox (syncs to cloud); 2 = local .pst (never syncs)
# 2. Offline / Outlook not running: the relocation policy.
Get-ItemProperty "HKCU:\Software\Policies\Microsoft\Office\16.0\Outlook" |
Select-Object forceostpath, forcepstpath # e.g. forceostpath = D:\OutlookData
# 3. Which profile is active.
(Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Office\16.0\Outlook").DefaultProfile
# 4. Last resort: search both the default location and any policy path.
Get-ChildItem "$env:LOCALAPPDATA\Microsoft\Outlook\*.ost", "<policyPath>\*.ost" -ErrorAction SilentlyContinue
Reference paths:
| What | Where |
|---|---|
| Classic OST (default) | %LOCALAPPDATA%\Microsoft\Outlook\*.ost |
| Classic OST (relocated) | whatever forceostpath says |
| Archive PST | %USERPROFILE%\Documents\Outlook Files\*.pst, or forcepstpath |
| New Outlook cache | %LOCALAPPDATA%\Microsoft\Olk\ — WebView2 IndexedDB, not an OST, do not parse |
| Outlook profiles | HKCU:\SOFTWARE\Microsoft\Office\16.0\Outlook\Profiles\<profile> |
In a sandbox, tell the user the resolved path to mount rather than guessing — and note the OST is locked while Outlook runs, so they must close Outlook or copy the file.
New Outlook (Monarch) — what it actually is
New Outlook is an Edge WebView2 wrapper around outlook.office.com, not a mail client with a local store. Verified layout:
%LOCALAPPDATA%\Microsoft\Olk\ process: olk.exe
└─ EBWebView\Default\IndexedDB\
├─ https_outlook.office.com_0.indexeddb.leveldb mail metadata (Chromium LevelDB)
└─ https_outlook.office.com_0.indexeddb.blob images only — NO mail bodies
Consequences, in priority order:
- There is no OST/PST.
libpff/pypffis inapplicable — it parses PST/OST only. - Do not try to parse the IndexedDB. It is a dead end: locked and live-compacting under
olk.exe, ~1% of the mailbox (a rolling window), and it requires stacking LevelDB + Chromium IndexedDB key encoding + Blink structured-clone + Microsoft's undocumented OWA schema. Any parser built today breaks on the next update. - The authoritative mailbox is Exchange Online. Both the OST and the Olk cache are just caches.
- Therefore: prefer classic Outlook COM even when the user lives in New Outlook. Folders and rules are server-side (see Workflow C), so changes made through classic COM appear in New Outlook automatically. Classic and New can both be installed; check with
Get-Process olk, OUTLOOK.
If classic Outlook is not installed at all: query via OST parsing is impossible (no OST exists), so fall back to asking the user to export, or drive the OWA UI. For compose, deliver the HTML with paste-via-Word instructions (references/outlook-html.md).
Classic Outlook present but its data looks stale? A classic profile only syncs while it is actually running with a signed-in session. A profile untouched for weeks reports Offline=False yet returns no recent mail, and a COM-launched headless instance is often too short-lived to finish an incremental resync. Check $ns.ExchangeConnectionMode — see the enum table in references/troubleshooting.md, and note 400 means disconnected, not connected. Fix: have the user open Outlook normally and leave it running until the status bar reads "Connected"; a multi-week backfill can take an hour.
Workflow A: Query emails
Live (COM)
# keyword search across Inbox + Sent, last 90 days, export CSV
powershell -ExecutionPolicy Bypass -File scripts/query_com.ps1 `
-Keyword "hackathon" -Since "2026-01-01" -Folders Inbox,SentMail `
-OutCsv results.csv -IncludeBody
Run scripts/query_com.ps1 -? style inspection (read the param block) for all options. Output CSV is UTF-8 BOM so Excel opens Chinese/Unicode correctly.
Offline (.ost / .pst)
pip install libpff-python --break-system-packages # module imports as pypff
python3 scripts/query_ost.py \
--files "/path/to/mailbox.ost" \
--keyword "hackathon|黑客松" \
--out ./mail_out --budget 30
Important behaviors baked into the script (read them, don't re-derive):
- Checkpoint/resume: large OSTs (multi-GB) can't be scanned inside one shell-call timeout, and background processes do not survive between calls in sandboxes. The script scans for
--budgetseconds then exits with state saved; simply re-run the identical command until it printsALL_DONE. - Sent-items recipient backfill: sent/draft messages in OST files usually have no transport headers, so To/Cc looks empty. The script reads MAPI properties PR_DISPLAY_TO (0x0E04) / PR_DISPLAY_CC (0x0E03) from the message record set to recover display-name recipients. Without this, any "emails I sent to X" filter silently loses most results.
- Output:
matches.jsonl(full bodies for later use) +summary.csv(UTF-8 BOM, Excel-ready preview).
If the OST is locked by a running Outlook, ask the user to close Outlook or copy the file first.
Query hygiene (both backends)
- Deduplicate: the same message often exists in multiple folders (Inbox copy + Sent copy + Deleted). Key on (date, sender, subject, folder) when listing; on (date, subject) when the user wants unique conversations.
- Offer to filter automated senders (Microsoft Forms, GitLab, SharePoint, no-reply/noreply, Teams/Yammer notifications) — they typically dominate keyword matches and users almost always want them separated out.
- HTML bodies: strip
<style>/<script>then tags for previews; keep the raw body in JSONL because the user often wants full content later.
Workflow B: Compose / backfill a draft
- Write the email body following references/outlook-html.md — Outlook desktop renders with the Word engine, so browser-grade CSS silently breaks. That reference contains the safe-markup rules plus copy-paste snippets (stat cards, ranking tables, image grids, section headers) that survive Word rendering.
- Put referenced images next to the HTML (e.g.
images/*.png) using plain relativesrc="images/name.png". - Create the draft with
scripts/create_draft.ps1:
powershell -ExecutionPolicy Bypass -File scripts/create_draft.ps1 `
-Html final.html -Subject "My Subject" -To "[email protected]" -Cc "[email protected]"
The script attaches every locally-referenced image as a hidden inline attachment, sets its Content-ID, rewrites src to cid:, sets HTMLBody, and calls .Display() — so the user reviews and sends manually. Never modify it to send automatically: drafts are the safety boundary of this skill.
If you cannot execute PowerShell (sandbox), place create_draft.ps1 + HTML + images together in a folder the user can see and tell them: right-click the .ps1 → "使用 PowerShell 运行" / "Run with PowerShell". Warn that classic desktop Outlook is required.
Workflow C: Organize a mailbox (folders + rules + backlog)
Use scripts/organize_mailbox.ps1 with a JSON config. Read references/mailbox-organize.md first — it covers the server-side model, the client-only-rule trap, and the COM landmines that make rule creation fail with a useless error message.
# 1. always dry-run first
powershell -ExecutionPolicy Bypass -File scripts/organize_mailbox.ps1 -Config plan.json -Mode Plan -DoFolders -DoRules -DoBacklog
# 2. folders must exist before rules/backlog can reference them
powershell -ExecutionPolicy Bypass -File scripts/organize_mailbox.ps1 -Config plan.json -Mode Apply -DoFolders
powershell -ExecutionPolicy Bypass -File scripts/organize_mailbox.ps1 -Config plan.json -Mode Apply -DoRules
powershell -ExecutionPolicy Bypass -File scripts/organize_mailbox.ps1 -Config plan.json -Mode Apply -DoBacklog
Method that works well:
- Profile before designing. Dump every inbox message's sender + unread flag to CSV, then group by sender. The folder scheme should follow the actual volume distribution, not a generic GTD template. In real mailboxes ~40–60% of the inbox is broadcast/notification noise from <40 distinct senders.
- Design folders from that profile, numbered (
01_,10_,30_…) so ordering is stable. - Rules match on sender ADDRESS, never display name. Display names must resolve in the GAL; system senders (
itnoreply,SharePoint Online,Workday…) usually do not, and an unresolved recipient makes the rule silently never match. Get real addresses first via$msg.Sender.GetExchangeUser().PrimarySmtpAddress. An alias fragment (opsalerts) matches both the SMTP form and the X500 form. - Rule actions: move only. Anything else demotes the rule to client-only.
- File the backlog with explicit per-sender queries, not "Run Rules Now" — every move is then counted and reportable, and New Outlook has no global Run Rules Now anyway.
- Move, never delete. Everything stays reversible.
Report volumes per folder before applying so the user can sanity-check the split.
Common failure modes
Read references/troubleshooting.md when you hit: COM errors, rules that refuse to save, locked OST files, garbled encodings, emoji in PowerShell strings, pypff install failures, stale classic profiles, or pasted-HTML formatting loss. It documents fixes verified in real sessions.
What ships with it: 7 files
42.6 KB alongside SKILL.md, 4 of them executable
references/
- mailbox-organize.md6.3 KB
- outlook-html.md4.5 KB
- troubleshooting.md8.1 KB
scripts/
- create_draft.ps1runs2.2 KB
- organize_mailbox.ps1runs9.5 KB
- query_com.ps1runs3.8 KB
- query_ost.pyruns8.2 KB