inbox-cleanup
Bulk IMAP email triage: classify → delete/archive by sender domain, subject keywords, or custom patterns.
When to Use This / When NOT to Use This
Use inbox-cleanup when:
- - You need to bulk-delete or archive 50+ emails matching a pattern (sender domain, subject keyword)
- The inbox has a large backlog from known noisy senders (GitHub notifications, Slack digests, newsletters)
- You want a dry-run preview before committing any destructive action
- You need reproducible triage logic stored as config (not one-off manual clicks)
Do NOT use inbox-cleanup when:
- - Reading or searching for a specific email — use IMAP tools or webmail directly
- Triaging fewer than ~10 emails — just do it manually
- You want to reply, forward, or compose — this is delete/archive only
- You're unsure what's in the inbox — always dry-run first, never run live blind
Boundary with other skills: This skill does NOT read email content for decision-making (no NLP/LLM classification). It matches on sender domain and subject string patterns only. For content-aware triage, a different approach is needed.
⚠️ What NOT to Delete
Some email categories look like noise but must be preserved:
- - Transactional emails — order confirmations, shipping notices, receipts (needed for expense tracking)
- Auth codes / OTPs / 2FA emails — one-time codes, password resets
- Legal / compliance — invoices, tax docs, terms-of-service change notices
- Bank / financial — statements, transaction alerts
- Domain / hosting renewals — expiry notices from registrars, DNS providers
Safeguard pattern: Add these sender domains to leave_domains in your config. When in doubt, archive instead of delete.
CODEBLOCK0
Key Files
- -
scripts/inbox_cleanup.py — main cleanup script (dry-run by default) - INLINECODE2 — pattern config template
Quick Start
CODEBLOCK1
What a Successful Dry-Run Looks Like
When dry-run completes, you'll see output like:
CODEBLOCK2
If the numbers look wrong (e.g. 0 matches when you expected hundreds), check:
- 1. The
IMAP_HOST / IMAP_PORT / IMAP_USER env vars are set - The sender domains in your config match exactly (e.g.
noreply.github.com ≠ github.com) - The script connected to the right IMAP folder (default: INBOX)
Required Env Vars
CODEBLOCK3
Or use --imap-* CLI flags. See python3 scripts/inbox_cleanup.py --help.
Config File Format (YAML)
CODEBLOCK4
Design Notes
- - UIDs not sequence numbers: The script always uses
UID FETCH/UID STORE to
avoid message-renumbering bugs when messages are deleted mid-batch.
- - Dry-run by default: Always preview before committing. Pass
--no-dry-run to apply. - Batch fetching: Headers fetched in batches of 50 for large inboxes. One-at-a-time
fetch mode available with
--one-at-a-time for reliable UID tracking.
- - Progress logging: Stdout log with counts per domain and final report JSON.
- STARTTLS support: Needed for Proton Bridge (port 1143 with self-signed cert).
Secret Management
Credentials via env vars or 1Password:
CODEBLOCK5
Common Mistakes
- 1. Running live without a dry-run first
- Deleted emails may not be recoverable from all IMAP servers
- Always run
--dry-run first and review the counts
- 2. Domain mismatch — listing
github.com but emails come from noreply.github.com
- IMAP From headers often use subdomains. List both:
github.com AND
noreply.github.com
- Run dry-run and check the "0 matches" — then inspect an actual email's From header
- 3.
ARCHIVE_FOLDER doesn't exist in the mailbox
- The script will error on archive operations if the folder isn't pre-created
- Create the folder in webmail or your email client first
- 4. Proton Bridge not running when script executes
- Port 1143 will refuse the connection
- Ensure Proton Bridge desktop app is open and logged in before running
- 5.
leave_domains not populated
- Without
leave_domains, the script will happily delete emails from payment processors, banks, and auth providers if they match another rule
- Always populate
leave_domains before any live run
- 6. STARTTLS vs SSL confusion
- Direct IMAP SSL (Gmail, Fastmail):
IMAP_PORT=993,
IMAP_STARTTLS=false
- Proton Bridge local proxy:
IMAP_PORT=1143,
IMAP_STARTTLS=true,
IMAP_SKIP_CERT_VERIFY=true
- Mixing these up causes connection failures or cert errors
inbox-cleanup
批量IMAP邮件分类:通过发件人域名、主题关键词或自定义模式进行分类 → 删除/归档。
何时使用 / 何时不使用
使用inbox-cleanup的场景:
- - 需要批量删除或归档50+封符合特定模式(发件人域名、主题关键词)的邮件
- 收件箱中存在大量来自已知噪音发件人(GitHub通知、Slack摘要、新闻通讯)的积压邮件
- 在执行破坏性操作前,希望先进行预览(dry-run)
- 需要将可复现的分类逻辑存储为配置文件(而非一次性手动操作)
不要使用inbox-cleanup的场景:
- - 需要阅读或搜索特定邮件——请直接使用IMAP工具或网页邮箱
- 需要分类的邮件少于约10封——手动处理即可
- 需要回复、转发或撰写邮件——本工具仅支持删除/归档操作
- 不确定收件箱内容——务必先执行dry-run,切勿盲目直接运行
与其他技能的边界: 本技能不会读取邮件内容进行决策(无NLP/LLM分类)。仅基于发件人域名和主题字符串模式进行匹配。如需内容感知分类,需采用其他方法。
⚠️ 不应删除的内容
某些邮件类别看似噪音,但必须保留:
- - 交易邮件 — 订单确认、发货通知、收据(用于费用追踪)
- 验证码/一次性密码/双因素认证邮件 — 一次性验证码、密码重置
- 法律/合规邮件 — 发票、税务文件、服务条款变更通知
- 银行/金融邮件 — 账单、交易提醒
- 域名/主机续费邮件 — 注册商、DNS提供商的到期通知
保护措施: 将这些发件人域名添加到配置文件的 leave_domains 中。如有疑问,选择归档而非删除。
yaml
leave_domains:
- ato.gov.au # 澳大利亚税务局
- myob.com # 会计软件
- godaddy.com # 域名注册商
- cloudflare.com # DNS/主机
- stripe.com # 支付
- paypal.com # 支付
- no-reply@apple.com # Apple收据
关键文件
- - scripts/inboxcleanup.py — 主清理脚本(默认dry-run模式)
- scripts/configexample.yaml — 模式配置模板
快速开始
bash
步骤1:始终先执行dry-run — 不做任何更改,仅预览
python3 scripts/inbox
cleanup.py --config mypatterns.yaml --dry-run
步骤2:检查输出。如果看起来正确:
python3 scripts/inbox
cleanup.py --config mypatterns.yaml
成功Dry-Run的输出示例
dry-run完成后,您将看到类似输出:
[DRY RUN] 将删除来自github.com的142封邮件
[DRY RUN] 将删除来自slack.com的38封邮件
[DRY RUN] 将归档来自notion.so的17封邮件
[DRY RUN] 将归档匹配关键词newsletter的9封邮件
[DRY RUN] 跳过来自leave_domains的3封邮件(stripe.com, paypal.com)
─────────────────────────────────────────────
总计将删除:180
总计将归档:26
总计跳过(leave_domains):3
如果数字看起来不对(例如预期数百封但显示0匹配),请检查:
- 1. 是否已设置 IMAPHOST / IMAPPORT / IMAP_USER 环境变量
- 配置文件中的发件人域名是否完全匹配(例如 noreply.github.com ≠ github.com)
- 脚本是否连接到了正确的IMAP文件夹(默认:INBOX)
必需的环境变量
bash
IMAP_HOST=127.0.0.1 # IMAP服务器主机(Proton Bridge本地代理使用127.0.0.1)
IMAP_PORT=1143 # 端口:993 = 直接SSL,1143 = Proton Bridge STARTTLS
IMAP_USER=you@example.com # 您的IMAP登录用户名
IMAP_PASSWORD=yourpassword # IMAP密码(可使用op read从1Password读取)
IMAP_STARTTLS=true # true = 连接后升级STARTTLS(Proton Bridge);false = 从一开始使用SSL
IMAPSKIPCERT_VERIFY=true # true = 接受自签名证书(Proton Bridge必需)
ARCHIVE_FOLDER=Archive # 归档邮件移入的IMAP文件夹名称(必须已存在)
或使用 --imap-* 命令行参数。详见 python3 scripts/inbox_cleanup.py --help。
配置文件格式(YAML)
yaml
应永久删除的发件人域名
delete_domains:
- github.com # GitHub通知(Issues、PRs、Actions)
- noreply.github.com # GitHub无回复(不同子域名——如需请同时列出)
- slack.com # Slack摘要/通知邮件
应移至归档(而非删除)的发件人域名
archive_domains:
- notion.so # Notion分享通知
- coinbase.com # 加密货币价格提醒
主题关键词——匹配任一关键词的邮件将被归档(不区分大小写)
archive_keywords:
- newsletter # 匹配The Weekly Newsletter、Newsletter #42等
- digest # Daily Digest、Weekly Digest
- weekly roundup # 精确子字符串匹配
主题正则表达式模式——匹配任一模式的邮件将被删除
注意:模式使用Python re.search()——如需行首匹配请使用^锚定
delete
subjectpatterns:
- ^\\[GitHub\\] # 以[GitHub]开头的主题
绝不应触碰的发件人域名——覆盖所有其他规则
在此添加银行、支付处理商、认证提供商、注册商
leave_domains:
- important-bank.com
- stripe.com
- paypal.com
设计说明
- - 使用UID而非序列号:脚本始终使用 UID FETCH/UID STORE 以避免在批量删除邮件时出现消息重新编号错误。
- 默认dry-run:在提交操作前始终预览。使用 --no-dry-run 执行实际操作。
- 批量获取:对于大型收件箱,以50封为一批获取邮件头。可使用 --one-at-a-time 模式逐封获取以确保UID跟踪可靠。
- 进度日志:标准输出日志包含每个域名的计数和最终报告JSON。
- STARTTLS支持:Proton Bridge需要此功能(端口1143,使用自签名证书)。
密钥管理
通过环境变量或1Password提供凭据:
bash
通过环境变量
export IMAP_PASSWORD=$(op read op://Vault/Email Account/password)
python3 scripts/inbox_cleanup.py --config patterns.yaml
常见错误
- 1. 未先执行dry-run就直接运行
- 某些IMAP服务器可能无法恢复已删除的邮件
- 始终先运行 --dry-run 并检查计数
- 2. 域名不匹配——列出github.com但邮件来自noreply.github.com
- IMAP的From头通常使用子域名。同时列出两者:github.com 和 noreply.github.com
- 运行dry-run检查0匹配——然后检查实际邮件的From头
- 3. 邮箱中不存在ARCHIVE_FOLDER
- 如果文件夹未预先创建,脚本在执行归档操作时会报错
- 先在网页邮箱或邮件客户端中创建该文件夹
- 4. 执行脚本时Proton Bridge未运行
- 端口1143将拒绝连接
- 运行前确保Proton Bridge桌面应用已打开并登录
- 5. 未填充leave_domains
- 如果没有leave_domains,脚本会愉快地删除来自支付处理商、银行和认证提供商的邮件(如果它们匹配其他规则)
- 在任何实际运行前务必填充leave_domains
- 6. STARTTLS与SSL混淆
- 直接IMAP SSL(Gmail、Fastmail):IMAP
PORT=993,IMAPSTARTTLS=false
- Proton Bridge本地代理:IMAP
PORT=1143,IMAPSTARTTLS=true,IMAP
SKIPCERT_VERIFY=true
- 混淆这些设置会导致连接失败或证书错误