Iris Pro — Inbox Intelligence — Iris Pro — 收件箱智能
v1.0.0Iris Pro — Inbox Intelligence,阅读您的Gmail收件箱,根据紧急程度和发送者重要性对每封电子邮件进行评分,并为每个动作草拟完整的个性化回复...
运行时依赖
安装命令
点击复制本土化适配说明
Iris Pro — Inbox Intelligence — Iris Pro — 收件箱智能 安装说明: 安装命令:["openclaw skills install iris-pro"]
技能文档
Iris Pro — 全面的收件箱智能功能 Iris 的所有功能,以及无限的草稿回复、电子邮件分类、每周分析和自定义回复语气。
Pro 版本与免费版 Iris 的比较 功能 | Iris(免费) | Iris Pro -----|----------|-------- 扫描的电子邮件 | 50 | 最多 200 草稿回复 | 前 5 个 | 所有的可操作电子邮件 回复语气 | 标准 | 专业 / 友好 / 简洁 电子邮件分类 | — | 销售、人力资源、法律、财务、支持 每周分析 | — | 趋势图 + 平均响应时间、噪音统计、发送者详细信息 报告格式 | Markdown | Markdown + 结构化 JSON
设置
- 获取您的许可密钥:在 ko-fi.com/occupythemilkyway 购买许可密钥。
- 设置环境变量:将许可密钥设置为 LICENSE_KEY。
- 创建 Gmail 应用密码:在 myaccount.google.com/apppasswords 创建应用密码。
- 安装:运行 pip3 install rich --break-system-packages --quiet 安装 rich 库。
步骤 1 — 安装
pip3 install rich --break-system-packages --quiet
步骤 2 — 分类收件箱(Pro)
```python
import os
import imaplib
import email
import re
import json
from email.header import decode_header
from email.utils import parsedate_to_datetime
from datetime import datetime, timezone, timedelta
from collections import defaultdict
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import boxconsole = Console() LICENSE_KEY = os.environ.get("LICENSE_KEY", "").strip() if not LICENSE_KEY: console.print(Panel("[red bold]需要许可密钥[/red bold]\n\n" "获取许可密钥:[bold cyan]ko-fi.com/occupythemilkyway[/bold cyan]\n\n" "或使用免费版本:[dim]openclaw skills install iris[/dim]", title="许可密钥要求", border_style="red")) raise SystemExit(1)
GMAIL_ADDR = os.environ.get("GMAIL_ADDRESS", "").strip() GMAIL_PASS = os.environ.get("GMAIL_APP_PASSWORD", "").strip() try: SCAN_COUNT = min(int(os.environ.get("SCAN_COUNT", "100")), 200) except ValueError: SCAN_COUNT = 100
VIP_RAW = os.environ.get("VIP_SENDERS", "") VIP_LIST = [v.strip().lower() for v in VIP_RAW.split(",") if v.strip()] YOUR_NAME = os.environ.get("YOUR_NAME", "").strip() YOUR_ROLE = os.environ.get("YOUR_ROLE", "").strip() REPLY_TONE = os.environ.get("REPLY_TONE", "professional").lower().strip()
if not GMAIL_ADDR or not GMAIL_PASS: console.print(Panel("[red]GMAIL_ADDRESS 和 GMAIL_APP_PASSWORD 是必需的[/red]", title="设置错误", border_style="red")) raise SystemExit(1)
URGENT_KEYWORDS = ["urgent", "asap", "deadline", "immediately", "action required", "time sensitive", "overdue", "past due", "invoice", "payment due", "legal", "lawsuit", "critical", "emergency", "final notice", "expires", "expiring", "last chance", "must respond"] REPLY_KEYWORDS = ["?", "question", "can you", "could you", "please", "request", "following up", "follow-up", "reminder", "let me know", "thoughts", "feedback"] QUESTION_KW = ["?", "question", "can you", "could you", "help", "assist"] NOISE_PATTERNS = [r"unsubscribe", r"newsletter", r"no-reply@", r"noreply@", r"marketing@", r"notifications?@", r"donotreply@", r"@.*\.(mailchim|sendgrid|constantcontact|klaviyo)"]
# Pro:电子邮件分类器 CATEGORY_KEYWORDS = { "Sales": ["quote", "proposal", "partnership", "deal", "pricing", "discount", "demo", "trial"], "HR": ["onboarding", "payroll", "benefits", "vacation", "leave", "performance", "hiring", "interview"], "Legal": ["contract", "agreement", "terms", "compliance", "gdpr", "lawsuit", "legal", "attorney", "counsel"], "Finance": ["invoice", "payment", "overdue", "refund", "billing", "expense", "budget", "receipt"], "Support": ["issue", "bug", "error", "help", "ticket", "problem", "broken", "not working", "downtime"], "General": [], }
def classify_category(subject: str, snippet: str) -> str: text = (subject + " " + snippet).lower() for cat, keywords in CATEGORY_KEYWORDS.items(): if cat == "General": continue if any(k in text for k in keywords): return cat return "General"
def decode_str(s): if not s: return "" parts = decode_header(s) result = [] for part, enc in parts: if isinstance(part, bytes): result.append(part.decode(enc or "utf-8", errors="replace")) else: result.append(str(part)) return " ".join(result)
def is_noise(sender: str, subject: str) -> bool: text = (sender + " " + subject).lower() return any(re.search(p, text) for p in NOISE_PATTERNS)
def score_email(subject, snippet, sender, age_hours, has_replied): score = 50 text = (subject + " " + snippet).lower() if any(k in text for k in URGENT_KEYWORDS): score += 20 if any(k in text for k in REPLY_KEYWORDS): score += 10 if any(vip in sender.lower() for vip in VIP_LIST): score += 25 if age_hours < 2: score += 5 elif age_hours > 48: score -= 10 elif age_hours > 120: score -= 20 if has_replied: score -= 15 return max(0, min(100, score))