const logger = require('./logger'); const BANNED_DOMAINS = new Set(); const DOMAIN_REQUEST_COUNTS = new Map(); const RATE_LIMIT = 10; // 每分钟10封邮件 const TIME_WINDOW = 60 * 1000; // 1分钟 const BAN_DURATION = 5 * 60 * 1000; // 5分钟 function getDomainFromEmail(sender) { if (!sender) { return null; } let emailAddress = sender; // 检查 "Name " 格式 const match = sender.match(/<([^>]+)>/); if (match && match[1]) { emailAddress = match[1]; // 提取 'email@domain.com' } // 现在,从(可能已清理的)电子邮件地址中提取域名 if (!emailAddress.includes('@')) { return null; } return emailAddress.split('@')[1]; } function isRateLimited(sender) { const domain = getDomainFromEmail(sender); if (!domain) { // 如果无法从发件人中提取域名,则不进行速率限制 return false; } if (BANNED_DOMAINS.has(domain)) { logger.warn(`Domain ${domain} is currently banned, rejecting email.`, { domain, action: 'reject-banned-domain' }); return true; } const now = Date.now(); const requests = DOMAIN_REQUEST_COUNTS.get(domain) || []; // 过滤掉时间窗口之外的旧请求 const recentRequests = requests.filter(timestamp => now - timestamp < TIME_WINDOW); if (recentRequests.length >= RATE_LIMIT) { logger.warn(`Domain ${domain} has exceeded the rate limit. Banning for ${BAN_DURATION / 1000} seconds.`, { domain, action: 'ban-domain' }); BANNED_DOMAINS.add(domain); // 设置解封计时器 setTimeout(() => { BANNED_DOMAINS.delete(domain); logger.info(`Domain ${domain} has been unbanned.`, { domain, action: 'unban-domain' }); }, BAN_DURATION); // 清空该域名的请求记录 DOMAIN_REQUEST_COUNTS.delete(domain); return true; } // 记录当前请求时间 recentRequests.push(now); DOMAIN_REQUEST_COUNTS.set(domain, recentRequests); return false; } module.exports = { isRateLimited };