Iris Lite — Inbox Intelligence (Free) — Iris Lite — 收件箱智能(免费)
v1.0.0Iris Lite — Inbox Intelligence(免费)。扫描您最近的25封Gmail邮件,显示紧急程度评分和优先列表,并草拟2条快速回复。一个免费的试用...
运行时依赖
安装命令
点击复制本土化适配说明
Iris Lite — Inbox Intelligence (Free) — Iris Lite — 收件箱智能(免费) 安装说明: 安装命令:["openclaw skills install iris-lite"]
技能文档
Iris Lite — 免费收件箱扫描 扫描最近25封电子邮件并获取快速优先级列表,包含2个草稿回复。 免费版与专业版功能对比 Iris Lite(免费) Iris Pro 扫描电子邮件 25 最多200 草稿回复 2 每封可操作电子邮件 电子邮件类别 — Sales、HR、Legal、Finance 回复语气 — 专业/友好/简洁 每周分析 — JSON导出 — 升级:openclaw skills install iris-pro — 在ko-fi.com/occupythemilkyway获取您的密钥 步骤1 — 安装 pip3 install rich --break-system-packages --quiet 步骤2 — 快速收件箱扫描(Lite) 导入os、imaplib、email、re 从email.header导入decode_header 从email.utils导入parsedate_to_datetime 从datetime导入datetime、timezone 从rich.console导入Console 从rich.table导入Table 从rich.panel导入Panel 从rich导入box console = Console() GMAIL_ADDR = os.environ.get("GMAIL_ADDRESS", "").strip() GMAIL_PASS = os.environ.get("GMAIL_APP_PASSWORD", "").strip() YOUR_NAME = os.environ.get("YOUR_NAME", "").strip() # Lite版本硬性限制 SCAN_LIMIT = 25 DRAFT_LIMIT = 2 如果不GMAIL_ADDR或不GMAIL_PASS: console.print(Panel("[red]GMAIL_ADDRESS和GMAIL_APP_PASSWORD是必需的。[/red]\n\n" "应用程序密码:myaccount.google.com/apppasswords", title="设置必需", border_style="red")) 引发SystemExit(1) URGENT_KEYWORDS = ["urgent","asap","deadline","immediately","overdue","payment","invoice","emergency"] NOISE_PATTERNS = [r"unsubscribe",r"newsletter",r"no-reply@",r"noreply@",r"marketing@"] 定义decode_str(s): 如果不s:返回"" 部分 = decode_header(s) 结果 = [] 对于部分、enc在部分中: 如果部分是bytes类型:结果.append(部分.decode(enc or "utf-8", errors="replace")) 否则:结果.append(str(部分)) 返回" ".join(结果) 定义is_noise(sender, subject): 返回任何(re.search(p, (sender+subject).lower()) for p in NOISE_PATTERNS) 定义score_email(subject, snippet, sender, age_hours, has_replied): 评分 = 50 文本 = (subject + " " + snippet).lower() 如果任何(k in text for k in URGENT_KEYWORDS):评分 += 20 如果"?" in text:评分 += 10 如果age_hours > 48:评分 -= 10 如果has_replied:评分 -= 15 返回max(0, min(评分, 100)) console.print(Panel.fit( f"[bold cyan]ðŸ Iris Lite — 快速收件箱扫描[/bold cyan]\n" f"扫描最近[yellow]{SCAN_LIMIT}[/yellow]封电子邮件来自[green]{GMAIL_ADDR}[/green]\n" f"[dim]Lite:25封电子邮件,2个草稿 — 升级到Pro以获得完整的收件箱覆盖[/dim]", border_style="cyan" )) 尝试: mail = imaplib.IMAP4_SSL("imap.gmail.com", 993) mail.login(GMAIL_ADDR, GMAIL_PASS) mail.select("INBOX", readonly=True) 除异常e外: console.print(f"[red]â 登录失败:{e}\n检查GMAIL_ADDRESS和GMAIL_APP_PASSWORD。[/red]") 引发SystemExit(1) _, msg_ids = mail.search(None, "ALL") all_ids = msg_ids[0].split() if msg_ids and msg_ids[0] else [] recent_ids = list(reversed(all_ids[-SCAN_LIMIT:])) if len(all_ids) > SCAN_LIMIT else list(reversed(all_ids)) emails_data = [] now = datetime.now(timezone.utc) 对于uid在recent_ids中: 尝试: _, raw = mail.fetch(uid, "(RFC822.HEADER FLAGS)") 如果不raw或不raw[0]:继续 raw_header = raw[0][1] if isinstance(raw[0], tuple) else raw[0] msg = email.message_from_bytes(raw_header) subject = decode_str(msg.get("Subject","(no subject)")) sender = decode_str(msg.get("From","")) flags_raw = raw[0][0] if isinstance(raw[0], tuple) else b"" has_replied = b"\\Answered" in flags_raw 尝试: sent_dt = parsedate_to_datetime(msg.get("Date","")) 如果sent_dt.tzinfo是None:sent_dt = sent_dt.replace(tzinfo=timezone.utc) age_hours = (now - sent_dt).total_seconds() / 3600 除异常外:age_hours = 0 body_snippet = "" 尝试: _, rb = mail.fetch(uid, "(BODY[TEXT]<0.150>)") 如果rb和rb[0]和isinstance(rb[0], tuple)和rb[0][1]:body_snippet = rb[0][1].decode("utf-8", errors="replace").strip()[:100] 除异常外:pass m = re.search(r'"?([^"<]+)"?\s*<([^>]+)>', sender) sender_name = m.group(1).strip() if m else sender noise = is_noise(sender, subject) urgency = score_email(subject, body_snippet, sender, age_hours, has_replied) emails_data.append({ "subject": subject, "sender": sender_name, "age_hours": age_hours, "urgency": urgency, "is_noise": noise, "replied": has_replied, "snippet": body_snippet, }) 除异常外:继续 mail.logout() actionable = sorted([e for e in emails_data if not e["is_noise"]], key=lambda e: -e["urgency"]) noise_count = sum(1 for e in emails_data if e["is_noise"]) console.print() tbl = Table(title=f"📬 优先收件箱 — 顶{min(len(actionable), 15)}个{len(emails_data)}封电子邮件")