文件预览

SKILL.md

查看 邮件助手 技能包中的文件内容。

文件内容

SKILL.md

---
name: email-helper
version: 1.0.0
description: 邮件助手 - 编写/发送/管理邮件,支持SMTP发信和IMAP收信,多模板草稿,自动归档
tags: [email, communication, smtp, imap, productivity]
author: laosi
source: original
---

# Email Helper - 邮件助手

> 激活词: 邮件 / 发邮件 / email

## 功能

- 编写邮件草稿(支持模板)
- 通过SMTP发送邮件
- 通过IMAP读取收件箱
- 邮件归档和搜索
- 草稿本地持久化

## Python 实现

```python
import os, json, smtplib, imaplib, email
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from datetime import datetime
from typing import List, Optional

DRAFT_FILE = os.path.join(os.path.dirname(__file__), "email_drafts.json")

class EmailHelper:
    def __init__(self):
        os.makedirs(os.path.dirname(DRAFT_FILE), exist_ok=True)
        self.drafts = self._load_drafts()
    
    def _load_drafts(self) -> list:
        if os.path.exists(DRAFT_FILE):
            with open(DRAFT_FILE, encoding="utf-8") as f:
                return json.load(f)
        return []
    
    def _save_drafts(self):
        with open(DRAFT_FILE, "w", encoding="utf-8") as f:
            json.dump(self.drafts, f, ensure_ascii=False, indent=2)
    
    def create_draft(self, to_addr: str, subject: str, body: str,
                     cc: str = "", bcc: str = "") -> dict:
        """创建邮件草稿"""
        draft = {
            "id": len(self.drafts) + 1,
            "to": to_addr,
            "cc": cc,
            "bcc": bcc,
            "subject": subject,
            "body": body,
            "status": "draft",
            "created": datetime.now().isoformat(),
        }
        self.drafts.append(draft)
        self._save_drafts()
        return draft
    
    def build_mime(self, draft_id: int) -> Optional[MIMEMultipart]:
        """将草稿构建为MIME消息"""
        draft = next((d for d in self.drafts if d["id"] == draft_id), None)
        if not draft:
            return None
        
        msg = MIMEMultipart()
        msg["From"] = draft.get("from_addr", "sender@example.com")
        msg["To"] = draft["to"]
        if draft.get("cc"):
            msg["Cc"] = draft["cc"]
        msg["Subject"] = draft["subject"]
        msg.attach(MIMEText(draft["body"], "plain", "utf-8"))
        return msg
    
    def send(self, draft_id: int, smtp_host: str, smtp_port: int,
             username: str, password: str, use_tls: bool = True) -> dict:
        """通过SMTP发送草稿"""
        draft = next((d for d in self.drafts if d["id"] == draft_id), None)
        if not draft:
            return {"error": f"Draft #{draft_id} not found"}
        
        msg = self.build_mime(draft_id)
        if not msg:
            return {"error": "Failed to build MIME message"}
        
        try:
            server = smtplib.SMTP(smtp_host, smtp_port, timeout=10)
            if use_tls:
                server.starttls()
            server.login(username, password)
            server.send_message(msg)
            server.quit()
            
            draft["status"] = "sent"
            draft["sent_at"] = datetime.now().isoformat()
            self._save_drafts()
            return {"success": True, "to": draft["to"], "subject": draft["subject"]}
        except Exception as e:
            return {"error": str(e)}
    
    def inbox(self, imap_host: str, username: str, password: str,
              limit: int = 10) -> List[dict]:
        """读取收件箱"""
        try:
            conn = imaplib.IMAP4_SSL(imap_host)
            conn.login(username, password)
            conn.select("INBOX")
            
            _, data = conn.search(None, "ALL")
            ids = data[0].split()[-limit:]  # 最近的N封
            messages = []
            
            for mid in ids:
                _, msg_data = conn.fetch(mid, "(RFC822)")
                raw = email.message_from_bytes(msg_data[0][1])
                messages.append({
                    "from": raw["From"],
                    "subject": raw["Subject"],
                    "date": raw["Date"],
                    "body": self._get_text(raw)[:200],
                })
            
            conn.logout()
            return messages
        except Exception as e:
            return [{"error": str(e)}]
    
    def _get_text(self, msg) -> str:
        """从邮件对象提取正文"""
        if msg.is_multipart():
            for part in msg.walk():
                if part.get_content_type() == "text/plain":
                    return part.get_payload(decode=True).decode("utf-8", errors="ignore")
        return msg.get_payload(decode=True).decode("utf-8", errors="ignore") if msg.get_payload(decode=True) else ""
    
    def list_drafts(self, status: str = None) -> list:
        """列出草稿"""
        if status:
            return [d for d in self.drafts if d["status"] == status]
        return self.drafts
    
    def delete_draft(self, draft_id: int) -> bool:
        """删除草稿"""
        before = len(self.drafts)
        self.drafts = [d for d in self.drafts if d["id"] != draft_id]
        if len(self.drafts) < before:
            self._save_drafts()
            return True
        return False

# 使用示例
eh = EmailHelper()

# 创建草稿
draft = eh.create_draft(
    to_addr="team@company.com",
    subject="Weekly Update - May 28",
    body="Hi team,\n\nThis week's update:\n1. Feature A completed\n2. Bug fixes deployed\n\nBest,\nLaosi"
)
print(f"Draft #{draft['id']}: {draft['subject']}")

# 列出所有草稿
for d in eh.list_drafts():
    print(f"  [{d['status']}] #{d['id']}: {d['subject']} -> {d['to']}")

# 实际发送(需要配置SMTP)
# result = eh.send(1, "smtp.gmail.com", 587, "user@gmail.com", "app_password")
# print(f"Send result: {result}")
```

## 邮件模板

```python
TEMPLATES = {
    "weekly_report": {
        "subject": "Weekly Report - {date}",
        "body": "Hi {name},\n\n{content}\n\nBest,\n{sender}"
    },
    "meeting_invite": {
        "subject": "Meeting: {topic} - {date}",
        "body": "Hi {name},\n\nYou're invited to {topic} at {time}.\n\nAgenda:\n{agenda}\n\nRegards,\n{sender}"
    },
    "follow_up": {
        "subject": "Re: {topic}",
        "body": "Hi {name},\n\nFollowing up on {topic}. Any updates?\n\nBest,\n{sender}"
    }
}
```

## 使用场景

1. **周报自动发送**: 集成数据分析结果,自动生成并发送周报
2. **告警通知**: 系统异常时自动发邮件给值班人员
3. **批量邀请**: 会议邀请/活动通知批量发送
4. **邮件归档**: 按项目/关键词自动分类归档邮件

## 配置

```yaml
smtp:
  host: smtp.gmail.com
  port: 587
  use_tls: true
imap:
  host: imap.gmail.com
sender:
  name: AI Assistant
  email: ai@example.com
```

## 依赖

- Python 3.8+
- 标准库(smtplib, imaplib, email)