/** * 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} - 验证码 */ 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} */ 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;