auto-account-machine/src/tools/account-register/email-verification/index.js
dengqichen 969f9cdb5d aaaaa
2025-11-16 21:27:33 +08:00

203 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Email Verification Service
* 邮箱验证码服务 - 统一入口
*/
const ImapConnector = require('./connectors/imap-connector');
const WindsurfParser = require('./parsers/windsurf-parser');
const emailConfig = require('./email-config');
const logger = require('../../../shared/logger');
class EmailVerificationService {
constructor(config = null) {
this.config = config || emailConfig.primary;
this.connector = null;
this.parsers = [
new WindsurfParser()
// 未来添加更多解析器
// new GitHubParser(),
// new TwitterParser(),
];
}
/**
* 获取验证码
* @param {string} siteName - 网站名称(如 'windsurf'
* @param {string} recipientEmail - 接收验证码的邮箱地址
* @param {number} timeout - 超时时间(秒)
* @returns {Promise<string>} - 验证码
*/
async getVerificationCode(siteName, recipientEmail, timeout = 60) {
logger.info('EmailVerification', `开始获取 ${siteName} 的验证码...`);
logger.info('EmailVerification', `接收邮箱: ${recipientEmail}`);
try {
// 1. 初始化连接器
this.connector = new ImapConnector(this.config);
// 2. 等待验证码邮件
const startTime = Date.now();
const checkInterval = emailConfig.search.checkInterval * 1000; // 转换为毫秒
let attempts = 0;
while (Date.now() - startTime < timeout * 1000) {
attempts++;
logger.info('EmailVerification', `${attempts} 次检查邮件...`);
// 关键每次都重新连接以获取最新邮件QQ邮箱IMAP有延迟问题
if (attempts > 1) {
logger.info('EmailVerification', '断开并重新连接以刷新邮件...');
this.connector.disconnect();
await this.sleep(1000);
}
await this.connector.connect();
// 获取最新邮件(倒序排列)
const emails = await this.connector.getLatestEmails(20, 1);
if (emails && emails.length > 0) {
logger.info('EmailVerification', `找到 ${emails.length} 封邮件`);
// 打印最近5条邮件信息倒序最新的在前
const recentEmails = emails.slice(-5).reverse();
logger.info('EmailVerification', '='.repeat(60));
logger.info('EmailVerification', '最近5条邮件');
recentEmails.forEach((email, index) => {
const dateStr = email.date ? new Date(email.date).toLocaleString('zh-CN') : 'N/A';
logger.info('EmailVerification', ` ${index + 1}. 时间: ${dateStr}`);
logger.info('EmailVerification', ` 发件人: ${email.from}`);
logger.info('EmailVerification', ` 主题: ${email.subject}`);
logger.info('EmailVerification', ` 收件人: ${email.to}`);
});
logger.info('EmailVerification', '='.repeat(60));
// 3. 查找匹配的邮件并提取验证码(从最新的开始)
for (const email of emails.reverse()) {
logger.info('EmailVerification', `检查邮件: 发件人="${email.from}", 主题="${email.subject}", 收件人="${email.to}"`);
// 关键:检查收件人是否匹配
const emailTo = (email.to || '').toLowerCase();
const isForRecipient = emailTo.includes(recipientEmail.toLowerCase());
if (!isForRecipient) {
logger.info('EmailVerification', ` ✗ 跳过:收件人不匹配(需要:${recipientEmail}`);
continue;
}
logger.info('EmailVerification', ` ✓ 收件人匹配!`);
for (const parser of this.parsers) {
if (parser.canParse(email)) {
logger.success('EmailVerification', ` ✓ 找到匹配的邮件: ${email.subject}`);
const code = parser.extractCode(email);
if (code) {
logger.success('EmailVerification', ` ✓ 成功提取验证码: ${code}`);
// 标记为已读
try {
await this.connector.markAsRead(email.uid);
} catch (e) {
// 忽略标记失败
}
// 断开连接
this.connector.disconnect();
return code;
} else {
logger.warn('EmailVerification', ` 邮件匹配但无法提取验证码`);
}
}
}
}
logger.warn('EmailVerification', `未找到匹配的Windsurf验证码邮件`);
} else {
logger.info('EmailVerification', `没有邮件`);
}
// 等待一段时间后再检查
logger.info('EmailVerification', `等待 ${emailConfig.search.checkInterval} 秒后重试...`);
await this.sleep(checkInterval);
}
// 超时
this.connector.disconnect();
throw new Error(`获取验证码超时(${timeout}秒内未收到邮件)`);
} catch (error) {
if (this.connector) {
this.connector.disconnect();
}
throw error;
}
}
/**
* 搜索特定主题的邮件并提取验证码
* @param {string} subject - 邮件主题关键词
* @param {number} timeout - 超时时间(秒)
* @returns {Promise<string>}
*/
async getCodeBySubject(subject, timeout = 60) {
logger.info('EmailVerification', `搜索主题包含 "${subject}" 的邮件...`);
try {
this.connector = new ImapConnector(this.config);
await this.connector.connect();
const startTime = Date.now();
const checkInterval = emailConfig.search.checkInterval * 1000;
while (Date.now() - startTime < timeout * 1000) {
const emails = await this.connector.searchBySubject(subject, 1);
if (emails && emails.length > 0) {
for (const email of emails.reverse()) {
for (const parser of this.parsers) {
if (parser.canParse(email)) {
const code = parser.extractCode(email);
if (code) {
logger.success('EmailVerification', `提取到验证码: ${code}`);
this.connector.disconnect();
return code;
}
}
}
}
}
await this.sleep(checkInterval);
}
this.connector.disconnect();
throw new Error(`获取验证码超时`);
} catch (error) {
if (this.connector) {
this.connector.disconnect();
}
throw error;
}
}
/**
* 添加新的解析器
* @param {BaseParser} parser - 解析器实例
*/
addParser(parser) {
this.parsers.push(parser);
}
/**
* 休眠
* @param {number} ms - 毫秒
*/
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
module.exports = EmailVerificationService;