Weekly Report Email
通用周报收集和邮件推送技能,支持交互式填写周报内容,自动计算周数和日期范围,生成美观的HTML格式邮件。
Like a lobster shell, security has layers — review code before you run it.
License
SKILL.md
周报技能 - xl-weekly-report-email
一个通用的周报收集和邮件推送技能,安装后配置邮箱即可使用。
触发方式
在对话中说"写周报"即可触发周报生成流程。
配置邮箱时说"配置周报邮箱"。
⚠️ 重要:执行此技能时必须严格遵循以下步骤,不得省略或跳过任何步骤!
最关键的规则:
- 每次只问一个问题,等用户回复后再问下一个
- 绝对禁止一次性抛出所有问题
- 绝对禁止在没有用户确认的情况下自动发送邮件!
- 必须等待用户明确确认后才能发送邮件!
- 任何用户回复的内容都应该被记录,除非用户明确回复"无"、"空"、"不需要"、"跳过"等否定词
- 即使内容很短(如"2"、"无内容"等非否定词),也应该记录
- 即使内容不按格式写,也应该直接展示,不当作空值处理
📋 完整工作流程
第零步:检查配置
首次使用需要配置邮箱参数和报告参数。发送"配置周报邮箱"命令会自动引导你完成配置。
配置内容包括:
- SMTP服务器:选择预设(腾讯企业邮箱、阿里企业邮箱、Gmail 等)或自定义
- SMTP端口:通常是465(SSL)或587(TLS)
- 邮箱账号:你的邮箱地址
- 邮箱密码:邮箱登录密码或授权码
- 发件人:发件人邮箱地址(通常与账号相同)
- 组织/部门名称(可选):如"XX公司",会显示在邮件标题开头
- 你的姓名:如"张三"
- 你的职位:如"后端工程师"
- 周报收件人:接收周报的邮箱地址
- 周报抄送人(可选):抄送周报的邮箱地址
注意:
- 组织/部门名称(
company)字段可选,如果配置了会显示在邮件标题开头;如果不配置或为空,邮件标题中不会显示组织/部门名称和前面的"-"。 - 默认抄送人(
cc)字段可选,如果配置了每次发送时都会抄送这些邮箱;如果不配置,则不抄送(除非发送时额外添加)。 - 邮箱配置会自动保存到
.env文件(包含敏感信息,不会被发布到 clawhub)。 - 报告配置会保存到
config.json文件。
第一步:计算并展示日期信息
必须先执行这一步!
自动计算并展示以下信息(所有时间必须是东八区):
- 周数 = ISO周数(周五/周六/周日不减1,周四/周四之前减1)
- 截止日期 = 下周周四(YYYYMMDD 格式)
- 时间范围 = 本周四 到 下周三(中文格式:YYYY年MM月DD日)
示例输出(如果今天是周五):
📊 周报日期信息:
- 周数:13
- 截止日期:20260402
- 时间范围:2026年3月26日 至 2026年4月1日
⚠️ 警告:在计算并展示日期信息之前,不要询问任何周报内容!
第二步:逐项收集周报内容
⚠️ 关键规则:必须一个一个询问!禁止一次性抛出所有问题!
每次只问一个问题,等用户回复后再问下一个。绝对不能把所有问题一次性列出来!
第一部分:遗留问题/阻碍因素跟进
执行顺序:
- 先给描述
- 再给格式提示
- 最后给示例
- 等用户回复
描述: 列出上周遗留问题或当前最大的阻碍因素的跟进情况。
格式:
[问题描述][当前状态]:进展详情
重要: 必须使用方括号 [] 包裹问题描述和当前状态,否则没有样式!
示例:
1. [测试环境资源不足][已解决]:已申请新服务器,问题解决,进度已恢复。
2. [数据接口延迟问题][跟进中]:已联系数据负责人,承诺本周五前修复,目前正在联调。
状态样式说明:
已解决或Done→ 绿色样式 ✓- 其他所有状态 → 蓝色样式 →
⚠️ 格式提示与用户坚持的规则(重要!):
用户输入内容不按格式时的处理流程:
情况1:用户第一次输入不按格式(如"111"、"完成开发任务"等)
- AI 只提示一次:"建议格式是 [问题描述][当前状态]:进展详情,您确定要这样写吗?"
- 如果用户回复"确定"、"是的"、"就这么写"等确认词 → 直接记录用户之前输入的内容("111")
- 如果用户回复"好的"、"明白了"等 → 重新询问用户第一部分内容
- 如果用户继续输入新的内容(不是确认词) → 直接记录用户新输入的内容
情况2:用户坚持使用不按格式的内容
- 任何用户输入的内容,都应该被记录,除非用户明确回复"无"、"空"、"不需要"、"跳过"等否定词
- 即使内容很短(如"111"、"222"),也应该记录
- 即使内容不按格式写,也应该直接展示,用普通样式展示
记住:
- 格式提示只提示一次,不要重复提示
- 用户输入任何内容(除了明确的否定词),都要记录
- 不要问"您确定要这样写吗?"多次
⚠️ 关键规则:
- 任何用户回复的内容都应该被记录,除非用户明确回复"无"、"空"、"不需要"、"跳过"等否定词
- 即使内容很短(如"2"、"123"),也应该记录
- 即使内容不按格式写,也应该直接展示,不当作空值处理
⚠️ 禁止: 不要问"第一部分是什么",直接按照"描述→格式→示例"的顺序给用户!也不要继续问第二部分,等用户回复第一部分后再问!
第二部分:本周具体产出
执行顺序:
- 先给描述
- 再给格式提示
- 最后给示例
- 等用户回复
描述: 列出本周具体的产出,建议按项目或模块分类。
格式:
[项目 xxx] 子项目名 + 项目状态 (Done/Doing 进度 X%/ Delay/ Suspend) + 进度详情/阶段成果/阻塞原因
重要: 必须使用方括号 [] 包裹项目名,状态必须用圆括号 () 包裹,否则没有样式!
示例:
1. [项目 A] 画像标签开发 (Doing 80%)
完成了用户活跃度标签的逻辑重构,性能提升 30%。
正在与业务方进行数据验收。
2. [数据治理] 人员数据质量优化 (Done)
完成了历史脏数据的清洗工作,并补充了缺失的日志数据。
3. [项目 B] 人员表开发(Doing 80%/Delay)
完成了 xxxx 的开发
需求变动导致 delay
状态样式说明:
Done→ 绿色样式Delay→ 橙色样式Suspend→ 灰色样式Doing 进度X%或其他状态 → 蓝色样式- 组合状态(如
Doing 80%/Delay)会拆分成多个状态标签,分别显示对应样式
⚠️ 格式提示与用户坚持的规则(重要!):
用户输入内容不按格式时的处理流程:
情况1:用户第一次输入不按格式(如"222"、"完成开发任务"等)
- AI 只提示一次:"建议格式是 [项目名] 任务名 (状态),您确定要这样写吗?"
- 如果用户回复"确定"、"是的"、"就这么写"等确认词 → 直接记录用户之前输入的内容("222")
- 如果用户回复"好的"、"明白了"等 → 重新询问用户第二部分内容
- 如果用户继续输入新的内容(不是确认词) → 直接记录用户新输入的内容
情况2:用户坚持使用不按格式的内容
- 任何用户输入的内容,都应该被记录,除非用户明确回复"无"、"空"、"不需要"、"跳过"等否定词
- 即使内容很短(如"222"、"123"),也应该记录
- 即使内容不按格式写,也应该直接展示,用普通样式展示
记住:
- 格式提示只提示一次,不要重复提示
- 用户输入任何内容(除了明确的否定词),都要记录
- 不要问"您确定要这样写吗?"多次
⚠️ 关键规则:
- 任何用户回复的内容都应该被记录,除非用户明确回复"无"、"空"、"不需要"、"跳过"等否定词
- 即使内容很短(如"2"、"123"),也应该记录
- 即使内容不按格式写,也应该直接展示,不当作空值处理
⚠️ 禁止: 同上,等用户回复第一部分后再问第二部分!不要问"第二部分是什么",直接按顺序给!
第三部分:技术难点/业务卡点
执行顺序:
- 先给描述
- 最后给示例
- 等用户回复
描述: 这里重点写本周遇到的技术难点或业务卡点,以及你打算怎么解决。
示例:
1. 问题描述:需求频繁变更,导致开发返工。
解决方案:已与产品经理约定,后续需求变更需通过 TAPD 更新 PRD 并邮件周知,重大变更需重新评估工时。
2. 问题描述:ClickHouse 查询超时。
解决方案:通过分析慢查询日志,发现索引未命中,已优化 SQL 语句并增加二级索引。
⚠️ 禁止: 同上,等用户回复后再继续!
第四部分:下周核心计划
执行顺序:
- 先给描述
- 最后给示例
- 等用户回复
描述: 按优先级列出下周的核心产出承诺。
示例:
1. [计划 1]
2. [计划 2]
3. [计划 3]
⚠️ 禁止: 同上!
第五部分:团队协作/流程/架构思考(非必选)
执行顺序:
- 先给描述
- 最后给示例
- 等用户回复
描述: 不仅限于自己的代码,着眼于团队协作、流程、架构等宏观问题。这是周报中体现思考深度的部分。
示例:
1. 协作问题:[例如:数据上游经常口头变更字段,导致下游任务失败]。建议建立字段变更通知机制,必须经过审批群周知。
2. 架构/稳定性问题:[例如:当前实时任务单点故障风险较高]。建议将核心任务迁移至 Flink 集群,并配置拉起机制。
3. 业务痛点:[例如:业务方普遍反映离线数据产出时间太晚]。建议优化 DAG 调度依赖,将核心任务优先级提高。
⚠️ 禁止: 同上!
第六部分:自由发挥区(非必选)
执行顺序:
- 先给描述
- 等用户回复
描述: 自由发挥区(心得体会、GET 技能、共鸣句子、个人思考等)
⚠️ 禁止: 同上!
第三步:保存周报内容(临时文件)
将所有内容写入 memory/weekly-report-YYYYMMDD.md 文件
注意: 这是临时文件,发送完邮件后会自动删除,不会保留。
保存临时文件的方式:
const fs = require('fs');
const path = require('path');
// 生成文件名(用当前日期)
const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, ''); // YYYYMMDD
const tempFile = path.join(__dirname, 'memory', `weekly-report-${dateStr}.md`);
// 确保目录存在
const memoryDir = path.join(__dirname, 'memory');
if (!fs.existsSync(memoryDir)) {
fs.mkdirSync(memoryDir, { recursive: true });
}
// 写入文件
fs.writeFileSync(tempFile, content);
第四步:生成 HTML 预览
⚠️ 必须使用 main.js!禁止自己手写 HTML!
正确方式:
cd /home/node/.openclaw/workspace/skills/xl-weekly-report-email
nodejs main.js
调用方式:
- 先导入:
const { generateWeeklyReport } = require('./main.js'); - 再生成:
const report = generateWeeklyReport(content); - 预览:把
report.body给用户看
禁止:
- ❌ 自己写 HTML
- ❌ 直接输出文本
- ❌ 省略样式
⚠️ 重要:生成预览后,给用户看HTML内容,然后问用户是否确认发送!绝对不要自动发送!
第五步:询问额外抄送人(可跳过)
⚠️ 在发送邮件前询问!
执行顺序:
- 询问用户是否有其他抄送人
- 让用户填写抄送邮箱地址(多个用逗号分隔,全角逗号","或半角逗号","都可以)
- 如果用户不填或填写"无",则只使用配置的抄送人(如果配置了)
示例:
这次发送周报,是否需要添加其他抄送人?(可留空,多个邮箱用逗号分隔)
例如:boss@example.com,leader@example.com
第六步:发送邮件
⚠️ 关键规则:必须等待用户明确确认后才能发送邮件!绝对禁止自动发送!
执行顺序:
- 生成 HTML 格式预览给用户确认
- 明确询问用户:是否确认发送?
- 等待用户明确回复"确认"、"发送"、"是"等确认词
- 只有收到用户明确确认后,才能调用
main.js中的generateAndSendReport(content, additionalCc, tempFilePath)函数发送邮件 - 如果用户回复"不"、"取消"、"修改"等否定词,则不发送,询问用户需要修改什么
- 邮件信息(收件人、抄送、发件人)处理逻辑:
- 配置的抄送人 + 额外填写的抄送人 = 所有抄送人(自动去重)
- 如果两者都没有,则不抄送任何人
- 邮件发送成功后,自动删除临时文件
memory/weekly-report-YYYYMMDD.md
⚠️ 严重警告:
- 绝对禁止在生成预览后自动发送邮件!
- 绝对禁止在没有用户确认的情况下调用发送函数!
- 必须明确等待用户的确认回复!
tempFilePath参数是第三步保存的临时文件路径- 邮件发送成功后会自动清理,无需手动删除
- 如果需要手动清理,可以调用
cleanupTempFile(filePath)函数
📧 邮件规则
- 标题格式: 从 config.json 读取配置生成(姓名、职位会自动填入)
- 收件人: 从 config.json 读取
- 抄送: 从 config.json 读取(可选)
- 时间计算规则:
- 周数 = 当前周数 - 1(使用 ISO 标准周数,通过 Python 的
isocalendar()方法计算) - 截止日期 = 本周周四(如果今天 <= 周四则取本周,如果今天 > 周四则取下周)
- 时间范围 = 上周四 到 本周三
- 周数 = 当前周数 - 1(使用 ISO 标准周数,通过 Python 的
🔧 技术实现
核心文件
main.js: 周报生成和发送主逻辑(日期计算、HTML生成、内容解析)mailer.js: 邮件发送模块(基于 nodemailer)setup.js: 首次配置引导config.json: 用户配置文件
依赖
- nodemailer: 邮件发送
发送邮件的正确方式
方式1:使用 nodemailer(main.js 中已集成)
const { sendWeeklyReport } = require('./mailer');
await sendWeeklyReport(subject, htmlBody, recipient, cc);
方式2:使用 imap-smtp-email/smtp.js 命令行(标准)
cd /home/node/.openclaw/workspace/skills/imap-smtp-email/scripts
nodejs smtp.js send --to target@example.com --subject "标题" --html-file email.html
⚠️ 系统环境限制
- Node.js 命令是
nodejs不是node - nodemailer 依赖在
/home/node/.openclaw/workspace/skills/xl-weekly-report-email/node_modules
📁 配置文件格式
config.json(报告配置)
报告配置保存在 config.json 中:
{
"report": {
"company": "XX公司",
"name": "张三",
"position": "后端工程师",
"recipient": "manager@example.com",
"cc": "cc@example.com"
}
}
.env(邮箱配置)
邮箱配置保存在 .env 文件中(首次使用请复制 .env.example 为 .env):
# SMTP 配置(发邮件)
SMTP_HOST=smtp.qiye.aliyun.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=your-email@example.com
SMTP_PASS=your-password
SMTP_FROM=your-email@example.com
说明:
company字段可选,如果不配置或为空,邮件标题中不会显示组织/部门名称和前面的"-"- 如果配置了
company,邮件标题格式为:组织/部门名称 - 职位姓名 - X周周报 - 日期 - 如果没配置
company,邮件标题格式为:职位姓名 - X周周报 - 日期 .env文件包含敏感信息,不会被发布到 clawhub(在 .clawignore 中已排除)
🐛 常见问题
忘记配置了怎么办?
重新发送"配置周报邮箱"命令,会重新进入配置流程。
邮件发送失败怎么办?
- 检查
.env文件是否存在且配置正确 - 检查邮箱密码是否正确(某些邮箱需要使用授权码)
- 检查SMTP服务器地址和端口是否正确
- 检查是否开启了SMTP服务
- 查看 detailed 错误信息
如何配置邮箱?
- 复制
.env.example为.env - 填写你的 SMTP 配置信息
支持哪些邮箱?
支持所有标准SMTP协议的邮箱,包括:
- 腾讯企业邮箱
- 阿里企业邮箱
- 网易企业邮箱
- Gmail(需要应用专用密码)
- Outlook
- 其他支持SMTP的邮箱
🧪 测试
运行测试脚本:
cd /home/node/.openclaw/workspace/skills/xl-weekly-report-email
nodejs test.js
版本历史和变更日志请查看 CHANGELOG.md
Files
10 totalComments
Loading comments…
