@zhin.js/adapter-email 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +355 -0
- package/lib/index.d.ts +77 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +362 -0
- package/lib/index.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 凉菜
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Email 适配器
|
|
2
|
+
|
|
3
|
+
基于 SMTP/IMAP 协议的邮件适配器,支持邮件的收发、附件处理等功能。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @zhin.js/adapter-email
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 依赖库
|
|
12
|
+
|
|
13
|
+
本适配器使用以下库:
|
|
14
|
+
- `nodemailer` - SMTP 邮件发送
|
|
15
|
+
- `imap` - IMAP 邮件接收
|
|
16
|
+
- `mailparser` - 邮件内容解析
|
|
17
|
+
|
|
18
|
+
## 配置
|
|
19
|
+
|
|
20
|
+
### 基础配置
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { EmailBotConfig } from '@zhin.js/adapter-email'
|
|
24
|
+
|
|
25
|
+
const emailConfig: EmailBotConfig = {
|
|
26
|
+
context: 'email',
|
|
27
|
+
name: 'my-email-bot',
|
|
28
|
+
smtp: {
|
|
29
|
+
host: 'smtp.gmail.com',
|
|
30
|
+
port: 587,
|
|
31
|
+
secure: false, // true for 465, false for other ports
|
|
32
|
+
auth: {
|
|
33
|
+
user: 'your-email@gmail.com',
|
|
34
|
+
pass: 'your-app-password'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
imap: {
|
|
38
|
+
host: 'imap.gmail.com',
|
|
39
|
+
port: 993,
|
|
40
|
+
tls: true,
|
|
41
|
+
user: 'your-email@gmail.com',
|
|
42
|
+
password: 'your-app-password',
|
|
43
|
+
checkInterval: 60000, // 检查新邮件间隔(毫秒)
|
|
44
|
+
mailbox: 'INBOX', // 监听的邮箱文件夹
|
|
45
|
+
markSeen: true // 是否标记已读
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 完整配置选项
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const fullEmailConfig: EmailBotConfig = {
|
|
54
|
+
context: 'email',
|
|
55
|
+
name: 'advanced-email-bot',
|
|
56
|
+
smtp: {
|
|
57
|
+
host: 'smtp.gmail.com',
|
|
58
|
+
port: 587,
|
|
59
|
+
secure: false,
|
|
60
|
+
auth: {
|
|
61
|
+
user: 'your-email@gmail.com',
|
|
62
|
+
pass: 'your-app-password'
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
imap: {
|
|
66
|
+
host: 'imap.gmail.com',
|
|
67
|
+
port: 993,
|
|
68
|
+
tls: true,
|
|
69
|
+
user: 'your-email@gmail.com',
|
|
70
|
+
password: 'your-app-password',
|
|
71
|
+
checkInterval: 30000, // 30秒检查一次
|
|
72
|
+
mailbox: 'INBOX',
|
|
73
|
+
markSeen: true
|
|
74
|
+
},
|
|
75
|
+
attachments: {
|
|
76
|
+
enabled: true,
|
|
77
|
+
downloadPath: './downloads/email', // 附件下载路径
|
|
78
|
+
maxFileSize: 10 * 1024 * 1024, // 10MB 最大文件大小
|
|
79
|
+
allowedTypes: ['image/*', 'text/*', 'application/pdf'] // 允许的文件类型
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 使用示例
|
|
85
|
+
|
|
86
|
+
### 基础使用
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { createApp } from 'zhin.js'
|
|
90
|
+
import EmailAdapter from '@zhin.js/adapter-email'
|
|
91
|
+
|
|
92
|
+
const app = createApp({
|
|
93
|
+
adapters: {
|
|
94
|
+
email: {
|
|
95
|
+
context: 'email',
|
|
96
|
+
name: 'email-bot',
|
|
97
|
+
smtp: {
|
|
98
|
+
host: 'smtp.gmail.com',
|
|
99
|
+
port: 587,
|
|
100
|
+
secure: false,
|
|
101
|
+
auth: {
|
|
102
|
+
user: 'your-email@gmail.com',
|
|
103
|
+
pass: 'your-app-password'
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
imap: {
|
|
107
|
+
host: 'imap.gmail.com',
|
|
108
|
+
port: 993,
|
|
109
|
+
tls: true,
|
|
110
|
+
user: 'your-email@gmail.com',
|
|
111
|
+
password: 'your-app-password'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
// 处理接收到的邮件
|
|
118
|
+
app.on('message.receive', (message) => {
|
|
119
|
+
if (message.$adapter === 'email') {
|
|
120
|
+
console.log('收到邮件:', message.$content)
|
|
121
|
+
|
|
122
|
+
// 回复邮件
|
|
123
|
+
message.$reply('感谢您的邮件!')
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
app.start()
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 发送邮件
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// 发送简单文本邮件
|
|
134
|
+
await app.sendMessage({
|
|
135
|
+
adapter: 'email',
|
|
136
|
+
channel_id: 'recipient@example.com',
|
|
137
|
+
content: '这是一条测试邮件'
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
// 发送带附件的邮件
|
|
141
|
+
await app.sendMessage({
|
|
142
|
+
adapter: 'email',
|
|
143
|
+
channel_id: 'recipient@example.com',
|
|
144
|
+
content: [
|
|
145
|
+
{ type: 'text', data: { content: '请查收附件' } },
|
|
146
|
+
{ type: 'file', data: { url: '/path/to/file.pdf', filename: 'report.pdf' } }
|
|
147
|
+
]
|
|
148
|
+
})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 处理特定邮件
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
app.addCommand('auto-reply', {
|
|
155
|
+
match: (message) => {
|
|
156
|
+
return message.$adapter === 'email' &&
|
|
157
|
+
message.$content.some(seg => seg.type === 'text' &&
|
|
158
|
+
seg.data.content.includes('自动回复'))
|
|
159
|
+
},
|
|
160
|
+
action: async (message) => {
|
|
161
|
+
await message.$reply('这是自动回复邮件。')
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 邮件服务商配置
|
|
167
|
+
|
|
168
|
+
### Gmail
|
|
169
|
+
|
|
170
|
+
1. 开启两步验证
|
|
171
|
+
2. 生成应用专用密码
|
|
172
|
+
3. 使用以下配置:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
{
|
|
176
|
+
smtp: {
|
|
177
|
+
host: 'smtp.gmail.com',
|
|
178
|
+
port: 587,
|
|
179
|
+
secure: false
|
|
180
|
+
},
|
|
181
|
+
imap: {
|
|
182
|
+
host: 'imap.gmail.com',
|
|
183
|
+
port: 993,
|
|
184
|
+
tls: true
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Outlook/Hotmail
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
{
|
|
193
|
+
smtp: {
|
|
194
|
+
host: 'smtp-mail.outlook.com',
|
|
195
|
+
port: 587,
|
|
196
|
+
secure: false
|
|
197
|
+
},
|
|
198
|
+
imap: {
|
|
199
|
+
host: 'outlook.office365.com',
|
|
200
|
+
port: 993,
|
|
201
|
+
tls: true
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### QQ邮箱
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
{
|
|
210
|
+
smtp: {
|
|
211
|
+
host: 'smtp.qq.com',
|
|
212
|
+
port: 587,
|
|
213
|
+
secure: false
|
|
214
|
+
},
|
|
215
|
+
imap: {
|
|
216
|
+
host: 'imap.qq.com',
|
|
217
|
+
port: 993,
|
|
218
|
+
tls: true
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### 163邮箱
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
{
|
|
227
|
+
smtp: {
|
|
228
|
+
host: 'smtp.163.com',
|
|
229
|
+
port: 465,
|
|
230
|
+
secure: true
|
|
231
|
+
},
|
|
232
|
+
imap: {
|
|
233
|
+
host: 'imap.163.com',
|
|
234
|
+
port: 993,
|
|
235
|
+
tls: true
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## 支持的消息类型
|
|
241
|
+
|
|
242
|
+
### 接收消息
|
|
243
|
+
|
|
244
|
+
| 类型 | 说明 | MessageSegment |
|
|
245
|
+
|------|------|----------------|
|
|
246
|
+
| 文本 | 邮件正文内容 | `text` |
|
|
247
|
+
| HTML | HTML格式邮件 | `text` (转换为纯文本) |
|
|
248
|
+
| 图片附件 | 图片文件 | `image` |
|
|
249
|
+
| 文件附件 | 其他文件 | `file` |
|
|
250
|
+
| 主题 | 邮件主题 | `text` (前缀显示) |
|
|
251
|
+
|
|
252
|
+
### 发送消息
|
|
253
|
+
|
|
254
|
+
| MessageSegment 类型 | 说明 | 实现方式 |
|
|
255
|
+
|-------------------|------|----------|
|
|
256
|
+
| `text` | 文本内容 | 作为邮件正文 |
|
|
257
|
+
| `image` | 图片 | 作为邮件附件 |
|
|
258
|
+
| `file` | 文件 | 作为邮件附件 |
|
|
259
|
+
|
|
260
|
+
## 频道类型
|
|
261
|
+
|
|
262
|
+
| 类型 | 说明 | channel_id 格式 |
|
|
263
|
+
|------|------|----------------|
|
|
264
|
+
| `private` | 个人邮箱 | 邮箱地址 |
|
|
265
|
+
|
|
266
|
+
注意:邮件适配器只支持 `private` 类型的频道,因为邮件本质上是点对点的通信方式。
|
|
267
|
+
|
|
268
|
+
## 特性
|
|
269
|
+
|
|
270
|
+
### ✅ 已实现功能
|
|
271
|
+
|
|
272
|
+
- **邮件接收**: 基于 IMAP 协议接收新邮件
|
|
273
|
+
- **邮件发送**: 基于 SMTP 协议发送邮件
|
|
274
|
+
- **附件支持**: 支持接收和发送各种类型的附件
|
|
275
|
+
- **定时检查**: 可配置的邮件检查间隔
|
|
276
|
+
- **HTML转换**: 自动将HTML邮件转换为纯文本
|
|
277
|
+
- **主题解析**: 解析并显示邮件主题
|
|
278
|
+
- **回复支持**: 支持回复邮件
|
|
279
|
+
- **多邮箱支持**: 支持主流邮箱服务商
|
|
280
|
+
|
|
281
|
+
### 📋 配置选项
|
|
282
|
+
|
|
283
|
+
- **SMTP设置**: 完整的SMTP服务器配置
|
|
284
|
+
- **IMAP设置**: 完整的IMAP服务器配置
|
|
285
|
+
- **附件管理**: 可配置的附件下载和处理
|
|
286
|
+
- **检查间隔**: 自定义邮件检查频率
|
|
287
|
+
- **邮箱选择**: 指定监听的邮箱文件夹
|
|
288
|
+
|
|
289
|
+
### 🔧 高级功能
|
|
290
|
+
|
|
291
|
+
- **邮件过滤**: 只处理未读邮件
|
|
292
|
+
- **自动标记**: 可选的已读标记
|
|
293
|
+
- **错误处理**: 完整的错误处理和重连机制
|
|
294
|
+
- **日志记录**: 详细的操作日志
|
|
295
|
+
|
|
296
|
+
## 安全注意事项
|
|
297
|
+
|
|
298
|
+
1. **应用专用密码**: 建议使用应用专用密码而非账户密码
|
|
299
|
+
2. **TLS/SSL**: 确保启用加密连接
|
|
300
|
+
3. **权限最小化**: 只授予必要的邮箱权限
|
|
301
|
+
4. **配置保护**: 不要将邮箱密码硬编码在代码中
|
|
302
|
+
|
|
303
|
+
## 故障排除
|
|
304
|
+
|
|
305
|
+
### 连接问题
|
|
306
|
+
|
|
307
|
+
1. **SMTP连接失败**:
|
|
308
|
+
- 检查服务器地址和端口
|
|
309
|
+
- 确认账户密码正确
|
|
310
|
+
- 检查是否需要应用专用密码
|
|
311
|
+
|
|
312
|
+
2. **IMAP连接失败**:
|
|
313
|
+
- 确认IMAP服务已启用
|
|
314
|
+
- 检查TLS设置
|
|
315
|
+
- 验证邮箱权限设置
|
|
316
|
+
|
|
317
|
+
3. **邮件接收异常**:
|
|
318
|
+
- 检查邮箱文件夹名称
|
|
319
|
+
- 确认检查间隔设置
|
|
320
|
+
- 查看错误日志
|
|
321
|
+
|
|
322
|
+
### 附件问题
|
|
323
|
+
|
|
324
|
+
1. **附件下载失败**:
|
|
325
|
+
- 检查下载路径权限
|
|
326
|
+
- 验证文件大小限制
|
|
327
|
+
- 确认文件类型允许
|
|
328
|
+
|
|
329
|
+
2. **附件发送失败**:
|
|
330
|
+
- 检查文件路径是否存在
|
|
331
|
+
- 验证文件大小限制
|
|
332
|
+
- 确认SMTP服务器支持
|
|
333
|
+
|
|
334
|
+
## 示例项目
|
|
335
|
+
|
|
336
|
+
完整的使用示例可以在 `test-bot` 目录中找到。
|
|
337
|
+
|
|
338
|
+
## API 参考
|
|
339
|
+
|
|
340
|
+
### EmailBot 类
|
|
341
|
+
|
|
342
|
+
#### 方法
|
|
343
|
+
|
|
344
|
+
- `$connect()`: 连接邮件服务器
|
|
345
|
+
- `$disconnect()`: 断开连接
|
|
346
|
+
- `$formatMessage(emailMsg)`: 格式化邮件消息
|
|
347
|
+
- `$sendMessage(options)`: 发送邮件
|
|
348
|
+
|
|
349
|
+
#### 事件
|
|
350
|
+
|
|
351
|
+
- `message.receive`: 接收到新邮件时触发
|
|
352
|
+
|
|
353
|
+
### 配置接口
|
|
354
|
+
|
|
355
|
+
详细的配置接口说明请参考 TypeScript 类型定义。
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Attachment } from 'mailparser';
|
|
2
|
+
import { Bot, BotConfig, Adapter, Plugin, Message, SendOptions, MessageSegment } from "zhin.js";
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
declare module 'zhin.js' {
|
|
5
|
+
interface RegisteredAdapters {
|
|
6
|
+
email: Adapter<EmailBot>;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export interface SmtpConfig {
|
|
10
|
+
host: string;
|
|
11
|
+
port: number;
|
|
12
|
+
secure: boolean;
|
|
13
|
+
auth: {
|
|
14
|
+
user: string;
|
|
15
|
+
pass: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface ImapConfig {
|
|
19
|
+
host: string;
|
|
20
|
+
port: number;
|
|
21
|
+
tls: boolean;
|
|
22
|
+
user: string;
|
|
23
|
+
password: string;
|
|
24
|
+
checkInterval?: number;
|
|
25
|
+
mailbox?: string;
|
|
26
|
+
markSeen?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export type EmailBotConfig = BotConfig & {
|
|
29
|
+
context: 'email';
|
|
30
|
+
name: string;
|
|
31
|
+
smtp: SmtpConfig;
|
|
32
|
+
imap: ImapConfig;
|
|
33
|
+
attachments?: {
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
downloadPath?: string;
|
|
36
|
+
maxFileSize?: number;
|
|
37
|
+
allowedTypes?: string[];
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export interface EmailMessage {
|
|
41
|
+
messageId: string;
|
|
42
|
+
from: string;
|
|
43
|
+
to: string[];
|
|
44
|
+
cc?: string[];
|
|
45
|
+
bcc?: string[];
|
|
46
|
+
subject: string;
|
|
47
|
+
text?: string;
|
|
48
|
+
html?: string;
|
|
49
|
+
attachments: Attachment[];
|
|
50
|
+
date: Date;
|
|
51
|
+
uid: number;
|
|
52
|
+
}
|
|
53
|
+
export declare class EmailBot extends EventEmitter implements Bot<EmailMessage, EmailBotConfig> {
|
|
54
|
+
$config: EmailBotConfig;
|
|
55
|
+
plugin: Plugin;
|
|
56
|
+
private smtpTransporter;
|
|
57
|
+
private imapConnection;
|
|
58
|
+
private checkTimer;
|
|
59
|
+
private isConnected;
|
|
60
|
+
constructor(plugin: Plugin, config: EmailBotConfig);
|
|
61
|
+
$connect(): Promise<void>;
|
|
62
|
+
$disconnect(): Promise<void>;
|
|
63
|
+
private setupImapListeners;
|
|
64
|
+
private startEmailCheck;
|
|
65
|
+
private checkForNewEmails;
|
|
66
|
+
private handleImapMessage;
|
|
67
|
+
private parseEmailMessage;
|
|
68
|
+
$formatMessage(emailMsg: EmailMessage): Message<EmailMessage>;
|
|
69
|
+
static parseEmailContent(email: EmailMessage): MessageSegment[];
|
|
70
|
+
$sendMessage(options: SendOptions): Promise<void>;
|
|
71
|
+
private formatSendContent;
|
|
72
|
+
private downloadAttachment;
|
|
73
|
+
}
|
|
74
|
+
export default class EmailAdapter extends Adapter<EmailBot> {
|
|
75
|
+
constructor();
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import nodemailer from 'nodemailer';
|
|
2
|
+
import Imap from 'imap';
|
|
3
|
+
import { simpleParser } from 'mailparser';
|
|
4
|
+
import { Adapter, registerAdapter, Message, segment } from "zhin.js";
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { createWriteStream, promises as fs } from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
// Bot 类实现
|
|
9
|
+
export class EmailBot extends EventEmitter {
|
|
10
|
+
$config;
|
|
11
|
+
plugin;
|
|
12
|
+
smtpTransporter = null;
|
|
13
|
+
imapConnection = null;
|
|
14
|
+
checkTimer = null;
|
|
15
|
+
isConnected = false;
|
|
16
|
+
constructor(plugin, config) {
|
|
17
|
+
super();
|
|
18
|
+
this.$config = config;
|
|
19
|
+
this.plugin = plugin;
|
|
20
|
+
// 设置默认值
|
|
21
|
+
this.$config.imap.checkInterval = this.$config.imap.checkInterval || 60000; // 1分钟
|
|
22
|
+
this.$config.imap.mailbox = this.$config.imap.mailbox || 'INBOX';
|
|
23
|
+
this.$config.imap.markSeen = this.$config.imap.markSeen !== false;
|
|
24
|
+
if (this.$config.attachments?.enabled) {
|
|
25
|
+
this.$config.attachments.downloadPath = this.$config.attachments.downloadPath || './downloads/email';
|
|
26
|
+
this.$config.attachments.maxFileSize = this.$config.attachments.maxFileSize || 10 * 1024 * 1024; // 10MB
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async $connect() {
|
|
30
|
+
try {
|
|
31
|
+
// 初始化 SMTP 传输器
|
|
32
|
+
this.smtpTransporter = nodemailer.createTransport({
|
|
33
|
+
host: this.$config.smtp.host,
|
|
34
|
+
port: this.$config.smtp.port,
|
|
35
|
+
secure: this.$config.smtp.secure,
|
|
36
|
+
auth: this.$config.smtp.auth
|
|
37
|
+
});
|
|
38
|
+
// 验证 SMTP 连接
|
|
39
|
+
await this.smtpTransporter.verify();
|
|
40
|
+
this.plugin.logger.info(`SMTP connection verified for ${this.$config.smtp.auth.user}`);
|
|
41
|
+
// 初始化 IMAP 连接
|
|
42
|
+
this.imapConnection = new Imap({
|
|
43
|
+
user: this.$config.imap.user,
|
|
44
|
+
password: this.$config.imap.password,
|
|
45
|
+
host: this.$config.imap.host,
|
|
46
|
+
port: this.$config.imap.port,
|
|
47
|
+
tls: this.$config.imap.tls
|
|
48
|
+
});
|
|
49
|
+
// 设置 IMAP 事件监听
|
|
50
|
+
this.setupImapListeners();
|
|
51
|
+
// 连接 IMAP
|
|
52
|
+
await new Promise((resolve, reject) => {
|
|
53
|
+
this.imapConnection.once('ready', resolve);
|
|
54
|
+
this.imapConnection.once('error', reject);
|
|
55
|
+
this.imapConnection.connect();
|
|
56
|
+
});
|
|
57
|
+
this.plugin.logger.info(`IMAP connection established for ${this.$config.imap.user}`);
|
|
58
|
+
// 开始检查邮件
|
|
59
|
+
this.startEmailCheck();
|
|
60
|
+
this.isConnected = true;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.plugin.logger.error('Failed to connect email services:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async $disconnect() {
|
|
68
|
+
this.isConnected = false;
|
|
69
|
+
// 停止定时检查
|
|
70
|
+
if (this.checkTimer) {
|
|
71
|
+
clearInterval(this.checkTimer);
|
|
72
|
+
this.checkTimer = null;
|
|
73
|
+
}
|
|
74
|
+
// 关闭 IMAP 连接
|
|
75
|
+
if (this.imapConnection) {
|
|
76
|
+
this.imapConnection.end();
|
|
77
|
+
this.imapConnection = null;
|
|
78
|
+
}
|
|
79
|
+
// 关闭 SMTP 连接
|
|
80
|
+
if (this.smtpTransporter) {
|
|
81
|
+
this.smtpTransporter.close();
|
|
82
|
+
this.smtpTransporter = null;
|
|
83
|
+
}
|
|
84
|
+
this.plugin.logger.info('Email bot disconnected');
|
|
85
|
+
}
|
|
86
|
+
setupImapListeners() {
|
|
87
|
+
if (!this.imapConnection)
|
|
88
|
+
return;
|
|
89
|
+
this.imapConnection.on('mail', (numNewMsgs) => {
|
|
90
|
+
this.plugin.logger.debug(`Received ${numNewMsgs} new emails`);
|
|
91
|
+
this.checkForNewEmails();
|
|
92
|
+
});
|
|
93
|
+
this.imapConnection.on('error', (error) => {
|
|
94
|
+
this.plugin.logger.error('IMAP error:', error);
|
|
95
|
+
});
|
|
96
|
+
this.imapConnection.on('end', () => {
|
|
97
|
+
this.plugin.logger.info('IMAP connection ended');
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
startEmailCheck() {
|
|
101
|
+
if (this.checkTimer)
|
|
102
|
+
return;
|
|
103
|
+
this.checkTimer = setInterval(() => {
|
|
104
|
+
this.checkForNewEmails();
|
|
105
|
+
}, this.$config.imap.checkInterval);
|
|
106
|
+
// 立即检查一次
|
|
107
|
+
this.checkForNewEmails();
|
|
108
|
+
}
|
|
109
|
+
async checkForNewEmails() {
|
|
110
|
+
if (!this.imapConnection || !this.isConnected)
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
await new Promise((resolve, reject) => {
|
|
114
|
+
this.imapConnection.openBox(this.$config.imap.mailbox, false, (error, box) => {
|
|
115
|
+
if (error)
|
|
116
|
+
return reject(error);
|
|
117
|
+
// 搜索未读邮件
|
|
118
|
+
this.imapConnection.search(['UNSEEN'], (error, results) => {
|
|
119
|
+
if (error)
|
|
120
|
+
return reject(error);
|
|
121
|
+
if (results.length === 0) {
|
|
122
|
+
return resolve();
|
|
123
|
+
}
|
|
124
|
+
// 获取邮件
|
|
125
|
+
const fetch = this.imapConnection.fetch(results, {
|
|
126
|
+
bodies: '',
|
|
127
|
+
markSeen: this.$config.imap.markSeen
|
|
128
|
+
});
|
|
129
|
+
fetch.on('message', (msg, seqno) => {
|
|
130
|
+
this.handleImapMessage(msg, seqno);
|
|
131
|
+
});
|
|
132
|
+
fetch.once('error', reject);
|
|
133
|
+
fetch.once('end', resolve);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
this.plugin.logger.error('Error checking for new emails:', error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
handleImapMessage(msg, seqno) {
|
|
143
|
+
let body = '';
|
|
144
|
+
let uid = 0;
|
|
145
|
+
msg.on('body', (stream) => {
|
|
146
|
+
stream.on('data', (chunk) => {
|
|
147
|
+
body += chunk.toString('utf8');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
msg.once('attributes', (attrs) => {
|
|
151
|
+
uid = attrs.uid;
|
|
152
|
+
});
|
|
153
|
+
msg.once('end', async () => {
|
|
154
|
+
try {
|
|
155
|
+
const parsed = await simpleParser(body);
|
|
156
|
+
const emailMessage = this.parseEmailMessage(parsed, uid);
|
|
157
|
+
const formattedMessage = this.$formatMessage(emailMessage);
|
|
158
|
+
this.emit('message.receive', formattedMessage);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
this.plugin.logger.error('Error parsing email:', error);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
parseEmailMessage(parsed, uid) {
|
|
166
|
+
const getAddressText = (addr) => {
|
|
167
|
+
if (!addr)
|
|
168
|
+
return [];
|
|
169
|
+
if (Array.isArray(addr)) {
|
|
170
|
+
return addr.map((a) => a.text || a.address || a.toString());
|
|
171
|
+
}
|
|
172
|
+
return [addr.text || addr.address || addr.toString()];
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
messageId: parsed.messageId || '',
|
|
176
|
+
from: parsed.from ? getAddressText(parsed.from)[0] || '' : '',
|
|
177
|
+
to: getAddressText(parsed.to),
|
|
178
|
+
cc: getAddressText(parsed.cc),
|
|
179
|
+
bcc: getAddressText(parsed.bcc),
|
|
180
|
+
subject: parsed.subject || '',
|
|
181
|
+
text: parsed.text || '',
|
|
182
|
+
html: parsed.html ? parsed.html.toString() : '',
|
|
183
|
+
attachments: parsed.attachments || [],
|
|
184
|
+
date: parsed.date || new Date(),
|
|
185
|
+
uid
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
$formatMessage(emailMsg) {
|
|
189
|
+
// 确定频道类型和ID
|
|
190
|
+
const channelType = 'private';
|
|
191
|
+
const channelId = emailMsg.from;
|
|
192
|
+
// 解析邮件内容
|
|
193
|
+
const content = EmailBot.parseEmailContent(emailMsg);
|
|
194
|
+
const result = Message.from(emailMsg, {
|
|
195
|
+
$id: emailMsg.messageId,
|
|
196
|
+
$adapter: 'email',
|
|
197
|
+
$bot: this.$config.name,
|
|
198
|
+
$sender: {
|
|
199
|
+
id: emailMsg.from,
|
|
200
|
+
name: emailMsg.from.split('<')[0].trim() || emailMsg.from
|
|
201
|
+
},
|
|
202
|
+
$channel: {
|
|
203
|
+
id: channelId,
|
|
204
|
+
type: channelType
|
|
205
|
+
},
|
|
206
|
+
$raw: JSON.stringify(emailMsg),
|
|
207
|
+
$timestamp: emailMsg.date.getTime(),
|
|
208
|
+
$content: content,
|
|
209
|
+
$reply: async (content) => {
|
|
210
|
+
await this.$sendMessage({
|
|
211
|
+
context: this.$config.context,
|
|
212
|
+
bot: this.$config.name,
|
|
213
|
+
id: emailMsg.from,
|
|
214
|
+
type: 'private',
|
|
215
|
+
content
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
static parseEmailContent(email) {
|
|
222
|
+
const segments = [];
|
|
223
|
+
// 添加主题(如果有且不为空)
|
|
224
|
+
if (email.subject) {
|
|
225
|
+
segments.push(segment.text(`Subject: ${email.subject}\n\n`));
|
|
226
|
+
}
|
|
227
|
+
// 添加文本内容
|
|
228
|
+
if (email.text) {
|
|
229
|
+
segments.push(segment.text(email.text));
|
|
230
|
+
}
|
|
231
|
+
// 如果没有纯文本但有HTML,尝试转换
|
|
232
|
+
if (!email.text && email.html) {
|
|
233
|
+
// 简单的HTML到文本转换
|
|
234
|
+
const textFromHtml = email.html
|
|
235
|
+
.replace(/<[^>]*>/g, '') // 移除HTML标签
|
|
236
|
+
.replace(/ /g, ' ')
|
|
237
|
+
.replace(/&/g, '&')
|
|
238
|
+
.replace(/</g, '<')
|
|
239
|
+
.replace(/>/g, '>')
|
|
240
|
+
.replace(/"/g, '"')
|
|
241
|
+
.trim();
|
|
242
|
+
if (textFromHtml) {
|
|
243
|
+
segments.push(segment.text(textFromHtml));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// 处理附件
|
|
247
|
+
for (const attachment of email.attachments) {
|
|
248
|
+
if (attachment.contentType?.startsWith('image/')) {
|
|
249
|
+
segments.push(segment('image', {
|
|
250
|
+
filename: attachment.filename,
|
|
251
|
+
contentType: attachment.contentType,
|
|
252
|
+
size: attachment.size
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
segments.push(segment('file', {
|
|
257
|
+
filename: attachment.filename,
|
|
258
|
+
contentType: attachment.contentType,
|
|
259
|
+
size: attachment.size
|
|
260
|
+
}));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return segments.length > 0 ? segments : [segment.text('(Empty email)')];
|
|
264
|
+
}
|
|
265
|
+
async $sendMessage(options) {
|
|
266
|
+
if (!this.smtpTransporter) {
|
|
267
|
+
throw new Error('SMTP transporter not initialized');
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
const mailOptions = await this.formatSendContent(options);
|
|
271
|
+
const info = await this.smtpTransporter.sendMail(mailOptions);
|
|
272
|
+
this.plugin.logger.debug('Email sent:', info.messageId);
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
this.plugin.logger.error('Failed to send email:', error);
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async formatSendContent(options) {
|
|
280
|
+
const mailOptions = {
|
|
281
|
+
from: this.$config.smtp.auth.user,
|
|
282
|
+
to: options.id,
|
|
283
|
+
subject: 'Message from Bot'
|
|
284
|
+
};
|
|
285
|
+
if (typeof options.content === 'string') {
|
|
286
|
+
mailOptions.text = options.content;
|
|
287
|
+
}
|
|
288
|
+
else if (Array.isArray(options.content)) {
|
|
289
|
+
const textParts = [];
|
|
290
|
+
const htmlParts = [];
|
|
291
|
+
const attachments = [];
|
|
292
|
+
for (const item of options.content) {
|
|
293
|
+
if (typeof item === 'string') {
|
|
294
|
+
textParts.push(item);
|
|
295
|
+
htmlParts.push(item.replace(/\n/g, '<br>'));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
const segment = item;
|
|
299
|
+
switch (segment.type) {
|
|
300
|
+
case 'text':
|
|
301
|
+
const textContent = segment.data.text || segment.data.content || '';
|
|
302
|
+
textParts.push(textContent);
|
|
303
|
+
htmlParts.push(textContent.replace(/\n/g, '<br>'));
|
|
304
|
+
break;
|
|
305
|
+
case 'image':
|
|
306
|
+
if (segment.data.url) {
|
|
307
|
+
attachments.push({
|
|
308
|
+
filename: segment.data.filename || 'image.png',
|
|
309
|
+
path: segment.data.url
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
break;
|
|
313
|
+
case 'file':
|
|
314
|
+
if (segment.data.url) {
|
|
315
|
+
attachments.push({
|
|
316
|
+
filename: segment.data.filename || 'file',
|
|
317
|
+
path: segment.data.url
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (textParts.length > 0) {
|
|
325
|
+
mailOptions.text = textParts.join('\n');
|
|
326
|
+
mailOptions.html = htmlParts.join('<br>');
|
|
327
|
+
}
|
|
328
|
+
if (attachments.length > 0) {
|
|
329
|
+
mailOptions.attachments = attachments;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// 如果有回复对象,可以在这里处理
|
|
333
|
+
// 邮件适配器暂时不支持回复对象
|
|
334
|
+
return mailOptions;
|
|
335
|
+
}
|
|
336
|
+
// 下载附件到本地
|
|
337
|
+
async downloadAttachment(attachment) {
|
|
338
|
+
if (!this.$config.attachments?.enabled || !this.$config.attachments.downloadPath) {
|
|
339
|
+
throw new Error('Attachment download is not enabled');
|
|
340
|
+
}
|
|
341
|
+
const downloadPath = this.$config.attachments.downloadPath;
|
|
342
|
+
await fs.mkdir(downloadPath, { recursive: true });
|
|
343
|
+
const filename = attachment.filename || `attachment_${Date.now()}`;
|
|
344
|
+
const filepath = path.join(downloadPath, filename);
|
|
345
|
+
return new Promise((resolve, reject) => {
|
|
346
|
+
const writeStream = createWriteStream(filepath);
|
|
347
|
+
writeStream.write(attachment.content);
|
|
348
|
+
writeStream.end();
|
|
349
|
+
writeStream.on('finish', () => resolve(filepath));
|
|
350
|
+
writeStream.on('error', reject);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// 创建和注册适配器
|
|
355
|
+
export default class EmailAdapter extends Adapter {
|
|
356
|
+
constructor() {
|
|
357
|
+
super('email', EmailBot);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// 注册适配器到全局
|
|
361
|
+
registerAdapter(new EmailAdapter());
|
|
362
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zhin.js/adapter-email",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Email adapter for zhin.js",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@types/imap": "^0.8.40",
|
|
10
|
+
"@types/nodemailer": "^6.4.14",
|
|
11
|
+
"imap": "^0.8.19",
|
|
12
|
+
"mailparser": "^3.6.5",
|
|
13
|
+
"nodemailer": "^6.9.8"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@zhin.js/types": "^1.0.1",
|
|
17
|
+
"zhin.js": "^1.0.1"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/mailparser": "^3.4.6",
|
|
21
|
+
"@types/node": "^20.10.6",
|
|
22
|
+
"typescript": "^5.3.3"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"zhin",
|
|
26
|
+
"adapter",
|
|
27
|
+
"email",
|
|
28
|
+
"smtp",
|
|
29
|
+
"imap",
|
|
30
|
+
"mail"
|
|
31
|
+
],
|
|
32
|
+
"author": "",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/zhinjs/zhin-next",
|
|
37
|
+
"directory": "adapters/email"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"lib"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc",
|
|
44
|
+
"dev": "tsc --watch",
|
|
45
|
+
"clean": "rm -rf lib"
|
|
46
|
+
}
|
|
47
|
+
}
|