Email Cleanup
/install inbox-cleanup-outlook
Inbox Cleanup & Rules (Outlook)
This skill covers both one-time inbox cleanup and ongoing rule automation for Microsoft 365 / Outlook. The workflow uses the Microsoft Graph API for folder management and server-side inbox rules.
When to Use This Skill
Use when the user's inbox has become noisy — automated notifications drowning out human conversations, newsletters mixed with client emails, or hundreds of unread messages that make it hard to find what matters.
Real trigger example: A user's partner email went unread for 9 days because it was buried under GitHub and npm notifications. This is the exact problem server-side rules solve.
Trust Boundary: What This Skill Can and Cannot Enforce
Before you install or grant OAuth consent, understand where the safety boundary lies.
This skill is instruction-only. It ships no code, executes nothing by itself, and cannot enforce any of the safety protections described below. Everything in the "Rule Security Model" and "Authentication & Required Scopes" sections is enforced (or not enforced) by whichever runtime actually executes the Microsoft Graph API calls. The skill file is a set of instructions, not a sandbox.
What that means in practice
- The blocked-actions list (
forwardTo,redirectTo,delete, etc.) describes what a trusted runtime SHOULD reject. Whether those actions are actually rejected depends on the runtime. If you useemail-agent-mcp, rejection is built into the action handler (rules.ts:39). If you use a raw Graph API client or a custom MCP without equivalent guards, the protections do not automatically apply. MailboxSettings.ReadWriteis a high-risk scope because it controls inbox rules — and inbox rules can be configured to forward or redirect mail externally. Granting the scope without a runtime that enforces the blocked-actions list gives up the primary mitigation.- Autonomous invocation (where the agent runs this skill without per-call approval) is a platform-level setting, not something the skill controls. Combined with write scopes, it increases the surface area of any runtime weakness.
Before installing or granting consent
This skill requests a high-risk mailbox-rule permission (MailboxSettings.ReadWrite). Review the five items below before you grant consent. They are the exact things to check; the skill cannot enforce any of them for you.
- Only grant
MailboxSettings.ReadWriteif you trust the runtime that will execute these instructions. The skill itself cannot enforce the blocked-actions list (forwardTo,forwardAsAttachmentTo,redirectTo,delete,permanentDelete). Verify your runtime does. - Prefer audit-only scopes (
MailboxSettings.Read) — or omit rule creation entirely — if you do not need automated rule management. Folder operations and batch moves work with justMail.ReadWrite. - If you must grant full scopes, use a vetted runtime that enforces blocking of forward/redirect/delete actions at the action handler. The reference runtime
email-agent-mcpdoes this atrules.ts:39— inspect the code yourself. Alternatively, add network-level protections (for example, NemoClaw) to block Graph endpoints that create dangerous rules. - Test on a non-production account first. Be prepared to revoke OAuth consent and invalidate refresh tokens at https://myaccount.microsoft.com/consent if anything looks wrong or misconfigured.
- Avoid enabling autonomous invocation for this skill unless you understand and trust the runtime's guardrails. Autonomous invocation combined with
MailboxSettings.ReadWritegives the agent the ability to create inbox rules without per-call user approval — only safe if the runtime enforces the blocked-actions list.
Authentication & Required Scopes
This skill operates against Microsoft Graph and requires an OAuth 2.0 delegated access token for a Microsoft 365 account.
Minimum scopes by use case
| Use case | Scopes required |
|---|---|
| Audit existing folders and inbox rules (read-only) | Mail.Read, MailboxSettings.Read, offline_access |
| Create folders and move existing email | + Mail.ReadWrite |
| Create and delete server-side inbox rules | + MailboxSettings.ReadWrite |
This skill does not require Mail.Send — inbox cleanup never sends email.
Token storage
The reference runtime stores OAuth tokens in the OS keychain (macOS Keychain / Windows Credential Manager / Linux libsecret) via MSAL with @azure/identity-cache-persistence. No raw passwords. No plain text token files. Refresh tokens are handled silently by MSAL.
Risk mapping — scopes to exfiltration risk
| Scope | Enables | Risk if misused |
|---|---|---|
Mail.Read |
Read any message, folder, and attachment | Read-only; no exfiltration beyond the agent session |
Mail.ReadWrite |
Create folders, move/copy messages | Low on its own — no outbound mail capability |
MailboxSettings.ReadWrite |
Create and delete inbox rules | HIGH — malicious rules with forwardTo/redirectTo can exfiltrate mail silently even after the session ends |
offline_access |
Refresh tokens without re-auth | Low on its own; extends the blast radius of any other scope if the token is stolen |
MailboxSettings.ReadWrite is the only HIGH-risk scope this skill needs. It is mitigated by the reference runtime's hard block on dangerous rule actions (see "Rule Security Model" below).
Reference runtime guardrails
This skill is instruction-only — it cannot enforce any guardrails by itself. The protections below are provided by the runtime that actually executes the Graph API calls, not by this skill.
If you use email-agent-mcp as the runtime, it blocks dangerous inbox rule actions at the action handler level — forwardTo, forwardAsAttachmentTo, redirectTo, delete, permanentDelete — and rejects any rule creation attempt that includes them. Source: packages/email-core/src/actions/rules.ts:39.
If you use a different runtime (raw Graph API client, custom MCP server), these protections are NOT automatically present. You should either layer NemoClaw network policy, restrict OAuth scopes, or use a runtime that provides equivalent guardrails.
Hardening recipes
- Audit mode only — grant
MailboxSettings.Read(without.ReadWrite) if you want the agent to review existing rules without being able to create or modify them. The cleanup workflow below will still work for folder management. - Don't grant
MailboxSettings.ReadWriteif you don't need automated rule creation. Folder management and batch moves work with justMail.ReadWrite. - Layer NemoClaw — see the NemoClaw Email Policy skill to block dangerous Graph endpoints at the network layer regardless of scope grants.
The Cleanup Workflow
This workflow was battle-tested on a 2,500+ email cleanup. Follow the steps in order.
Step 1 — Scan Before Creating Folders
Don't guess what folders to create. Let the data tell you.
Fetch the last 200 inbox emails and count by sender address:
GET /me/messages?$top=200&$select=from,receivedDateTime&$orderby=receivedDateTime desc
Group by from.emailAddress.address, sort by count descending. The top automated senders are the ones to filter.
MCP: Use list_emails(max_results=200, fields=["fromAddress", "receivedDateTime"]) and count programmatically.
Step 2 — Categorize by Action Required
Don't organize by sender type (that is arbitrary). Organize by what the user needs to do:
| Category | Action | Examples |
|---|---|---|
| Glance, don't act | Skim the subject line, archive | GitHub CI, Azure DevOps builds, npm advisories, DMARC reports |
| Read when time allows | Set aside for a slow moment | Newsletters, marketing from known vendors |
| Archive for records | Keep but don't read now | Receipts, invoices, payment confirmations |
| May need action | Review and decide | Meeting bookings, compliance alerts, security notifications |
| Default: don't filter | Leave in inbox | Human conversations (colleagues, clients, partners) |
The last row is important: human conversations stay in inbox unless the user specifically requests otherwise. The goal is to remove noise, not to hide signal.
Step 3 — Create Folders
Keep it to 5-9 folders. More than that and the user stops checking them. The right test: "Would I check this folder at least weekly?" If no, it should be a subfolder or merged into a broader category.
REST API:
POST /me/mailFolders
{"displayName": "Dev Notifications"}
MCP: create_folder("Dev Notifications")
Step 4 — Batch-Move Existing Email
Rules only apply to future mail. After creating folders, move all existing matching emails.
REST API:
GET /me/messages?$filter=from/emailAddress/address eq '[email protected]'&$top=50
Then for each message:
POST /me/messages/{id}/move
{"destinationId": "\x3Cfolder-id>"}
Paginate with @odata.nextLink — some senders will have hundreds of messages. Process 50 at a time.
MCP: move_to_folder(email_id, "Dev Notifications") handles ID resolution. Loop through search results.
Step 5 — Create Server-Side Rules
Server-side rules run on Microsoft's servers — they work 24/7, even when no agent is running.
REST API:
POST /me/mailFolders/inbox/messageRules
{
"displayName": "GitHub to Dev Notifications",
"sequence": 1,
"isEnabled": true,
"conditions": {
"fromAddresses": [
{"emailAddress": {"address": "[email protected]"}}
]
},
"actions": {
"moveToFolder": "\x3Cfolder-id>",
"stopProcessingRules": true
}
}
MCP: create_inbox_rule({displayName: "GitHub to Dev Notifications", conditions: {fromAddresses: [{email: "[email protected]"}]}, actions: {moveToFolder: "\x3Cfolder-id>", markAsRead: true}})
Step 6 — Re-Sweep After Rule Creation
Rules and email arrival can race. After creating rules, wait a few minutes, then re-run the batch move from Step 4 to catch any emails that arrived between rule creation and activation.
Rule Ordering
The sequence field controls which rules fire first. Lower sequence = higher priority.
This matters because: A generic "any noreply@ sender goes to Newsletters" rule will swallow meeting booking notifications from [email protected] if it fires first.
Fix: Create specific rules with lower sequence numbers before broad rules.
sequence 1: HubSpot meeting bookings → Meetings folder
sequence 2: noreply@ senders → Newsletters folder
Always set stopProcessingRules: true on each rule to prevent cascade.
Rule Security Model
Not all rule actions are safe. Agents should never create rules with the actions listed below. This skill is instruction-only — it cannot enforce these restrictions itself. The agent's runtime is what actually makes (or blocks) the API calls.
If your runtime is email-agent-mcp, it rejects rule creation attempts that include any of these actions and returns a BLOCKED_ACTION error. Source: rules.ts:39. If you use a different runtime, you should verify it provides equivalent enforcement, or layer network-level controls (e.g. NemoClaw).
Block these actions:
| Action | Risk |
|---|---|
forwardTo |
Could exfiltrate email to external addresses |
forwardAsAttachmentTo |
Same risk |
redirectTo |
Same risk |
delete |
Data loss |
permanentDelete |
Irreversible data loss |
These actions are safe:
| Action | Effect |
|---|---|
moveToFolder |
Move to a folder ID |
copyToFolder |
Copy to a folder ID |
markAsRead |
Mark as read |
markImportance |
Set importance level (low/normal/high) |
stopProcessingRules |
Prevent later rules from firing |
If the user asks for a forwarding rule, ask them to confirm the destination address explicitly before creating it.
Common Conditions
| Condition | Use |
|---|---|
fromAddresses |
Exact sender match: [{emailAddress: {address: "..."}}] |
subjectContains |
Words in subject: ["[npm]", "advisory"] |
senderContains |
Partial sender match: ["github.com"] |
headerContains |
Match email headers |
Graph API Gotchas
These are production-discovered issues — not theoretical:
-
$selecton PATCH = 400 —$selectdoes not work on PATCH requests. Returns "OData request not supported." Only use$selecton GET. -
Move is POST, not PATCH —
POST /me/messages/{id}/movewith{"destinationId": "\x3Cid>"}. -
$filterwith sender address —$filter=from/emailAddress/address eq '...'works reliably. URL-encode the filter value. -
Uppercase in storage — Outlook uppercases
senderContainsvalues (e.g.,[email protected]). This is cosmetic — matching is case-insensitive. -
Root-only folder listing —
GET /me/mailFolders?$top=100returns only root-level folders. Child folders require/mailFolders/{id}/childFolders. -
Pagination — Large mailboxes can have hundreds of folders. Always check for and follow
@odata.nextLink.
Verification
After creating rules:
GET /me/mailFolders/inbox/messageRules— verify the rule exists and is enabled- Check
hasErrorfield — iftrue, the rule has a configuration issue - Send a test email matching the rule conditions and verify it lands in the correct folder
Feedback
If this skill helped, star us on GitHub: https://github.com/UseJunior/email-agent-mcp
On ClawHub: clawhub star stevenobiajulu/inbox-cleanup-outlook
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install inbox-cleanup-outlook - 安装完成后,直接呼叫该 Skill 的名称或使用
/inbox-cleanup-outlook触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Email Cleanup 是什么?
Organize a cluttered Outlook inbox with folders, batch moves, and server-side inbox rules via the Microsoft Graph API. Use when user says "clean up my inbox,... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 122 次。
如何安装 Email Cleanup?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install inbox-cleanup-outlook」即可一键安装,无需额外配置。
Email Cleanup 是免费的吗?
是的,Email Cleanup 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。
Email Cleanup 支持哪些平台?
Email Cleanup 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Email Cleanup?
由 Steven Obiajulu(@stevenobiajulu)开发并维护,当前版本 v0.1.4。