邮件发送服务被滥用怎么限制每日发送量
摘要:# 邮件发送服务,怎么才能不被“薅羊毛”? 前两天跟一个做SaaS的朋友吃饭,他愁眉苦脸地跟我吐槽:“我们那个邮件发送服务,差点被薅秃了。” 怎么回事呢?他们平台有个API,用户注册后能免费发一定量的邮件。结果不知道被谁盯上了,写了个脚本,批量注册了上…
邮件发送服务,怎么才能不被“薅羊毛”?
前两天跟一个做SaaS的朋友吃饭,他愁眉苦脸地跟我吐槽:“我们那个邮件发送服务,差点被薅秃了。”
怎么回事呢?他们平台有个API,用户注册后能免费发一定量的邮件。结果不知道被谁盯上了,写了个脚本,批量注册了上万个账号,每个账号都卡着免费额度发营销邮件。好家伙,一夜之间,他们服务器被当成“公共厕所”了,不仅自家正常用户发不出去,还差点被ISP(互联网服务提供商)拉进黑名单,说他们IP在发垃圾邮件。
这种事儿,说实话,在圈里真不新鲜。我自己看过不少创业公司,技术底子不错,业务逻辑也清晰,偏偏在“防滥用”这种看似基础的问题上栽跟头。很多方案,PPT上写得天花乱坠,真到被“打”的时候,才发现全是漏洞。
所以,今天咱们不聊那些高大上的安全架构,就聊聊一个最实际、也最头疼的问题:你的邮件发送服务,怎么才能有效限制每日发送量,不被恶意用户当“肉鸡”使?
一、为什么“每日限额”这么难搞?
你可能觉得,这不简单吗?在数据库里给每个用户加个daily_quota字段,发一封就减一,到零就拒绝,不就完了?
——如果你真这么想,那离被“打爆”就不远了。
这种最基础的计数方式,漏洞多得跟筛子一样。我给你举几个最常见的“薅羊毛”手法:
- 批量注册:就像我朋友遇到的情况,攻击者用程序自动注册海量账号,每个账号都用满免费额度。你限制单个账号有什么用?人家玩的是“蚁群战术”。
- 接口绕过:你的限制逻辑是放在Web API层吧?那好,攻击者直接去模拟调用你后端的队列处理Worker,或者找到你内部没做限制的管理接口。这种事儿我见过不止一次,问题往往不是没上防护,而是防护没做对地方。
- 时间窗口攻击:你的“每日”是以UTC零点重置,还是用户本地时间?如果是固定时间重置,攻击者可以在重置时间点前后疯狂发送,瞬间挤爆你的队列。
- “慢速”攻击:我不一下子发完,我每小时发几封,细水长流,让你的监控系统看起来“一切正常”,但实际上你的资源被长期、低强度地白白占用。
说白了,限制每日发送量,绝不仅仅是一个“计数”问题。它是一个涉及账户体系、API安全、资源调度和实时风控的综合防御工程。
二、从“单点防御”到“纵深防御”:三层防护网
别指望一个方案能解决所有问题。你得像剥洋葱一样,一层一层地设防。
第一层:账户与认证层 —— 把“坏用户”挡在门外
这层的目标是提高作恶成本,让批量注册和自动化攻击变得困难。
- 告别“邮箱即一切”:别只用邮箱验证了。加上手机短信验证码(注意防短信接码平台),或者引入像Google reCAPTCHA v3这样的行为验证。虽然用户体验上多了半步,但能过滤掉90%的脚本小子。
- 给新账号“上枷锁”:新注册的用户,头24小时只能发10封邮件。想提升额度?完成邮箱二次验证,或者上传更详细的资料(对企业用户)。这叫“冷启动限制”,很多大厂都在用。
- 设备与IP指纹:记录用户注册和登录时的设备信息、IP地址。如果同一个IP在短时间内注册了超过3个账号,直接触发人工审核或直接禁止。这招对付“蚁群战术”特别有效。
(私货:我知道有人会说这影响用户体验。但说真的,一个正经的业务用户,不会介意多花30秒完成验证;而介意这个的,多半就是想来白嫖或者搞破坏的。这个取舍你得做。)
第二层:API与业务逻辑层 —— 核心的“限流阀”
这是最关键的一层,你的计数和限流逻辑主要在这里发生。
- 限流位置要“深”:别只在最外层的API网关做限制。必须在最终处理邮件发送的那个服务、那个函数里,做最后一次额度校验。 这叫“最终一致性校验”,能防止任何绕过前端的攻击。
- 用对“令牌桶”:别自己用数据库写计数了,性能差还容易出并发问题。直接用Redis的
INCR和EXPIRE命令来实现令牌桶算法。比如,给用户分配一个键user:123:daily_quota,设置24小时过期。每次发送前INCR一下,如果超过限额就拒绝。Redis单线程原子操作,又快又准。 - 多维度配额桶:一个用户,不应该只有一个“每日限额”。你应该有:
- 秒级/分钟级桶:防止突发流量打垮服务。比如,每分钟最多发60封。
- 小时级桶:防止短时间内的密集滥用。
- 日级桶:我们最终要限制的总量。
- 终身免费桶:如果你有免费额度,这是另一个需要独立管理的桶。 这些桶相互独立,任何一个触顶都停止发送。这就解决了“细水长流”和“瞬间爆发”两种攻击模式。
- “硬限制”与“软限制”结合:对于付费用户,额度用完后可以进入“软限制”状态——发送速度变慢,或者进入低优先级队列,并立即通知用户续费。对于免费用户或疑似恶意用户,直接“硬限制”,返回明确错误。
第三层:监控与响应层 —— 你的“火眼金睛”
没有监控的防护,就是瞎子打仗。
- 建立发送行为基线:你的正常用户,一般什么时候发?发多少?发给谁?先搞清楚这个“正常”的样子。
- 设置异常告警规则:比如:
- 单个账号发送频率在5分钟内飙升1000%。
- 新注册账号在1小时内就用完所有额度。
- 大量邮件被主流邮件服务商(如Gmail, Outlook)弹回或标记为垃圾邮件。
- 来自同一个IP段或ASN(自治系统号)的发送请求激增。 一旦触发,立即告警到你的手机。
- 准备“熔断”开关:当监控系统发现某个IP或某个用户池出现明显异常,并且已经影响到系统稳定时,要有能一键“拉闸”的能力。先阻断可疑流量,保住大多数正常用户,然后再慢慢排查。
- 定期审计与调整:每周看看告警日志,分析攻击模式。你会发现,黑产的手法也在“迭代”。你今天防住了批量注册,明天他们可能就开始盗用老账号了。你的规则也得跟着变。
三、几个“小众但实用”的狠招
除了上面这些常规操作,再分享几个我觉着挺管用的“野路子”:
- 对“发送成功率”设限:这是对付垃圾邮件发送者的神器。如果他发的邮件,有超过30%都被目标邮件服务器直接拒收或进入垃圾箱,那就自动大幅降低他的发送额度,甚至暂停。因为正常业务邮件的到达率通常很高。
- 引入“人工质询”:对于触发高风险规则但又不确定的请求,不直接拒绝,而是返回一个需要人工参与的质询。比如,“请点击图中所有的自行车”这种验证码。把机器流量逼到需要人力成本,他们自然就撤了。
- 影子配额:给每个用户设置两个配额:一个明面的,一个暗地的“影子配额”。当明面配额用完后,如果请求还在持续,可以继续消耗“影子配额”,但同时触发最高级别的告警。这能帮你区分是“正常超量”还是“恶意攻击”。
最后,说点大实话
限制每日发送量,本质上是一场成本博弈。攻击者的目的是用最低的成本(他的时间、IP资源)换取你最高的资源消耗(服务器、IP信誉、带宽)。
你的所有策略,都要围绕抬高他的成本来设计。让他觉得,薅你的羊毛,不如去别家看看。
也别追求100%的防护,那不存在。你的目标是:让正常用户顺畅无感,让恶意攻击者觉得“不划算”。
如果你的邮件服务现在还在裸奔,或者只做了一个简单的计数,看完这篇文章,你心里应该有点谱了。赶紧去检查一下你的代码和配置吧。
真等被打的时候再补救,那代价可就大了。

