表单

静态站没数据库,
询盘存在哪、会不会丢?

客户最容易问的一句:「没有后台,表单填了去哪了?」这篇把链路拆开:边缘函数接收、校验、限流、转发邮件网关、失败兜底,每一段都可能丢单,逐段说怎么堵。

文 / RESPEC Team 2025-05-20 表单 / 询盘

「没有后台,客户填了表单去哪了?」这是静态站被问得最多的一句,也是最该被正面回答的一句。答案是:直接进你邮箱,中间不落库。但这条链路上有六个环节,每一段都可能丢单,这篇逐段说清怎么堵。

一张表单要走完的六段

环节做什么这一段的失败长什么样
1 接收边缘函数接住 POST 请求直接 404 或 405,表单点了没反应
2 校验必填项、邮箱格式、长度上限垃圾内容进了邮箱,或者真人被判成无效
3 限流防刷同 IP 频率、人机验证被刷爆,正常询盘混在几百封垃圾里
4 转发调邮件服务 API 发出最常见的丢单点:邮件发出去了但进了垃圾箱
5 兜底失败重试 + 备份存储转发失败时表单悄悄丢了,谁也不知道
6 留档可选:存一份到对象存储邮箱误删之后查不到原始记录

第一段:接收为什么放在边缘,不放在服务器?

纯静态站没有后端程序,但可以有「一段代码跑在网络边缘」。Cloudflare 把它叫 Pages Functions:

“Use Functions to deploy server-side code to enable dynamic functionality without running a dedicated server.” “Pages Functions allows you to build full-stack applications by executing code on the Cloudflare network with Cloudflare Workers.”

意思是:不用自己维护一台服务器,也能跑服务端代码。放到表单这个场景,就是「有人提交 → 边缘上的一小段函数接住 → 它去调邮件接口」。这段函数只在提交时执行,平时不占资源,也没有常驻进程可以被攻击。

Cloudflare · Pages Functions

要提醒的一点:边缘函数不是「没有后端」,是「后端不由你运维」。代码还是代码,写得糙一样会出问题——比如把 API 密钥硬编码在前端、比如不校验就直接拼进邮件头造成邮件头注入。技术方案不解决水平问题。

第二段:校验要在服务端做一遍

前端加 required 只是给用户提示,绕过它太容易了。真正有效的是在函数里再校验一次:必填项是否为空、邮箱是否符合格式、内容长度是否超过上限。

长度上限这一条常被忽略,但它很关键。一个不限制长度的字段,可以被塞进几兆的垃圾内容,把你的邮件配额一次吃完。限制在两千字符以内,够正常询盘用了。

还有一个细节:校验失败时,返回给用户的提示要说人话。「提交失败,请重试」会让人直接关掉页面;「邮箱格式好像不对,检查一下」会让人改一遍再提交。

第三段:限流与防刷,别把真人挡在外面

不加防护的表单,上线几天就会开始收垃圾:机器人批量提交,内容随机,落款乱七八糟。数量一多,真正的询盘混在里面就被淹了。

三层防护,从轻到重:

  • 频率限制。同一个 IP 十分钟内最多提交三次,超过就拒。这一层最便宜,也最不影响真人。
  • 人机验证。Cloudflare 的 Turnstile 就是干这个的,官方自称「智能验证码替代方案」——多数情况下用户只需点一下,不用认那些歪歪扭扭的字。
  • 蜜罐字段。表单里藏一个正常用户看不见的输入框,机器人会填,填了就判掉。零成本,但只能挡最笨的那批。

顺序建议是先上频率限制和蜜罐,观察一周。垃圾还是多,再上 Turnstile。别一上来就三重全开——防护越重,误伤真人的概率越高,而每一个被误伤的询盘都是钱。

第四段:邮件转发为什么最容易丢?

很多人的表单「能提交但收不到」,问题就在这一段。常见原因三个:

一、直接用自己的邮箱 SMTP 发。用 info@你的域名 作为发件人,通过第三方服务器发出,很容易被判成伪造。收件方看到的是「一个声称是你域名的服务器,但它的 IP 不在你的 SPF 记录里」。

二、SPF / DKIM / DMARC 没配。这三个 DNS 记录的作用是告诉收件方「哪些服务器有权用我的域名发信」。没配的话,你自己正常发的邮件都可能进垃圾箱,更不用说表单转发的。

三、用免费邮箱当收件箱。表单发到 Gmail 或 Outlook 的个人邮箱,量大之后会被限流甚至静默丢弃。这不是 bug,是对方的策略。

稳妥的做法是走专业的邮件服务 API(SendGrid、Mailgun、Resend 这类),发件域做完整认证,收件人用你自己的企业邮箱。多花十美元一个月,换的是「不会莫名其妙丢单」。

第五段:兜底那段漏了,为什么没人知道?

前面都做对,仍然会失败:邮件服务临时抽风、配额用完、收件箱满了。失败的时候如果没有兜底,这封询盘就消失了,而页面还会显示「提交成功」——这是最糟的情况,客户以为发了,你以为没人来。

三层兜底,按成本排:

  1. 失败即报错。邮件接口返回非 2xx,就返回错误给前端,让用户看到「提交失败,请直接发邮件到 xxx」,并同时给出邮箱和 WhatsApp。
  2. 重试一次。偶发的网络抖动重试一次就能过。注意别无限重试,会把自己拖垮。
  3. 落一份备份。把提交内容写进对象存储(比如 R2)或者一个轻量的表,邮件发成功与否都留一份。这样即使邮件丢了,你还能从备份里捞回来。

第三层多花的成本很小,但在「客户说发了、你说没收到」这种扯皮里,它是唯一能拿出证据的东西。

第六段:要不要留档

「不落库」是静态站的特点,不是缺点。它的好处是没有一个存着客户信息的数据库等着被拖——这两年数据泄露的案例里,很多就是这种「顺手存一下」的表被人拿走。

但完全不存也有代价:邮箱误删、员工离职、邮箱迁移,历史询盘就找不回来了。

折中方案:存到对象存储,只存最少的信息(称呼、邮箱、需求正文、提交时间、来源页面),设个保留期(比如一年),访问权限只给一个人。这样既不会形成「高价值攻击目标」,也留了可追溯的记录。

为什么不用现成的第三方表单服务?

第三方表单(Formspree、Jotform 这类)确实省事,但三个问题:

  • 多一个外部依赖。它的脚本要在你的页面上跑,它挂了你的表单就挂了。
  • 样式难统一。要么用 iframe(样式割裂),要么用它的 JS 渲染(加载更慢)。
  • 数据在别人那儿。客户填的内容存在第三方,你要走它的导出口。

小站用第三方没问题,能跑就行。但对一个把询盘当命的外贸站来说,这条链路上每多一个环节,就多一个不受你控制的地方。

我们这条链路长什么样

边缘函数接住提交 → 服务端校验 → 频率限制 + 蜜罐(垃圾多时再加人机验证)→ 走邮件服务 API 转发到客户企业邮箱 → 同时落一份到对象存储 → 失败时页面明确报错并给备选联系方式。

收件人是客户自己的邮箱,我们不中转、不留存。这一点值得强调:有些服务商会把询盘先收到自己那儿再转,美其名曰「帮你筛选」,实际是把你的客户名单握在手里。

说清边界:我们能保证链路本身不丢单(有失败报错、有备份),但保证不了你的邮箱不出问题。企业邮箱的垃圾箱规则、离职员工账号被注销,这些不在技术方案范围内。

表单填了没收到、或者不确定现在这条链路有没有兜底,把域名发我。我从这六段逐条查一遍。

资料来源

  1. Cloudflare · Pages Functions(无独立服务器的服务端代码)
  2. Cloudflare · Turnstile(智能验证码替代方案)
  3. Cloudflare · R2 对象存储(备份落盘用)
  4. RFC 7208 · Sender Policy Framework (SPF)(发件域授权记录)
免费

表单填了没收到?
发我域名,我顺着查一遍。

发邮件
  1. 01
    发网址,一句话说清你在担心什么企业微信或邮件都行,不用先填表、不用先注册。
  2. 02
    我按你给的地址实测一遍挑三个有询盘价值的页面,速度、抓取、表单各跑一次。
  3. 03
    当天给结论,能自己改的给清单该换的也直说,并告诉你换完能省下哪几笔。