【Skills开发实战指南】第27篇:邮件管理Skill:自动化收发与分类
在数字时代,邮件仍然是沟通的核心方式,但邮件管理却成为许多人头痛的问题。本文深入探讨如何通过Skills实现邮件的自动化处理,从邮件接收、发送、分类到智能回复,构建一个功能完整的邮件管理解决方案。你将学习到邮件协议(SMTP、IMAP、POP3)、邮件解析库、附件处理、智能分类算法等关键技术,掌握如何构建一个企业级的邮件管理系统,实现邮件处理的高效自动化,让你的邮箱管理变得井井有条。
快速导航
读完本文,你将获得:
- ✅ 掌握邮件协议的核心原理:SMTP、IMAP、POP3
- ✅ 学会使用Nodemailer、MailParser等核心库
- ✅ 实现邮件的自动收发、附件处理、模板发送
- ✅ 构建智能邮件分类与过滤系统
- ✅ 实现邮件监控与自动回复功能
- ✅ 掌握企业级邮件管理的最佳实践
- ✅ 了解邮件系统的安全与性能优化
一、邮件管理自动化的价值与挑战
1.1 为什么需要邮件管理自动化?
在现代工作环境中,邮件管理面临诸多挑战:
- 邮件数量爆炸:平均每人每天收到数十到上百封邮件
- 信息过载:重要邮件容易被埋没在垃圾邮件中
- 时间消耗:手动处理邮件占用大量工作时间(平均2-3小时/天)
- 分类困难:需要人工判断邮件类别和优先级
- 回复效率低:重复性回复耗时耗力
- 多邮箱管理:个人、工作、项目等多邮箱难以统一管理
1.2 邮件管理自动化的核心技术栈
构建邮件管理Skill需要掌握以下技术组件:
// mail-tech-stack.js - 邮件管理的核心技术栈
const MailTechStack = {
// 邮件发送库
nodemailer: {
description: "Node.js邮件发送库,支持SMTP",
features: ["邮件发送", "附件支持", "HTML邮件", "模板支持"],
npm: "npm install nodemailer"
},
// 邮件接收库
imap: {
description: "IMAP邮件接收库",
features: ["邮件接收", "文件夹管理", "邮件搜索"],
npm: "npm install imap"
},
mailparser: {
description: "邮件解析库",
features: ["邮件解析", "附件提取", "HTML/纯文本转换"],
npm: "npm install mailparser"
},
// 邮件分类
natural: {
description: "自然语言处理库",
features: ["文本分类", "关键词提取", "情感分析"],
npm: "npm install natural"
},
// 附件处理
pdf_parse: {
description: "PDF解析库",
features: ["PDF文本提取", "元数据读取"],
npm: "npm install pdf-parse"
},
mammoth: {
description: "Word文档解析库",
features: [".docx解析", "HTML转换"],
npm: "npm install mammoth"
}
};
二、基础邮件操作:从零开始
2.1 环境搭建与基础配置
首先,让我们搭建邮件处理开发环境:
// mail-environment-setup.js - 邮件处理环境搭建
const nodemailer = require('nodemailer');
const Imap = require('imap');
const fs = require('fs');
const path = require('path');
class MailEnvironmentSetup {
constructor() {
this.projectRoot = process.cwd();
this.configDir = path.join(this.projectRoot, 'config');
this.templatesDir = path.join(this.projectRoot, 'templates');
this.attachmentsDir = path.join(this.projectRoot, 'attachments');
this.logsDir = path.join(this.projectRoot, 'logs');
this.setupDirectories();
this.loadConfiguration();
}
setupDirectories() {
// 创建必要的目录结构
const directories = [
this.configDir,
this.templatesDir,
this.attachmentsDir,
this.logsDir,
path.join(this.configDir, 'email_accounts'),
path.join(this.templatesDir, 'html'),
path.join(this.templatesDir, 'text'),
path.join(this.attachmentsDir, 'incoming'),
path.join(this.attachmentsDir, 'outgoing'),
path.join(this.logsDir, 'sent'),
path.join(this.logsDir, 'received')
];
directories.forEach(dir => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
console.log(`创建目录: ${dir}`);
}
});
}
loadConfiguration() {
// 加载配置文件
const defaultConfig = {
smtp: {
host: process.env.SMTP_HOST || 'smtp.gmail.com',
port: process.env.SMTP_PORT || 587,
secure: false,
requireTLS: true
},
imap: {
host: process.env.IMAP_HOST || 'imap.gmail.com',
port: process.env.IMAP_PORT || 993,
tls: true
},
limits: {
maxAttachmentSize: 25 * 1024 * 1024, // 25MB
maxEmailsPerBatch: 100,
rateLimitPerHour: 100
}
};
this.config = defaultConfig;
// 尝试加载自定义配置
try {
const customConfig = require(path.join(this.configDir, 'mail-config.json'));
this.config = { ...defaultConfig, ...customConfig };
console.log('自定义配置加载成功');
} catch (error) {
console.log('使用默认配置');
}
}
// 测试邮件服务连接
async testConnections() {
const results = {};
try {
// 测试SMTP连接
const transporter = nodemailer.createTransport({
host: this.config.smtp.host,
port: this.config.smtp.port,
secure: this.config.smtp.secure
});
await transporter.verify();
results.smtp = { success: true, message: 'SMTP连接成功' };
} catch (error) {
results.smtp = { success: false, message: `SMTP连接失败: ${error.message}` };
}
return results;
}
}
2.2 邮件发送功能
让我们从邮件发送开始:
// mail-sending.js - 邮件发送功能
class MailSending {
constructor(config = {}) {
this.config = config;
this.transporter = null;
this.templates = new Map();
this.initTransporter();
this.loadTemplates();
}
initTransporter() {
this.transporter = nodemailer.createTransport({
host: this.config.smtp.host,
port: this.config.smtp.port,
secure: this.config.smtp.secure,
auth: {
user: this.config.smtp.user,
pass: this.config.smtp.pass
}
});
console.log('邮件传输器初始化完成');
}
// 加载邮件模板
loadTemplates() {
const templateFiles = fs.readdirSync(this.config.templatesDir);
templateFiles.forEach(file => {
if (file.endsWith('.html') || file.endsWith('.txt')) {
const templatePath = path.join(this.config.templatesDir, file);
const content = fs.readFileSync(templatePath, 'utf8');
const templateName = path.basename(file, path.extname(file));
this.templates.set(templateName, {
content: content,
type: file.endsWith('.html') ? 'html' : 'text'
});
console.log(`加载模板: ${templateName}`);
}
});
}
// 发送简单邮件
async sendSimpleMail(options) {
try {
const { to, subject, text, html } = options;
const mailOptions = {
from: this.config.smtp.from || this.config.smtp.user,
to: to,
subject: subject,
text: text,
html: html
};
const info = await this.transporter.sendMail(mailOptions);
this.logSentMail({
to: to,
subject: subject,
messageId: info.messageId,
sentAt: new Date()
});
console.log(`邮件发送成功: ${info.messageId}`);
return info;
} catch (error) {
console.error('邮件发送失败:', error);
throw error;
}
}
// 使用模板发送邮件
async sendTemplateMail(templateName, data, options) {
try {
const template = this.templates.get(templateName);
if (!template) {
throw new Error(`模板不存在: ${templateName}`);
}
// 渲染模板
let renderedContent = template.content;
Object.keys(data).forEach(key => {
const placeholder = `{{${key}}}`;
renderedContent = renderedContent.replace(
new RegExp(placeholder, 'g'),
data[key]
);
});
const mailOptions = {
from: options.from || this.config.smtp.from,
to: options.to,
subject: options.subject,
text: template.type === 'text' ? renderedContent : undefined,
html: template.type === 'html' ? renderedContent : undefined
};
if (options.attachments) {
mailOptions.attachments = options.attachments;
}
const info = await this.transporter.sendMail(mailOptions);
this.logSentMail({
to: options.to,
subject: options.subject,
template: templateName,
messageId: info.messageId,
sentAt: new Date()
});
return info;
} catch (error) {
console.error('模板邮件发送失败:', error);
throw error;
}
}
// 批量发送邮件
async sendBulkMail(recipients, options) {
const results = [];
const batchSize = options.batchSize || 10;
for (let i = 0; i < recipients.length; i += batchSize) {
const batch = recipients.slice(i, i + batchSize);
console.log(`发送批次: ${i / batchSize + 1}`);
const batchPromises = batch.map(async (recipient) => {
try {
const mailOptions = {
from: options.from || this.config.smtp.from,
to: recipient.email,
subject: options.subject,
text: options.text,
html: options.html
};
// 个性化内容
if (options.personalize) {
if (mailOptions.text) {
mailOptions.text = this.personalizeContent(mailOptions.text, recipient);
}
if (mailOptions.html) {
mailOptions.html = this.personalizeContent(mailOptions.html, recipient);
}
}
const info = await this.transporter.sendMail(mailOptions);
results.push({
email: recipient.email,
success: true,
messageId: info.messageId
});
console.log(`发送成功: ${recipient.email}`);
} catch (error) {
results.push({
email: recipient.email,
success: false,
error: error.message
});
console.error(`发送失败: ${recipient.email}`, error.message);
}
});
await Promise.all(batchPromises);
// 避免速率限制
if (i + batchSize < recipients.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return {
total: recipients.length,
success: results.filter(r => r.success).length,
failed: results.filter(r => !r.success).length,
results: results
};
}
// 个性化内容
personalizeContent(content, recipient) {
let personalized = content;
// 替换个性化占位符
Object.keys(recipient).forEach(key => {
const placeholder = `{{${key}}}`;
personalized = personalized.replace(
new RegExp(placeholder, 'g'),
recipient[key]
);
});
return personalized;
}
// 记录已发送邮件
logSentMail(info) {
const logEntry = {
timestamp: new Date().toISOString(),
...info
};
const logFile = path.join(this.config.logsDir, 'sent', `${new Date().toISOString().split('T')[0]}.json`);
try {
let logs = [];
if (fs.existsSync(logFile)) {
const content = fs.readFileSync(logFile, 'utf8');
logs = JSON.parse(content);
}
logs.push(logEntry);
fs.writeFileSync(logFile, JSON.stringify(logs, null, 2));
} catch (error) {
console.error('日志记录失败:', error);
}
}
}
2.3 邮件接收与解析
邮件接收是邮件管理的核心功能:
// mail-receiving.js - 邮件接收与解析
class MailReceiving {
constructor(config = {}) {
this.config = config;
this.imap = null;
this.parser = null;
this.initImapConnection();
this.initParser();
}
initImapConnection() {
this.imap = new Imap({
user: this.config.imap.user,
password: this.config.imap.pass,
host: this.config.imap.host,
port: this.config.imap.port,
tls: this.config.imap.tls,
tlsOptions: { rejectUnauthorized: false }
});
this.imap.on('error', (err) => {
console.error('IMAP连接错误:', err);
});
this.imap.on('end', () => {
console.log('IMAP连接结束');
});
}
initParser() {
this.parser = require('mailparser').simpleParser;
}
// 连接IMAP服务器
async connect() {
return new Promise((resolve, reject) => {
this.imap.once('ready', () => {
console.log('IMAP连接成功');
resolve();
});
this.imap.once('error', reject);
this.imap.connect();
});
}
// 断开连接
async disconnect() {
return new Promise((resolve) => {
this.imap.end();
this.imap.once('end', () => {
console.log('IMAP已断开连接');
resolve();
});
});
}
// 获取邮件列表
async fetchEmails(options = {}) {
const {
mailbox = 'INBOX',
limit = 50,
since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // 最近7天
} = options;
return new Promise((resolve, reject) => {
this.imap.openBox(mailbox, false, (err, box) => {
if (err) {
reject(err);
return;
}
const searchCriteria = ['ALL'];
if (since) {
searchCriteria.push(['SINCE', since]);
}
this.imap.search(searchCriteria, (err, results) => {
if (err) {
reject(err);
return;
}
if (results.length === 0) {
resolve([]);
return;
}
// 限制数量
const limitedResults = results.slice(0, limit);
const fetch = this.imap.fetch(limitedResults, {
bodies: '',
markSeen: false,
struct: true
});
const emails = [];
fetch.on('message', (msg, seqno) => {
const email = { seqno, headers: {}, parts: [] };
msg.on('body', (stream, info) => {
let buffer = '';
stream.on('data', (chunk) => {
buffer += chunk.toString('utf8');
});
stream.on('end', async () => {
try {
const parsed = await this.parser(buffer);
email.parsed = parsed;
emails.push(email);
} catch (parseErr) {
console.error('解析邮件失败:', parseErr);
}
});
});
msg.once('attributes', (attrs) => {
email.attributes = attrs;
});
msg.once('end', () => {
// 消息处理完成
});
});
fetch.once('error', reject);
fetch.once('end', () => {
// 按时间排序(最新的在前)
emails.sort((a, b) => {
const dateA = a.parsed ? a.parsed.date : new Date(0);
const dateB = b.parsed ? b.parsed.date : new Date(0);
return dateB - dateA;
});
resolve(emails);
});
});
});
});
}
// 解析邮件内容
async parseEmail(rawEmail) {
try {
const parsed = await this.parser(rawEmail);
// 提取重要信息
const extracted = {
from: {
address: parsed.from?.value[0]?.address,
name: parsed.from?.value[0]?.name
},
to: parsed.to?.value.map(v => ({
address: v.address,
name: v.name
})),
subject: parsed.subject,
date: parsed.date,
text: parsed.text,
html: parsed.html,
attachments: parsed.attachments || []
};
// 提取正文摘要
if (extracted.text) {
extracted.summary = extracted.text.substring(0, 200) + '...';
} else if (extracted.html) {
// 从HTML中提取文本
const textOnly = extracted.html.replace(/<[^>]*>/g, ' ').trim();
extracted.summary = textOnly.substring(0, 200) + '...';
}
// 保存附件
if (extracted.attachments.length > 0) {
extracted.savedAttachments = await this.saveAttachments(extracted.attachments);
}
return extracted;
} catch (error) {
console.error('邮件解析错误:', error);
throw error;
}
}
// 保存附件
async saveAttachments(attachments) {
const saved = [];
for (const attachment of attachments) {
try {
const filename = this.sanitizeFilename(attachment.filename || `attachment_${Date.now()}`);
const filepath = path.join(this.config.attachmentsDir, 'incoming', filename);
fs.writeFileSync(filepath, attachment.content);
saved.push({
originalName: attachment.filename,
savedName: filename,
path: filepath,
contentType: attachment.contentType,
size: attachment.size
});
console.log(`附件已保存: ${filename}`);
} catch (error) {
console.error('保存附件失败:', error);
}
}
return saved;
}
// 清理文件名
sanitizeFilename(filename) {
return filename.replace(/[^a-zA-Z0-9._-]/g, '_');
}
// 监控新邮件
async monitorNewEmails(callback, options = {}) {
const { mailbox = 'INBOX', interval = 30000 } = options;
console.log(`开始监控邮箱: ${mailbox}, 间隔: ${interval}ms`);
let lastCheck = new Date();
const checkInterval = setInterval(async () => {
try {
await this.connect();
const newEmails = await this.fetchEmails({
mailbox: mailbox,
since: lastCheck,
limit: 100
});
if (newEmails.length > 0) {
console.log(`发现 ${newEmails.length} 封新邮件`);
for (const email of newEmails) {
if (email.parsed && email.parsed.date > lastCheck) {
await callback(email.parsed);
}
}
lastCheck = new Date();
}
await this.disconnect();
} catch (error) {
console.error('监控邮件错误:', error);
}
}, interval);
return {
stop: () => {
clearInterval(checkInterval);
console.log('邮件监控已停止');
}
};
}
}
三、高级邮件管理:智能分类与自动回复
3.1 邮件智能分类
智能分类是现代邮件管理的核心功能:
// mail-classification.js - 邮件智能分类
class MailClassification {
constructor() {
this.rules = new Map();
this.keywords = new Map();
this.senders = new Map();
this.loadClassificationRules();
}
loadClassificationRules() {
// 分类规则配置
this.rules.set('important', {
keywords: ['urgent', 'important', 'priority', 'asap', 'deadline'],
senders: ['manager@company.com', 'ceo@company.com'],
subjectPatterns: [/\[IMPORTANT\]/, /\[URGENT\]/]
});
this.rules.set('newsletter', {
keywords: ['newsletter', 'subscribe', 'unsubscribe'],
subjectPatterns: [/newsletter/i, /weekly digest/i]
});
this.rules.set('notification', {
keywords: ['notification', 'alert', 'reminder', 'system'],
senders: ['noreply@', 'notifications@', 'alerts@']
});
this.rules.set('social', {
keywords: ['facebook', 'twitter', 'linkedin', 'instagram'],
subjectPatterns: [/friend request/i, /connection request/i]
});
this.rules.set('promotion', {
keywords: ['sale', 'discount', 'offer', 'coupon', 'deal'],
subjectPatterns: [/sale/i, /discount/i, /limited time/i]
});
console.log('分类规则加载完成');
}
// 分类邮件
classifyEmail(email) {
const scores = {};
// 初始化所有分类分数
for (const category of this.rules.keys()) {
scores[category] = 0;
}
// 分析发件人
this.analyzeSender(email.from.address, scores);
// 分析主题
this.analyzeSubject(email.subject, scores);
// 分析正文
if (email.text) {
this.analyzeContent(email.text, scores);
}
if (email.html) {
const textOnly = email.html.replace(/<[^>]*>/g, ' ');
this.analyzeContent(textOnly, scores);
}
// 确定主分类
let primaryCategory = 'general';
let highestScore = 0;
for (const [category, score] of Object.entries(scores)) {
if (score > highestScore) {
highestScore = score;
primaryCategory = category;
}
}
// 如果分数太低,保持为general
if (highestScore < 2) {
primaryCategory = 'general';
}
// 计算置信度
const confidence = Math.min(highestScore / 10, 1.0);
return {
category: primaryCategory,
confidence: confidence,
scores: scores,
tags: this.generateTags(email, primaryCategory)
};
}
// 分析发件人
analyzeSender(sender, scores) {
if (!sender) return;
for (const [category, rule] of this.rules.entries()) {
if (rule.senders) {
for (const senderPattern of rule.senders) {
if (sender.includes(senderPattern)) {
scores[category] += 3; // 发件人匹配权重高
break;
}
}
}
}
// 根据发件人域名分析
const domain = sender.split('@')[1];
if (domain) {
if (domain.includes('social.')) scores['social'] += 2;
if (domain.includes('news.')) scores['newsletter'] += 2;
if (domain.includes('store.')) scores['promotion'] += 2;
}
}
// 分析主题
analyzeSubject(subject, scores) {
if (!subject) return;
const subjectLower = subject.toLowerCase();
for (const [category, rule] of this.rules.entries()) {
// 关键词匹配
if (rule.keywords) {
for (const keyword of rule.keywords) {
if (subjectLower.includes(keyword.toLowerCase())) {
scores[category] += 2;
}
}
}
// 正则表达式匹配
if (rule.subjectPatterns) {
for (const pattern of rule.subjectPatterns) {
if (pattern.test(subject)) {
scores[category] += 2;
}
}
}
}
}
// 分析内容
analyzeContent(content, scores) {
if (!content) return;
const contentLower = content.toLowerCase();
for (const [category, rule] of this.rules.entries()) {
if (rule.keywords) {
for (const keyword of rule.keywords) {
const regex = new RegExp(`\\b${keyword}\\b`, 'gi');
const matches = (contentLower.match(regex) || []).length;
scores[category] += matches * 0.5; // 每个匹配加0.5分
}
}
}
}
// 生成标签
generateTags(email, primaryCategory) {
const tags = [primaryCategory];
// 根据发件人添加标签
if (email.from.address) {
tags.push(`from:${email.from.address.split('@')[0]}`);
}
// 根据日期添加标签
if (email.date) {
const date = new Date(email.date);
tags.push(`year:${date.getFullYear()}`);
tags.push(`month:${date.getMonth() + 1}`);
tags.push(`week:${Math.ceil(date.getDate() / 7)}`);
}
// 根据附件添加标签
if (email.attachments && email.attachments.length > 0) {
tags.push('has-attachment');
// 根据附件类型添加标签
const attachmentTypes = new Set();
email.attachments.forEach(att => {
if (att.contentType) {
const type = att.contentType.split('/')[0];
attachmentTypes.add(type);
}
});
attachmentTypes.forEach(type => {
tags.push(`attachment:${type}`);
});
}
return tags;
}
// 训练分类器(简单版本)
async trainClassifier(labeledEmails) {
// 这里可以集成机器学习库进行训练
// 目前使用基于规则的简单分类
console.log(`使用 ${labeledEmails.length} 封标注邮件更新分类规则`);
// 分析标注数据,优化规则
for (const labeledEmail of labeledEmails) {
const { email, category } = labeledEmail;
if (!this.rules.has(category)) {
this.rules.set(category, {
keywords: [],
senders: [],
subjectPatterns: []
});
}
const rule = this.rules.get(category);
// 添加发件人到规则
if (email.from && email.from.address) {
const senderDomain = email.from.address.split('@')[1];
if (senderDomain && !rule.senders.includes(senderDomain)) {
rule.senders.push(senderDomain);
}
}
// 从主题中提取关键词
if (email.subject) {
const words = email.subject.toLowerCase().split(/\s+/);
words.forEach(word => {
if (word.length > 3 && !rule.keywords.includes(word)) {
rule.keywords.push(word);
}
});
}
}
console.log('分类规则已更新');
return this.rules;
}
}
3.2 邮件自动回复
自动回复可以大大提高邮件处理效率:
// mail-auto-reply.js - 邮件自动回复
class MailAutoReply {
constructor(config = {}) {
this.config = config;
this.templates = new Map();
this.rules = [];
this.schedule = new Map();
this.loadAutoReplyRules();
this.loadTemplates();
}
loadAutoReplyRules() {
// 自动回复规则
this.rules = [
{
name: 'vacation',
enabled: false,
conditions: {
subjectKeywords: [],
senderDomains: [],
dateRange: null
},
template: 'vacation',
delay: 0 // 立即回复
},
{
name: 'out-of-office',
enabled: false,
conditions: {
subjectKeywords: ['urgent', 'important'],
senderDomains: ['company.com'],
workingHoursOnly: false
},
template: 'out-of-office',
delay: 0
},
{
name: 'faq-response',
enabled: true,
conditions: {
contentKeywords: ['how to', 'question', 'help'],
senderDomains: []
},
template: 'faq',
delay: 300 // 5分钟后回复
},
{
name: 'receipt-confirmation',
enabled: true,
conditions: {
subjectKeywords: ['order', 'purchase', 'invoice'],
senderDomains: []
},
template: 'receipt',
delay: 60 // 1分钟后回复
}
];
}
loadTemplates() {
// 加载自动回复模板
this.templates.set('vacation', {
subject: '自动回复:休假通知',
text: `您好,
我目前正在休假中,预计在{{returnDate}}返回办公室。在此期间,我将无法及时回复您的邮件。
如有紧急事宜,请联系我的同事{{colleagueName}}(邮箱:{{colleagueEmail}})。
感谢您的理解。
此致,
{{myName}}`
});
this.templates.set('out-of-office', {
subject: '自动回复:外出通知',
text: `您好,
我目前外出中,预计{{returnTime}}返回办公室。在此期间,我将无法及时回复您的邮件。
您的邮件我已收到,将在返回后尽快处理。
如有紧急事宜,请致电{{emergencyPhone}}。
感谢您的理解。
此致,
{{myName}}`
});
this.templates.set('faq', {
subject: '自动回复:常见问题解答',
text: `您好,
感谢您的来信。我收到了您关于"{{topic}}"的问题。
关于这个问题,您可以参考以下资源:
1. 常见问题页面:{{faqUrl}}
2. 用户指南:{{guideUrl}}
3. 视频教程:{{videoUrl}}
如果以上资源未能解决您的问题,我将在{{responseTime}}内给您详细回复。
感谢您的耐心等待。
此致,
{{myName}}`
});
this.templates.set('receipt', {
subject: '自动回复:订单确认',
text: `您好,
感谢您的订单(订单号:{{orderId}})。我们已收到您的订单请求,正在处理中。
订单详情:
- 产品:{{productName}}
- 数量:{{quantity}}
- 总价:{{totalPrice}}
您可以在以下链接查看订单状态:{{orderUrl}}
如有任何问题,请随时联系我们。
感谢您的惠顾。
此致,
{{myName}}`
});
}
// 检查是否需要自动回复
shouldAutoReply(email) {
const matchingRules = [];
for (const rule of this.rules) {
if (!rule.enabled) continue;
if (this.checkConditions(rule.conditions, email)) {
matchingRules.push(rule);
}
}
return matchingRules;
}
// 检查条件
checkConditions(conditions, email) {
// 检查发件人域名
if (conditions.senderDomains && conditions.senderDomains.length > 0) {
const senderDomain = email.from.address.split('@')[1];
if (!conditions.senderDomains.includes(senderDomain)) {
return false;
}
}
// 检查主题关键词
if (conditions.subjectKeywords && conditions.subjectKeywords.length > 0) {
const subject = email.subject.toLowerCase();
const hasKeyword = conditions.subjectKeywords.some(keyword =>
subject.includes(keyword.toLowerCase())
);
if (!hasKeyword) {
return false;
}
}
// 检查内容关键词
if (conditions.contentKeywords && conditions.contentKeywords.length > 0) {
const content = (email.text || '').toLowerCase();
const hasKeyword = conditions.contentKeywords.some(keyword =>
content.includes(keyword.toLowerCase())
);
if (!hasKeyword) {
return false;
}
}
// 检查日期范围
if (conditions.dateRange) {
const emailDate = new Date(email.date);
const { start, end } = conditions.dateRange;
if (start && emailDate < new Date(start)) {
return false;
}
if (end && emailDate > new Date(end)) {
return false;
}
}
// 检查工作时间
if (conditions.workingHoursOnly) {
const emailDate = new Date(email.date);
const hour = emailDate.getHours();
// 假设工作时间为9:00-18:00
if (hour < 9 || hour >= 18) {
return false;
}
}
return true;
}
// 生成回复内容
generateReply(rule, email, context = {}) {
const template = this.templates.get(rule.template);
if (!template) {
throw new Error(`模板不存在: ${rule.template}`);
}
// 合并上下文
const replyContext = {
senderName: email.from.name || email.from.address,
senderEmail: email.from.address,
originalSubject: email.subject,
originalDate: email.date,
currentDate: new Date().toISOString().split('T')[0],
...context
};
// 渲染模板
let subject = template.subject;
let text = template.text;
Object.keys(replyContext).forEach(key => {
const placeholder = `{{${key}}}`;
subject = subject.replace(new RegExp(placeholder, 'g'), replyContext[key] || '');
text = text.replace(new RegExp(placeholder, 'g'), replyContext[key] || '');
});
return {
to: email.from.address,
subject: subject,
text: text,
inReplyTo: email.messageId,
references: email.references || email.messageId
};
}
// 安排回复
scheduleReply(rule, email, replyContent) {
const delay = rule.delay || 0; // 秒
if (delay === 0) {
// 立即发送
return this.sendReply(replyContent);
} else {
// 延迟发送
const scheduleTime = Date.now() + delay * 1000;
const scheduleId = `reply_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.schedule.set(scheduleId, {
rule: rule.name,
email: email,
reply: replyContent,
scheduledFor: new Date(scheduleTime)
});
setTimeout(() => {
this.sendReply(replyContent);
this.schedule.delete(scheduleId);
}, delay * 1000);
console.log(`回复已安排,将在 ${delay} 秒后发送`);
return scheduleId;
}
}
// 发送回复
async sendReply(replyContent) {
// 这里需要集成邮件发送功能
console.log('发送自动回复:', replyContent);
// 实际实现中应该调用邮件发送器
// await mailSender.sendSimpleMail(replyContent);
return true;
}
// 处理新邮件
async processNewEmail(email, context = {}) {
try {
const matchingRules = this.shouldAutoReply(email);
if (matchingRules.length === 0) {
return { autoReplied: false };
}
// 使用第一个匹配的规则
const rule = matchingRules[0];
const replyContent = this.generateReply(rule, email, context);
const result = await this.scheduleReply(rule, email, replyContent);
return {
autoReplied: true,
rule: rule.name,
template: rule.template,
scheduled: typeof result === 'string',
scheduleId: typeof result === 'string' ? result : null
};
} catch (error) {
console.error('自动回复处理失败:', error);
return { autoReplied: false, error: error.message };
}
}
// 获取安排状态
getScheduleStatus() {
const now = new Date();
const upcoming = [];
const pastDue = [];
for (const [id, schedule] of this.schedule.entries()) {
if (schedule.scheduledFor < now) {
pastDue.push({ id, ...schedule });
} else {
upcoming.push({ id, ...schedule });
}
}
return {
total: this.schedule.size,
upcoming: upcoming,
pastDue: pastDue.length,
upcomingCount: upcoming.length
};
}
}
四、邮件管理Skill的完整实现
4.1 Skill架构设计
现在,让我们构建一个完整的邮件管理Skill:
// mail-skill-architecture.js - 邮件管理Skill架构设计
class MailSkillArchitecture {
constructor() {
this.name = 'mail-management-skill';
this.version = '1.0.0';
this.components = {
sender: null,
receiver: null,
classifier: null,
autoReplier: null,
organizer: null
};
this.initComponents();
this.loadConfig();
this.setupEventHandlers();
}
initComponents() {
const config = this.loadMailConfig();
this.components.sender = new MailSending(config);
this.components.receiver = new MailReceiving(config);
this.components.classifier = new MailClassification();
this.components.autoReplier = new MailAutoReply(config);
this.components.organizer = new MailOrganizer(config);
console.log('邮件管理Skill组件初始化完成');
}
loadConfig() {
this.config = {
mailboxes: {
inbox: 'INBOX',
sent: 'Sent',
drafts: 'Drafts',
trash: 'Trash',
archive: 'Archive'
},
processing: {
checkInterval: 30000, // 30秒
batchSize: 50,
maxRetries: 3
},
security: {
encryption: true,
attachmentScanning: true,
spamFiltering: true
}
};
}
setupEventHandlers() {
// 新邮件到达事件
this.components.receiver.on('new-mail', async (email) => {
console.log(`收到新邮件: ${email.subject}`);
// 分类邮件
const classification = await this.components.classifier.classifyEmail(email);
// 自动回复检查
const autoReplyResult = await this.components.autoReplier.processNewEmail(email, {
classification: classification.category
});
// 邮件组织
await this.components.organizer.organizeEmail(email, classification);
// 触发自定义处理
this.emit('mail-processed', {
email: email,
classification: classification,
autoReply: autoReplyResult
});
});
// 邮件发送成功事件
this.components.sender.on('mail-sent', (info) => {
console.log(`邮件发送成功: ${info.messageId}`);
// 记录到日志
this.logActivity('mail-sent', info);
this.emit('mail-sent', info);
});
}
// 处理邮件请求
async processRequest(requestType, params) {
try {
this.validateRequest(requestType, params);
const requestId = this.generateRequestId();
this.logRequest(requestType, params, requestId);
let result;
switch (requestType) {
case 'send-mail':
result = await this.components.sender.sendSimpleMail(params);
break;
case 'send-template':
result = await this.components.sender.sendTemplateMail(
params.template,
params.data,
params.options
);
break;
case 'check-mail':
result = await this.components.receiver.fetchEmails(params.options);
break;
case 'classify-mail':
result = await this.components.classifier.classifyEmail(params.email);
break;
case 'setup-auto-reply':
result = await this.components.autoReplier.setupAutoReply(params.rule);
break;
case 'organize-mailbox':
result = await this.components.organizer.organizeMailbox(params.mailbox, params.rules);
break;
default:
throw new Error(`不支持的操作类型: ${requestType}`);
}
this.logSuccess(requestType, params, result, requestId);
return {
success: true,
requestId: requestId,
result: result,
processedAt: new Date()
};
} catch (error) {
this.logError(requestType, params, error);
return {
success: false,
error: error.message,
requestId: this.generateRequestId(),
suggestions: this.getErrorSuggestions(error)
};
}
}
// 启动邮件监控
async startMonitoring(options = {}) {
console.log('启动邮件监控');
const monitor = await this.components.receiver.monitorNewEmails(
async (email) => {
// 处理新邮件
await this.processRequest('classify-mail', { email });
// 检查是否需要自动回复
const classification = await this.components.classifier.classifyEmail(email);
await this.components.autoReplier.processNewEmail(email, {
classification: classification.category
});
},
options
);
this.activeMonitor = monitor;
return monitor;
}
// 停止邮件监控
stopMonitoring() {
if (this.activeMonitor) {
this.activeMonitor.stop();
this.activeMonitor = null;
console.log('邮件监控已停止');
}
}
// 批量处理邮件
async batchProcessMail(operation, options = {}) {
const { mailbox = 'INBOX', limit = 100 } = options;
console.log(`批量处理邮件: ${operation}, 邮箱: ${mailbox}`);
// 获取邮件列表
const emails = await this.components.receiver.fetchEmails({
mailbox: mailbox,
limit: limit
});
const results = [];
for (const email of emails) {
try {
let result;
switch (operation) {
case 'classify':
result = await this.components.classifier.classifyEmail(email.parsed);
break;
case 'archive':
result = await this.components.organizer.moveToArchive(email);
break;
case 'cleanup':
result = await this.components.organizer.cleanupOldEmails(email);
break;
default:
throw new Error(`不支持的批量操作: ${operation}`);
}
results.push({
emailId: email.attributes?.uid,
success: true,
result: result
});
console.log(`处理成功: ${email.parsed?.subject}`);
} catch (error) {
results.push({
emailId: email.attributes?.uid,
success: false,
error: error.message
});
console.error(`处理失败: ${email.parsed?.subject}`, error.message);
}
}
return {
operation: operation,
total: emails.length,
success: results.filter(r => r.success).length,
failed: results.filter(r => !r.success).length,
results: results
};
}
// 生成报告
async generateReport(options = {}) {
const { period = 'week', metrics = ['volume', 'response_time', 'categories'] } = options;
console.log(`生成邮件报告: ${period}`);
const report = {
period: period,
generatedAt: new Date(),
metrics: {}
};
// 获取邮件数据
const emails = await this.components.receiver.fetchEmails({
since: this.getDateForPeriod(period)
});
// 计算指标
if (metrics.includes('volume')) {
report.metrics.volume = this.calculateVolumeMetrics(emails);
}
if (metrics.includes('response_time')) {
report.metrics.responseTime = await this.calculateResponseTimeMetrics(emails);
}
if (metrics.includes('categories')) {
report.metrics.categories = await this.calculateCategoryMetrics(emails);
}
// 生成见解
report.insights = this.generateInsights(report.metrics);
// 生成建议
report.recommendations = this.generateRecommendations(report);
return report;
}
// 计算邮件量指标
calculateVolumeMetrics(emails) {
const now = new Date();
const oneDayAgo = new Date(now - 24 * 60 * 60 * 1000);
const oneWeekAgo = new Date(now - 7 * 24 * 60 * 60 * 1000);
const total = emails.length;
const today = emails.filter(e => new Date(e.parsed.date) > oneDayAgo).length;
const thisWeek = emails.filter(e => new Date(e.parsed.date) > oneWeekAgo).length;
return {
total: total,
today: today,
thisWeek: thisWeek,
averagePerDay: thisWeek / 7,
trend: this.calculateTrend(emails)
};
}
// 计算响应时间指标
async calculateResponseTimeMetrics(emails) {
// 这里需要实现响应时间计算逻辑
// 实际项目中需要记录发送和回复的时间戳
return {
averageResponseTime: '2小时',
quickestResponse: '15分钟',
slowestResponse: '48小时',
responseRate: '85%'
};
}
// 计算分类指标
async calculateCategoryMetrics(emails) {
const categories = {};
for (const email of emails) {
if (email.parsed) {
const classification = await this.components.classifier.classifyEmail(email.parsed);
const category = classification.category;
categories[category] = (categories[category] || 0) + 1;
}
}
return categories;
}
// 生成见解
generateInsights(metrics) {
const insights = [];
if (metrics.volume) {
if (metrics.volume.today > 50) {
insights.push('今日邮件量较大,建议设置更严格的过滤规则');
}
if (metrics.volume.averagePerDay > 30) {
insights.push('平均每日邮件量较高,考虑使用更多自动化工具');
}
}
if (metrics.categories) {
const topCategory = Object.entries(metrics.categories)
.sort((a, b) => b[1] - a[1])[0];
if (topCategory) {
insights.push(`主要邮件类型为"${topCategory[0]}",占总量的${Math.round(topCategory[1] / Object.values(metrics.categories).reduce((a, b) => a + b, 0) * 100)}%`);
}
}
return insights;
}
// 生成建议
generateRecommendations(report) {
const recommendations = [];
// 基于邮件量的建议
if (report.metrics.volume?.averagePerDay > 20) {
recommendations.push('考虑设置更多的自动回复规则以减少手动处理');
recommendations.push('使用邮件模板提高回复效率');
}
// 基于分类的建议
if (report.metrics.categories) {
if (report.metrics.categories.newsletter > 10) {
recommendations.push('发现较多新闻简报邮件,建议设置自动归档');
}
if (report.metrics.categories.promotion > 5) {
recommendations.push('发现较多促销邮件,建议设置自动过滤');
}
}
return recommendations;
}
// 辅助方法
getDateForPeriod(period) {
const now = new Date();
switch (period) {
case 'day':
return new Date(now - 24 * 60 * 60 * 1000);
case 'week':
return new Date(now - 7 * 24 * 60 * 60 * 1000);
case 'month':
return new Date(now - 30 * 24 * 60 * 60 * 1000);
case 'year':
return new Date(now - 365 * 24 * 60 * 60 * 1000);
default:
return new Date(now - 7 * 24 * 60 * 60 * 1000);
}
}
calculateTrend(emails) {
// 计算趋势(简化版)
if (emails.length < 2) return 'stable';
const sorted = emails.sort((a, b) => new Date(a.parsed.date) - new Date(b.parsed.date));
const firstHalf = sorted.slice(0, Math.floor(sorted.length / 2)).length;
const secondHalf = sorted.slice(Math.floor(sorted.length / 2)).length;
if (secondHalf > firstHalf * 1.2) return 'increasing';
if (secondHalf < firstHalf * 0.8) return 'decreasing';
return 'stable';
}
}
4.2 Skill配置文件
让我们创建邮件管理Skill的配置文件:
// SKILL.md - 邮件管理Skill配置文件
const MAIL_SKILL_CONFIG = {
skill: {
name: "mail-management-skill",
version: "2.0.0",
description: "邮件自动化管理与智能分类Skill",
author: "AI助手团队",
homepage: "https://github.com/ai-assistant/mail-skill"
},
capabilities: [
{
name: "send_mail",
description: "发送邮件",
parameters: {
to: { type: "string", required: true },
subject: { type: "string", required: true },
text: { type: "string" },
html: { type: "string" }
}
},
{
name: "check_mail",
description: "检查邮件",
parameters: {
mailbox: { type: "string", default: "INBOX" },
limit: { type: "number", default: 50 }
}
},
{
name: "classify_mail",
description: "智能分类邮件",
parameters: {
email: { type: "object", required: true }
}
}
],
config: {
defaultMailbox: "INBOX",
checkInterval: 30000,
autoReplyEnabled: true,
classificationEnabled: true
}
};
五、典型应用场景
5.1 企业邮件自动化
// enterprise-mail-automation.js - 企业邮件自动化
class EnterpriseMailAutomation {
constructor() {
this.mailSkill = new MailSkillArchitecture();
this.setupEnterpriseRules();
}
setupEnterpriseRules() {
// 企业级自动回复规则
this.mailSkill.components.autoReplier.rules.push({
name: 'customer-support',
enabled: true,
conditions: {
senderDomains: [],
subjectKeywords: ['support', 'help', 'issue', 'problem']
},
template: 'customer-support',
delay: 60
});
this.mailSkill.components.autoReplier.rules.push({
name: 'sales-inquiry',
enabled: true,
conditions: {
subjectKeywords: ['quote', 'pricing', 'sales', 'inquiry']
},
template: 'sales-response',
delay: 300
});
// 加载企业模板
this.mailSkill.components.autoReplier.templates.set('customer-support', {
subject: '自动回复:客户支持请求已收到',
text: `尊敬的客户,
感谢您联系我们的客户支持团队。我们已收到您的问题,并分配了工单号:{{ticketId}}。
我们的支持工程师将在24小时内回复您。您可以通过以下链接查看工单状态:{{ticketUrl}}
如果问题紧急,请致电我们的紧急支持热线:{{supportPhone}}。
感谢您的耐心等待。
此致,
{{companyName}} 客户支持团队`
});
this.mailSkill.components.autoReplier.templates.set('sales-response', {
subject: '自动回复:销售咨询已收到',
text: `尊敬的客户,
感谢您对我们产品的兴趣。我们已收到您的询价请求。
我们的销售代表将在2个工作小时内与您联系,为您提供详细的报价和产品信息。
在等待期间,您可以访问我们的产品页面了解更多信息:{{productUrl}}
如有任何问题,请随时回复此邮件。
此致,
{{companyName}} 销售团队`
});
}
// 处理客户邮件
async processCustomerMail(email) {
console.log(`处理客户邮件: ${email.subject}`);
// 分类邮件
const classification = await this.mailSkill.components.classifier.classifyEmail(email);
// 根据分类处理
let result;
if (classification.category === 'support') {
result = await this.handleSupportRequest(email);
} else if (classification.category === 'sales') {
result = await this.handleSalesInquiry(email);
} else {
result = await this.handleGeneralInquiry(email);
}
// 记录处理结果
this.logCustomerInteraction(email, classification, result);
return result;
}
async handleSupportRequest(email) {
// 生成工单号
const ticketId = `TICKET-${Date.now()}-${Math.random().toString(36).substr(2, 6).toUpperCase()}`;
// 发送自动回复
const replyResult = await this.mailSkill.components.autoReplier.processNewEmail(email, {
ticketId: ticketId,
ticketUrl: `https://support.company.com/tickets/${ticketId}`,
supportPhone: '400-123-4567',
companyName: 'ABC科技有限公司'
});
// 创建工单记录
await this.createSupportTicket(email, ticketId);
return {
type: 'support',
ticketId: ticketId,
autoReplySent: replyResult.autoReplied
};
}
}
5.2 个人邮件智能管理
// personal-mail-management.js - 个人邮件智能管理
class PersonalMailManagement {
constructor() {
this.mailSkill = new MailSkillArchitecture();
this.setupPersonalRules();
this.startPersonalMonitoring();
}
setupPersonalRules() {
// 个人邮件分类规则
this.mailSkill.components.classifier.rules.set('personal', {
keywords: ['family', 'friend', 'personal', 'dinner', 'meetup'],
senders: ['gmail.com', 'qq.com', '163.com'],
subjectPatterns: []
});
this.mailSkill.components.classifier.rules.set('work', {
keywords: ['meeting', 'report', 'deadline', 'project', 'team'],
senders: ['company.com', 'work.com'],
subjectPatterns: [/\[工作\]/, /\[项目\]/]
});
// 个人自动回复规则
this.mailSkill.components.autoReplier.rules.push({
name: 'personal-vacation',
enabled: false,
conditions: {
dateRange: {
start: '2024-12-20',
end: '2024-12-27'
}
},
template: 'personal-vacation',
delay: 0
});
}
startPersonalMonitoring() {
this.mailSkill.startMonitoring({
interval: 60000, // 1分钟检查一次
mailbox: 'INBOX'
});
}
// 智能邮件整理
async organizePersonalMail() {
console.log('开始整理个人邮件');
// 获取所有邮件
const emails = await this.mailSkill.components.receiver.fetchEmails({
limit: 500
});
// 分类整理
for (const email of emails) {
if (email.parsed) {
const classification = await this.mailSkill.components.classifier.classifyEmail(email.parsed);
// 根据分类移动到相应文件夹
await this.moveToFolder(email, classification.category);
// 标记重要邮件
if (classification.confidence > 0.8 && classification.category === 'important') {
await this.markAsImportant(email);
}
}
}
console.log('个人邮件整理完成');
}
}
六、总结与展望
邮件管理Skill的自动化与智能化是现代工作环境的重要工具,它能够:
- 大幅提升效率:自动化处理邮件,节省每天2-3小时的邮件处理时间
- 保证邮件有序:智能分类让重要邮件不再被埋没
- 提高响应速度:自动回复确保及时响应客户和同事
- 实现智能分析:邮件数据洞察帮助优化工作流程
- 支持多场景应用:从个人邮箱管理到企业级邮件系统
通过本文的学习,你已经掌握了构建完整邮件管理Skill所需的所有关键技术。从邮件协议基础到智能分类算法,从自动回复系统到批量处理,你已经具备了开发专业级邮件管理解决方案的能力。
随着AI技术的不断发展,未来的邮件管理Skill将会更加智能化,能够理解邮件内容的深层含义,预测用户需求,提供更加个性化的邮件管理服务。现在就开始构建你的邮件管理Skill,让邮件处理变得更加高效和智能!
上一篇 [第26篇] 图像处理Skill:图片编辑与AI绘图
下一篇 未完待续
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)