配置邮件账号并添加测试工具

- 配置飞书邮箱发件 (noreply@pandalla.ai)
- 配置 Gmail 收件 (jiaxicui446@gmail.com)
- 添加邮件配置更新脚本
- 添加邮件发送测试工具
- 创建快速配置指南
- 更新 npm 脚本命令

现在可以:
1. 通过飞书邮箱发送通知
2. 在 Gmail 接收通知
3. 回复邮件控制 Claude Code

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
panda 2025-07-27 02:49:07 +08:00
parent ba4a6343aa
commit be9eb49734
7 changed files with 501 additions and 7 deletions

View File

@ -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 <panda@pandalla.ai>",
"from": "TaskPing 通知系统 <noreply@pandalla.ai>",
"to": "jiaxicui446@gmail.com",
"template": {
"checkInterval": 30

163
docs/QUICK_SETUP_GUIDE.md Normal file
View File

@ -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: <xxx@pandalla.ai>
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
```

View File

@ -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",

View File

@ -0,0 +1,9 @@
{
"TESTMDKLS3MK": {
"type": "pty",
"createdAt": 1753555687,
"expiresAt": 1753559287,
"cwd": "/Users/jessytsui/dev/TaskPing",
"description": "测试会话"
}
}

View File

@ -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
}

165
test-email-send.js Executable file
View File

@ -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: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #333;">🔔 TaskPing 测试通知</h2>
<p>这是一封测试邮件用于验证邮件配置是否正确</p>
<div style="background: #f5f5f5; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>会话信息</strong></p>
<p>Token: <code>${testToken}</code></p>
<p>创建时间: ${new Date().toLocaleString('zh-CN')}</p>
<p>过期时间: ${new Date(Date.now() + 3600000).toLocaleString('zh-CN')}</p>
</div>
<div style="background: #e8f4f8; padding: 15px; border-radius: 5px; margin: 20px 0;">
<p><strong>📝 测试指令</strong></p>
<p>请回复以下任意命令来测试</p>
<ul>
<li>直接回复: <code>echo "Hello from email"</code></li>
<li>使用CMD前缀: <code>CMD: pwd</code></li>
<li>使用代码块:
<pre style="background: white; padding: 10px; border-radius: 3px;">
\`\`\`
ls -la
\`\`\`
</pre>
</li>
</ul>
</div>
<hr style="border: none; border-top: 1px solid #ddd; margin: 30px 0;">
<p style="color: #666; font-size: 12px;">
会话ID: ${testToken}<br>
发送自: ${process.env.SMTP_USER}<br>
发送到: ${process.env.EMAIL_TO || 'jiaxicui446@gmail.com'}
</p>
</div>
`,
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);

142
update-email-config.js Executable file
View File

@ -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_PASSGmail应用专用密码');
}
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();