名称: email-to-calendar
版本: 1.13.1
描述: 从电子邮件中提取日历事件并创建日历条目。支持两种模式:(1) 直接收件箱监控 - 扫描所有邮件查找事件;(2) 转发邮件 - 处理您转发到专用地址的邮件。功能包括智能引导、事件追踪、待处理邀请提醒、撤销支持、静默活动日志记录、截止日期检测(附带独立提醒事件)、针对需处理事项的邮件通知,以及为未来扩展设计的提供者抽象层。
关键规则 - 处理任何邮件前必读
- 切勿直接调用
gog- 始终使用包装脚本(create_event.sh、email_read.sh等)。直接调用gog会绕过追踪并导致重复事件。此规则不可协商。- 忽略日历通知 - 不要处理来自
calendar-notification@google.com的邮件(例如:Accepted:、Declined:、Tentative: 等)。这些是对现有邀请的回复,不是新事件。运行process_calendar_replies.sh来归档它们。- 创建前务必询问 - 未经当前对话中用户明确确认,切勿创建日历事件。
- 检查是否已处理 - 处理任何邮件前,先检查 index.json 中的
processed_emails。- 先读取配置 - 在呈现事件前,加载并应用
ignore_patterns和auto_create_patterns。- 读取 MEMORY.MD - 检查从前次会话存储的用户偏好。
- 包含所有配置的参与者 - 创建/更新/删除事件时,始终使用
--attendees标志包含配置中的参与者(如果支持,还需加上--send-updates all)。- 先检查追踪事件 - 在日历搜索前,使用
lookup_event.sh --email-id查找现有事件(更快、更可靠)。- 追踪所有创建的事件 -
create_event.sh脚本会自动追踪事件;使用追踪的 ID 进行更新/删除。- 显示星期几 - 向用户呈现事件以供核实时,始终包含星期几。
⛔ 禁止:切勿直接使用
gog命令 ⛔错误示例:
gog calendar create ...或gog gmail ...
正确示例:"$SCRIPTS_DIR/create_event.sh" ...或"$SCRIPTS_DIR/email_read.sh" ...直接 CLI 调用会绕过事件追踪、破坏重复检测并导致重复事件。
所有操作都必须通过scripts/目录下的包装脚本进行。
从电子邮件中提取日历事件和待办事项,呈现以供审核,并使用重复检测和撤销支持来创建/更新日历事件。
首次设置: 配置选项和智能引导请参见 SETUP.md。
重要提示: 在提取事件之前,必须先读取邮件正文。请使用包装脚本。
SCRIPTS_DIR="$HOME/.openclaw/workspace/skills/email-to-calendar/scripts"
# 按 ID 获取单封邮件(推荐)
"$SCRIPTS_DIR/email_read.sh" --email-id "<messageId>"
# 搜索邮件(包含正文)
"$SCRIPTS_DIR/email_search.sh" --query "in:inbox is:unread" --max 20 --include-body
关于陈旧转发的说明: 不要使用 newer_than:1d,因为它检查的是邮件的原始日期头,而非接收时间。处理所有未读邮件,并依赖“已处理”检查。
SCRIPTS_DIR="$HOME/.openclaw/workspace/skills/email-to-calendar/scripts"
CONFIG_FILE="$HOME/.config/email-to-calendar/config.json"
INDEX_FILE="$HOME/.openclaw/workspace/memory/email-extractions/index.json"
# 启动活动日志记录
"$SCRIPTS_DIR/activity_log.sh" start-session
# 检查邮件模式
EMAIL_MODE=$(jq -r '.email_mode // "forwarded"' "$CONFIG_FILE")
# 检查邮件是否已处理
EMAIL_ID="<邮件消息ID>"
if jq -e ".extractions[] | select(.email_id == \"$EMAIL_ID\")" "$INDEX_FILE" > /dev/null 2>&1; then
"$SCRIPTS_DIR/activity_log.sh" log-skip --email-id "$EMAIL_ID" --subject "主题" --reason "已处理"
exit 0
fi
# 加载忽略/自动创建模式
IGNORE_PATTERNS=$(jq -r '.event_rules.ignore_patterns[]' "$CONFIG_FILE")
AUTO_CREATE_PATTERNS=$(jq -r '.event_rules.auto_create_patterns[]' "$CONFIG_FILE")
直接模式: 扫描所有未读邮件,查找事件指示符(日期、时间、会议关键词)。
转发模式: 仅处理带有转发指示符的邮件(例如:Fwd:、转发消息头)。
读取邮件并将事件提取为结构化数据。为每个事件包含以下信息:
- 标题:描述性名称(最多 80 个字符)
- 日期:事件日期
- 星期几:用于验证
- 时间:开始/结束时间(默认:上午 9:00 - 下午 5:00)
- is_multi_day:是否跨越多天
- is_recurring:是否重复(及重复模式)
- confidence:高/中/低
- urls:在邮件中找到的任何 URL(必需 - 始终查找注册链接、信息页面、票务网站等)
- deadline_date:RSVP/注册/购票截止日期(如果找到)
- deadline_action:用户需要做什么(例如,“RSVP”、“购票”、“注册”)
- deadline_url:用于执行操作的直接链接(通常与事件 URL 相同)
URL 提取规则: 始终扫描邮件中的 URL,并将最相关的一个放在事件描述的开头。
扫描邮件中指示事件前需要采取行动的截止日期模式:
常见截止日期模式:
- "RSVP by [日期]", "Please RSVP by [日期]"
- "Register by [日期]", "Registration closes [日期]"
- "Tickets available until [日期]", "Get tickets by [日期]"
- "Early bird ends [日期]", "Early registration deadline [日期]"
- "Must respond by [日期]", "Respond by [日期]"
- "Sign up by [日期]", "Sign up deadline [日期]"
- "Deadline: [日期]", "Due by [日期]"
- "Last day to [操作]: [日期]"
找到截止日期时:
1. 提取截止日期
2. 确定所需操作(RSVP、注册、购票等)
3. 查找执行该操作的 URL
4. 标记事件以进行特殊处理(见下文)
应用事件规则,然后以编号选择的方式呈现:
我发现了以下潜在事件:
1. ~~ELAC 会议 (2月2日,星期一 上午 8:15)~~ - 跳过(匹配忽略模式)
2. **团队外出活动 (2月2-6日,周日-周四)** - 待处理
3. **员工发展日 (2月12日,星期三)** - 自动创建
回复数字以创建(例如 '2, 3')、'all' 或 'none'。
停止并等待用户响应。
呈现后,记录待处理邀请以供后续提醒:
# 使用 add_pending.sh 记录待处理邀请
"$SCRIPTS_DIR/add_pending.sh" \
--email-id "$EMAIL_ID" \
--email-subject "$EMAIL_SUBJECT" \
--events-json '[{"title":"事件名称","date":"2026-02-15","time":"14:00","status":"pending"}]'
创建任何事件前始终检查:
# 步骤 1:先检查本地追踪(快速)
TRACKED=$("$SCRIPTS_DIR/lookup_event.sh" --email-id "$EMAIL_ID")
if [ "$(echo "$TRACKED" | jq 'length')" -gt 0 ]; then
EXISTING_EVENT_ID=$(echo "$TRACKED" | jq -r '.[0].event_id')
fi
# 步骤 2:如果未找到,尝试标题匹配
if [ -z "$EXISTING_EVENT_ID" ]; then
TRACKED=$("$SCRIPTS_DIR/lookup_event.sh" --summary "$EVENT_TITLE")
fi
# 步骤 3:回退到使用包装脚本进行日历搜索
if [ -z "$EXISTING_EVENT_ID" ]; then
"$SCRIPTS_DIR/calendar_search.sh" --calendar-id "$CALENDAR_ID" --from "${EVENT_DATE}T00:00:00" --to "${EVENT_DATE}T23:59:59"
fi
对于模糊重复项(例如,“团队外出活动”与“团队外出活动 5-6pm”),使用 LLM 语义匹配。
使用 create_event.sh(推荐) - 处理日期解析、追踪和变更日志:
# 创建新事件
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"事件标题" \
"2026年2月11日" \
"上午 9:00" \
"下午 5:00" \
"描述" \
"$ATTENDEE_EMAILS" \
"" \
"$EMAIL_ID"
# 更新现有事件(将 event_id 作为第 8 个参数传递)
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"更新后的标题" \
"2026年2月11日" \
"上午 10:00" \
"下午 6:00" \
"更新后的描述" \
"$ATTENDEE_EMAILS" \
"$EXISTING_EVENT_ID" \
"$EMAIL_ID"
关于直接 gog 命令和高级选项,请参见 references/gog-commands.md。
邮件处置(标记为已读和/或归档)由 create_event.sh 根据配置设置自动处理。无需手动步骤 - 事件创建后邮件即被处置。
手动处置邮件:
"$SCRIPTS_DIR/disposition_email.sh" --email-id "$EMAIL_ID"
处理日历回复邮件(接受、拒绝、暂定):
"$SCRIPTS_DIR/process_calendar_replies.sh" # 处理所有
"$SCRIPTS_DIR/process_calendar_replies.sh" --dry-run # 仅预览
# 结束活动会话
"$SCRIPTS_DIR/activity_log.sh" end-session
--rrule "RRULE:FREQ=DAILY;COUNT=N"按此顺序格式化事件描述:
行动警告(如果存在截止日期):
*** 需要处理:[操作] 截止于 [日期] ***
事件链接(如果找到 URL):
事件链接:[URL]
事件详情:从邮件中提取的信息
带截止日期的示例:
*** 需要处理:2月15日前购票 ***
事件链接:https://example.com/tickets
市中心剧院春季音乐会
晚上 7 点开门
提供 VIP 见面会
不带截止日期的示例:
事件链接:https://example.com/event
市中心剧院春季音乐会
晚上 7 点开门
如果满足以下条件,则视为重复:
- 相同日期 且 相似标题(语义匹配) 且 时间重叠
始终更新现有事件,而不是创建重复项。
当事件有截止日期(RSVP、注册、购票等)时,创建两个日历事件:
1. 主事件(正常创建,但在描述中添加警告):
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"春季音乐会" \
"2026年3月1日" \
"下午 7:00" \
"下午 10:00" \
"*** 需要处理:2月15日前购票 ***
事件链接:https://example.com/tickets
市中心剧院春季音乐会
晚上 7 点开门" \
"$ATTENDEE_EMAILS" \
"" \
"$EMAIL_ID"
2. 截止日期提醒事件(在截止日期上的独立事件):
# 截止日期提醒也使用 create_event.sh(确保追踪)
"$SCRIPTS_DIR/create_event.sh" \
"$CALENDAR_ID" \
"截止日期:为春季音乐会购票" \
"2026-02-15" \
"09:00" \
"09:30" \
"需要处理:购票
事件链接:https://example.com/tickets
主事件:2026年3月1日的春季音乐会" \
"" \
"" \
"$EMAIL_ID"
截止日期事件属性:
- 标题格式:截止日期:[操作] for [事件名称]
- 日期:截止日期
- 时间:上午 9:00(持续 30 分钟)
- 提醒:提前 1 天邮件提醒 + 提前 1 小时弹窗提醒
- 描述:需要处理的操作、URL、主事件引用
创建带截止日期的事件时,发送通知邮件以提醒用户:
# 加载配置
CONFIG_FILE="$HOME/.config/email-to-calendar/config.json"
USER_EMAIL=$(jq -r '.deadline_notifications.email_recipient // .gmail_account' "$CONFIG_FILE")
NOTIFICATIONS_ENABLED=$(jq -r '.deadline_notifications.enabled // false' "$CONFIG_FILE")
# 如果启用则发送通知(使用包装脚本)
if [ "$NOTIFICATIONS_ENABLED" = "true" ]; then
"$SCRIPTS_DIR/email_send.sh" \
--to "$USER_EMAIL" \
--subject "需要处理:2月15日前为春季音乐会购票" \
--body "已创建一个需要您处理的日历事件。
事件:春季音乐会
日期:2026年3月1日
截止日期:2026年2月15日
需要处理:购票
链接:https://example.com/tickets
已创建的日历事件:
- 主事件:春季音乐会 (3月1日)
- 截止日期提醒:截止日期:为春季音乐会购票 (2月15日)
---
此通知由邮件转日历技能发送。"
fi
何时发送通知:
- 仅当配置中 deadline_notifications.enabled 为 true 时
- 仅针对有需要处理截止日期的事件
- 包含截止日期、操作、URL 和事件详情
# 启动会话
"$SCRIPTS_DIR/activity_log.sh" start-session
# 记录跳过的邮件
"$SCRIPTS_DIR/activity_log.sh" log-skip --email-id "abc" --subject "新闻简报" --reason "无事件"
# 记录事件
"$SCRIPTS_DIR/activity_log.sh" log-event --email-id "def" --title "会议" --action created
# 结束会话
"$SCRIPTS_DIR/activity_log.sh" end-session
# 显示近期活动
"$SCRIPTS_DIR/activity_log.sh" show --last 3
变更可在 24 小时内撤销:
# 列出近期变更
"$SCRIPTS_DIR/changelog.sh" list --last 10
# 列出可撤销的变更
"$SCRIPTS_DIR/undo.sh" list
# 撤销最近的变更
"$SCRIPTS_DIR/undo.sh" last
# 撤销特定变更
"$SCRIPTS_DIR/undo.sh" --change-id "chg_20260202_143000_001"
未立即处理的事件会被追踪以供提醒:
# 添加待处理邀请(向用户呈现事件后)
"$SCRIPTS_DIR/add_pending.sh" \
--email-id "$EMAIL_ID" \
--email-subject "派对邀请" \
--events-json '[{"title":"生日派对","date":"2026-02-15","time":"14:00","status":"pending"}]'
# 列出待处理邀请(JSON)
"$SCRIPTS_DIR/list_pending.sh"
# 人类可读的摘要
"$SCRIPTS_DIR/list_pending.sh" --summary
# 更新提醒追踪
"$SCRIPTS_DIR/list_pending.sh" --summary --update-reminded
# 忽略 3 次提醒后自动关闭
"$SCRIPTS_DIR/list_pending.sh" --summary --auto-dismiss
```bash
"$SCRIPTS_DIR/lookup_event.sh" --email-id "19c1c86dcc389443"
"$SCRIPTS_DIR/lookup_event.sh" --summary "员工发展"