diff --git a/config/channels.json b/config/channels.json index 9dee6d9..387ceb3 100644 --- a/config/channels.json +++ b/config/channels.json @@ -13,20 +13,20 @@ "port": 465, "secure": true, "auth": { - "user": "panda@pandalla.ai", - "pass": "1fIvPAo0lagVG9gS" + "user": "noreply@pandalla.ai", + "pass": "kKgS3tNReRTL3RQC" } }, "imap": { - "host": "imap.feishu.cn", + "host": "imap.gmail.com", "port": 993, "secure": true, "auth": { - "user": "panda@pandalla.ai", - "pass": "1fIvPAo0lagVG9gS" + "user": "jiaxicui446@gmail.com", + "pass": "your-gmail-app-password" } }, - "from": "TaskPing ", + "from": "TaskPing 通知系统 ", "to": "jiaxicui446@gmail.com", "template": { "checkInterval": 30 diff --git a/docs/QUICK_SETUP_GUIDE.md b/docs/QUICK_SETUP_GUIDE.md new file mode 100644 index 0000000..2360e83 --- /dev/null +++ b/docs/QUICK_SETUP_GUIDE.md @@ -0,0 +1,163 @@ +# TaskPing 快速配置指南 + +## 🚀 5分钟快速开始 + +本指南帮助您快速配置 TaskPing 的邮件通知和回复功能。 + +## 第一步:配置邮件账号 + +### 1.1 复制环境配置文件 +```bash +cp .env.example .env +``` + +### 1.2 编辑 .env 文件 + +您的配置已经部分完成: +- ✅ 发件服务器:飞书邮箱 (noreply@pandalla.ai) +- ✅ 收件邮箱:Gmail (jiaxicui446@gmail.com) +- ❌ Gmail 应用密码:需要您配置 + +### 1.3 获取 Gmail 应用专用密码 + +1. 登录您的 Gmail 账号 (jiaxicui446@gmail.com) +2. 访问 [Google 账号安全设置](https://myaccount.google.com/security) +3. 开启"两步验证"(如果未开启) +4. 访问 [应用专用密码页面](https://myaccount.google.com/apppasswords) +5. 选择应用"邮件",设备选择"其他" +6. 输入名称"TaskPing" +7. 点击"生成"获取16位密码 +8. 将密码复制到 .env 文件的 `IMAP_PASS` 字段 + +## 第二步:更新配置 + +```bash +# 更新邮件配置到系统 +npm run email:config +``` + +## 第三步:测试邮件发送 + +```bash +# 发送测试邮件 +npm run email:test +``` + +成功后您会看到: +``` +✅ 邮件发送成功! + Message ID: + Response: 250 2.0.0 OK: queued +``` + +## 第四步:启动邮件监听服务 + +```bash +# 启动 PTY 模式的邮件监听 +npm run relay:pty +``` + +服务启动后会显示: +``` +🚀 正在启动 TaskPing PTY Relay 服务... +📧 IMAP服务器: imap.gmail.com +👤 邮件账号: jiaxicui446@gmail.com +``` + +## 第五步:测试完整流程 + +1. **检查收件箱** + - 查看 jiaxicui446@gmail.com 是否收到测试邮件 + - 主题类似:`[TaskPing #TESTXXXXX] 测试邮件 - 等待您的指令` + +2. **回复测试命令** + - 直接回复邮件 + - 内容输入:`echo "Hello from TaskPing"` + - 发送 + +3. **查看服务日志** + - PTY Relay 服务会显示收到的命令 + - Claude Code 会执行该命令 + +## 📝 常用命令速查 + +| 功能 | 命令 | +|------|------| +| 更新邮件配置 | `npm run email:config` | +| 测试邮件发送 | `npm run email:test` | +| 启动监听服务 | `npm run relay:pty` | +| 测试邮件解析 | `npm run relay:test` | +| 查看配置状态 | `cat .env` | + +## 🔧 故障排查 + +### 邮件发送失败 +- 检查飞书邮箱 SMTP 密码是否正确 +- 确认网络可以访问 smtp.feishu.cn:465 + +### 邮件接收失败 +- 确认 Gmail 应用专用密码已配置 +- 检查 Gmail 是否开启了 IMAP +- 查看服务日志中的错误信息 + +### 命令未执行 +- 确认回复邮件的主题包含原始 Token +- 检查邮件内容格式是否正确 +- 验证 Claude Code 是否在运行 + +## 💡 使用技巧 + +1. **邮件回复格式** + ``` + # 简单命令 + 继续 + + # 明确命令 + CMD: npm run build + + # 多行命令 + ``` + git add . + git commit -m "Update" + ``` + ``` + +2. **会话管理** + - 每个会话有1小时有效期 + - Token 在邮件主题中:`[TaskPing #TOKEN]` + - 过期后需要新的通知邮件 + +3. **安全建议** + - 只从受信任的邮箱发送命令 + - 定期更换应用专用密码 + - 不要在邮件中包含敏感信息 + +## 🎯 实际使用场景 + +1. **移动办公** + - 在手机上收到任务通知 + - 直接回复邮件继续任务 + - 无需返回电脑操作 + +2. **远程协作** + - 团队成员可以通过邮件控制任务 + - 支持多人协作(配置白名单) + - 保留邮件审计记录 + +3. **自动化工作流** + - 集成到现有邮件系统 + - 支持邮件规则触发 + - 可以配置自动回复 + +## 📚 更多文档 + +- [详细邮件配置指南](./EMAIL_GUIDE.md) +- [邮件回复功能说明](./EMAIL_REPLY_GUIDE.md) +- [系统架构文档](./EMAIL_ARCHITECTURE.md) + +--- + +有问题?查看 [GitHub Issues](https://github.com/JessyTsui/TaskPing/issues) 或运行调试模式: +```bash +LOG_LEVEL=debug npm run relay:pty +``` \ No newline at end of file diff --git a/package.json b/package.json index 6f0c4c4..eccfc28 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "start": "node email-automation.js", "relay:pty": "node start-relay-pty.js", "relay:test": "node test-email-reply.js", - "relay:start": "INJECTION_MODE=pty node src/relay/relay-pty.js" + "relay:start": "INJECTION_MODE=pty node src/relay/relay-pty.js", + "email:config": "node update-email-config.js", + "email:test": "node test-email-send.js" }, "bin": { "taskping-install": "./install.js", diff --git a/src/data/session-map.json b/src/data/session-map.json new file mode 100644 index 0000000..a083e7c --- /dev/null +++ b/src/data/session-map.json @@ -0,0 +1,9 @@ +{ + "TESTMDKLS3MK": { + "type": "pty", + "createdAt": 1753555687, + "expiresAt": 1753559287, + "cwd": "/Users/jessytsui/dev/TaskPing", + "description": "测试会话" + } +} \ No newline at end of file diff --git a/src/data/sessions/409d0107-1d7f-4892-a456-04d0f3c5300d.json b/src/data/sessions/409d0107-1d7f-4892-a456-04d0f3c5300d.json new file mode 100644 index 0000000..e32c6c4 --- /dev/null +++ b/src/data/sessions/409d0107-1d7f-4892-a456-04d0f3c5300d.json @@ -0,0 +1,13 @@ +{ + "id": "409d0107-1d7f-4892-a456-04d0f3c5300d", + "created": "2025-07-26T18:34:54.528Z", + "expires": "2025-07-27T18:34:54.528Z", + "notification": { + "type": "completed", + "project": "TaskPing", + "message": "[TaskPing] 任务已完成,Claude正在等待下一步指令" + }, + "status": "waiting", + "commandCount": 0, + "maxCommands": 10 +} \ No newline at end of file diff --git a/test-email-send.js b/test-email-send.js new file mode 100755 index 0000000..dbf6fd4 --- /dev/null +++ b/test-email-send.js @@ -0,0 +1,165 @@ +#!/usr/bin/env node + +/** + * 测试邮件发送功能 + * 验证 SMTP 配置是否正确 + */ + +const nodemailer = require('nodemailer'); +const fs = require('fs'); +const path = require('path'); +require('dotenv').config(); + +async function testEmailSend() { + console.log('📧 测试邮件发送功能\n'); + + // 检查配置 + if (!process.env.SMTP_HOST || !process.env.SMTP_USER || !process.env.SMTP_PASS) { + console.error('❌ 缺少 SMTP 配置,请检查 .env 文件'); + process.exit(1); + } + + // 创建测试会话 + const testToken = 'TEST' + Date.now().toString(36).toUpperCase(); + const sessionMapPath = process.env.SESSION_MAP_PATH || path.join(__dirname, 'src/data/session-map.json'); + + // 确保目录存在 + const dir = path.dirname(sessionMapPath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + + // 创建会话 + const sessions = fs.existsSync(sessionMapPath) + ? JSON.parse(fs.readFileSync(sessionMapPath, 'utf8')) + : {}; + + sessions[testToken] = { + type: 'pty', + createdAt: Math.floor(Date.now() / 1000), + expiresAt: Math.floor((Date.now() + 3600000) / 1000), // 1小时后过期 + cwd: process.cwd(), + description: '测试会话' + }; + + fs.writeFileSync(sessionMapPath, JSON.stringify(sessions, null, 2)); + console.log(`✅ 创建测试会话: ${testToken}\n`); + + // 创建邮件传输器 + const transporter = nodemailer.createTransport({ + host: process.env.SMTP_HOST, + port: parseInt(process.env.SMTP_PORT || '465'), + secure: process.env.SMTP_SECURE === 'true', + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASS + } + }); + + // 准备邮件内容 + const mailOptions = { + from: `${process.env.EMAIL_FROM_NAME || 'TaskPing'} <${process.env.EMAIL_FROM || process.env.SMTP_USER}>`, + to: process.env.EMAIL_TO || 'jiaxicui446@gmail.com', + subject: `[TaskPing #${testToken}] 测试邮件 - 等待您的指令`, + html: ` +
+

🔔 TaskPing 测试通知

+ +

这是一封测试邮件,用于验证邮件配置是否正确。

+ +
+

会话信息:

+

Token: ${testToken}

+

创建时间: ${new Date().toLocaleString('zh-CN')}

+

过期时间: ${new Date(Date.now() + 3600000).toLocaleString('zh-CN')}

+
+ +
+

📝 测试指令:

+

请回复以下任意命令来测试:

+
    +
  • 直接回复: echo "Hello from email"
  • +
  • 使用CMD前缀: CMD: pwd
  • +
  • 使用代码块: +
    +\`\`\`
    +ls -la
    +\`\`\`
    +                            
    +
  • +
+
+ +
+ +

+ 会话ID: ${testToken}
+ 发送自: ${process.env.SMTP_USER}
+ 发送到: ${process.env.EMAIL_TO || 'jiaxicui446@gmail.com'} +

+
+ `, + text: `TaskPing 测试通知\n\n` + + `这是一封测试邮件,用于验证邮件配置是否正确。\n\n` + + `会话Token: ${testToken}\n` + + `创建时间: ${new Date().toLocaleString('zh-CN')}\n\n` + + `请回复任意命令来测试,例如: echo "Hello from email"\n\n` + + `会话ID: ${testToken}`, + headers: { + 'X-TaskPing-Session-ID': testToken, + 'X-TaskPing-Type': 'test' + } + }; + + // 发送邮件 + try { + console.log('🚀 正在发送测试邮件...'); + console.log(` 发件人: ${mailOptions.from}`); + console.log(` 收件人: ${mailOptions.to}`); + console.log(` 主题: ${mailOptions.subject}\n`); + + const info = await transporter.sendMail(mailOptions); + + console.log('✅ 邮件发送成功!'); + console.log(` Message ID: ${info.messageId}`); + console.log(` Response: ${info.response}\n`); + + console.log('📋 下一步操作:'); + console.log('1. 检查收件箱是否收到邮件'); + console.log('2. 确保 Gmail 已配置应用专用密码'); + console.log('3. 启动邮件监听服务: npm run relay:pty'); + console.log('4. 回复邮件测试命令注入功能'); + console.log(`\n💡 回复时主题保持: [TaskPing #${testToken}]`); + + } catch (error) { + console.error('❌ 邮件发送失败:', error.message); + + if (error.code === 'EAUTH') { + console.log('\n可能的原因:'); + console.log('1. SMTP 密码错误'); + console.log('2. 邮箱未开启 SMTP 服务'); + console.log('3. 需要使用应用专用密码而非账号密码'); + } + + if (error.code === 'ECONNECTION') { + console.log('\n可能的原因:'); + console.log('1. SMTP 服务器地址或端口错误'); + console.log('2. 网络连接问题'); + console.log('3. 防火墙阻止了连接'); + } + + process.exit(1); + } +} + +// 主函数 +async function main() { + console.log('╔══════════════════════════════════════════════════════════╗'); + console.log('║ TaskPing Email Send Test ║'); + console.log('╚══════════════════════════════════════════════════════════╝\n'); + + await testEmailSend(); +} + +// 运行 +main().catch(console.error); \ No newline at end of file diff --git a/update-email-config.js b/update-email-config.js new file mode 100755 index 0000000..ac018f9 --- /dev/null +++ b/update-email-config.js @@ -0,0 +1,142 @@ +#!/usr/bin/env node + +/** + * 更新邮件配置 + * 从 .env 文件读取邮件配置并更新到 channels.json + */ + +const fs = require('fs'); +const path = require('path'); +require('dotenv').config(); + +function updateEmailConfig() { + console.log('📧 正在更新邮件配置...\n'); + + // 验证必需的环境变量 + const required = ['SMTP_HOST', 'SMTP_USER', 'SMTP_PASS', 'EMAIL_TO']; + const missing = required.filter(key => !process.env[key]); + + if (missing.length > 0) { + console.error('❌ 缺少必需的环境变量:'); + missing.forEach(key => console.log(` - ${key}`)); + console.log('\n请检查 .env 文件配置'); + process.exit(1); + } + + // 构建邮件配置 + const emailConfig = { + email: { + type: 'email', + enabled: true, + config: { + smtp: { + host: process.env.SMTP_HOST, + port: parseInt(process.env.SMTP_PORT || '465'), + secure: process.env.SMTP_SECURE === 'true', + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASS + } + }, + imap: { + host: process.env.IMAP_HOST, + port: parseInt(process.env.IMAP_PORT || '993'), + secure: process.env.IMAP_SECURE === 'true', + auth: { + user: process.env.IMAP_USER, + pass: process.env.IMAP_PASS + } + }, + from: `${process.env.EMAIL_FROM_NAME || 'TaskPing'} <${process.env.EMAIL_FROM || process.env.SMTP_USER}>`, + to: process.env.EMAIL_TO, + template: { + checkInterval: parseInt(process.env.CHECK_INTERVAL || '30') + } + } + } + }; + + // 读取现有的 channels.json + const channelsPath = path.join(__dirname, 'config/channels.json'); + let channels = {}; + + if (fs.existsSync(channelsPath)) { + try { + channels = JSON.parse(fs.readFileSync(channelsPath, 'utf8')); + } catch (error) { + console.warn('⚠️ 无法读取现有配置,将创建新配置'); + } + } + + // 更新邮件通道配置 + channels.email = emailConfig.email; + + // 写入配置文件 + try { + fs.writeFileSync(channelsPath, JSON.stringify(channels, null, 2)); + console.log('✅ 邮件配置已更新到 config/channels.json'); + + // 显示配置信息 + console.log('\n📋 当前配置:'); + console.log(` 发件服务器: ${process.env.SMTP_HOST}`); + console.log(` 发件邮箱: ${process.env.SMTP_USER}`); + console.log(` 收件邮箱: ${process.env.EMAIL_TO}`); + + if (process.env.IMAP_USER) { + console.log(` 监听邮箱: ${process.env.IMAP_USER}`); + console.log(` IMAP服务器: ${process.env.IMAP_HOST}`); + } else { + console.log('\n⚠️ 注意: IMAP 未配置,邮件回复功能需要配置 Gmail 的 IMAP 信息'); + console.log(' 请在 .env 文件中设置 IMAP_PASS(Gmail应用专用密码)'); + } + + console.log('\n💡 提示:'); + console.log(' 1. Gmail 需要使用应用专用密码'); + console.log(' 访问 https://myaccount.google.com/apppasswords 生成'); + console.log(' 2. 测试邮件发送: npm test'); + console.log(' 3. 启动邮件监听: npm run relay:pty'); + + } catch (error) { + console.error('❌ 更新配置失败:', error.message); + process.exit(1); + } +} + +// 显示 Gmail 配置指南 +function showGmailGuide() { + console.log('\n📖 Gmail 配置指南:'); + console.log('1. 登录 Gmail 账号'); + console.log('2. 访问 https://myaccount.google.com/security'); + console.log('3. 开启"两步验证"(如果未开启)'); + console.log('4. 访问 https://myaccount.google.com/apppasswords'); + console.log('5. 选择应用"邮件",设备"其他"'); + console.log('6. 输入名称"TaskPing"'); + console.log('7. 生成16位应用专用密码'); + console.log('8. 将密码复制到 .env 文件的 IMAP_PASS'); + console.log('\n注意: 应用专用密码只显示一次,请妥善保存'); +} + +// 主函数 +function main() { + console.log('╔══════════════════════════════════════════════════════════╗'); + console.log('║ TaskPing Email Configuration ║'); + console.log('╚══════════════════════════════════════════════════════════╝\n'); + + // 检查 .env 文件 + if (!fs.existsSync('.env')) { + console.error('❌ 未找到 .env 文件'); + console.log('请先复制 .env.example 到 .env 并配置'); + process.exit(1); + } + + // 更新配置 + updateEmailConfig(); + + // 如果 IMAP 未配置,显示 Gmail 指南 + if (!process.env.IMAP_PASS || process.env.IMAP_PASS === 'your-gmail-app-password') { + showGmailGuide(); + } +} + +// 运行 +main(); \ No newline at end of file