静态网站不用写一行后端代码,把用户留言直接发到你的邮箱。
一、快速决策(30 秒选方案)
| 你的情况 | 选这个 |
|---|---|
| 免费、够用、异步不跳页,接受注册 | Web3Forms(推荐) |
| 看重老牌品牌和生态、需要 Dashboard 记录提交历史 | Formspree |
| 想要”一行 action 零注册”的极简方案 | ❌ FormSubmit.co 已永久离线,此路不通(见第四节) |
为什么不再推荐 FormSubmit.co?
它曾是最简单的无后端表单服务,但源服务器已不可访问,处于永久离线状态。此外,多个安全平台因其所有权信息不公开将其评为”可疑网站”,信任评分很低,已被多家安全机构列入黑名单,部分浏览器会将其拦截或误报为网络钓鱼。网上的旧教程全部失效,不要在任何项目中使用。
二、方案一:Web3Forms
官网: https://web3forms.com
定位: 面向开发者的无后端表单 API,异步提交不跳页
核心参数
| 项 | 值 |
|---|---|
| 免费额度 | 250 提交/月 |
| 注册要求 | 必须(邮箱注册 → Dashboard 拿 Access Key) |
| 提交方式 | JS fetch() 异步 POST,无页面跳转 |
| JS 依赖 | 必须 |
| 反垃圾 | AI botcheck + Honeypot + 速率限制 |
| 自动回复 | ✅ 免费自带(Dashboard 开启 AutoResponder) |
| 文件上传 | ❌ 免费不支持,Pro 支持(≤3MB) |
| Pro 价格 | $7/月(无限制 + 自定义域名 + 入站白名单) |
| Key 暴露 | ⚠️ Access Key 会暴露在前端 HTML 中(无法避免) |
| 数据保留 | 不存储,转发即删 |
注册与获取 Key
- 打开 https://web3forms.com → 输入邮箱注册
- 进入 Dashboard,复制 Access Key
- 在项目代码中把
YOUR_ACCESS_KEY替换为真实 Key
HTML 表单(原生 POST,会跳页)
<form action="https://api.web3forms.com/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input type="text" name="name" placeholder="您的姓名" required />
<input type="email" name="email" placeholder="电子邮箱" required />
<textarea name="message" placeholder="留言内容" required></textarea>
<button type="submit">发送留言</button>
</form>
注意: 这种方式提交后会跳转到 Web3Forms 的成功页,用户体验较差。推荐使用下面的 JS 异步方式。
HTML 表单(配合 JS 异步,无跳页)
<form id="contactForm">
<!-- 反垃圾 honeypot,必须加,否则被识别为垃圾提交 -->
<input type="checkbox" name="botcheck" style="display:none;" />
<input type="text" name="name" placeholder="您的姓名" required />
<input type="email" name="email" placeholder="电子邮箱" required />
<input type="text" name="subject" placeholder="主题" />
<textarea name="message" placeholder="留言内容" required></textarea>
<button type="submit">发送留言</button>
<p id="formMsg" style="display:none;"></p>
</form>
关键:
<input name="botcheck">是 Web3Forms 的 Honeypot 字段,不加会被识别为垃圾提交。
JavaScript 异步提交(FormData 方式)
const form = document.getElementById("contactForm");
const formMsg = document.getElementById("formMsg");
const submitBtn = form.querySelector('button[type="submit"]');
const ACCESS_KEY = "YOUR_ACCESS_KEY"; // ⚠️ 替换为 Dashboard 中的真实 Key
form.addEventListener("submit", async function (e) {
e.preventDefault();
const formData = new FormData(form);
formData.append("access_key", ACCESS_KEY);
const originalText = submitBtn.textContent;
submitBtn.textContent = "发送中...";
submitBtn.disabled = true;
try {
const res = await fetch("https://api.web3forms.com/submit", {
method: "POST",
body: formData,
});
const data = await res.json();
if (data.success) {
formMsg.textContent = "留言已发送,我们会尽快回复!";
formMsg.style.color = "#4ade80";
formMsg.style.display = "block";
form.reset();
} else {
throw new Error(data.message || "提交失败");
}
} catch (err) {
formMsg.textContent = "发送失败,请稍后重试或直接发送邮件至 your-email@example.com";
formMsg.style.color = "#ef4444";
formMsg.style.display = "block";
} finally {
submitBtn.textContent = originalText;
submitBtn.disabled = false;
}
});
JavaScript 异步提交(JSON 方式)
const form = document.getElementById("contactForm");
const formMsg = document.getElementById("formMsg");
const ACCESS_KEY = "YOUR_ACCESS_KEY";
form.addEventListener("submit", async function (e) {
e.preventDefault();
const btn = form.querySelector('button[type="submit"]');
btn.textContent = "发送中...";
btn.disabled = true;
try {
const res = await fetch("https://api.web3forms.com/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
access_key: ACCESS_KEY,
...Object.fromEntries(new FormData(form)),
}),
});
const data = await res.json();
if (data.success) {
formMsg.textContent = "留言已发送,我们会尽快回复!";
formMsg.style.color = "#4ade80";
formMsg.style.display = "block";
form.reset();
} else {
throw new Error(data.message || "提交失败");
}
} catch (err) {
formMsg.textContent = "发送失败,请稍后重试或直接发送邮件至 your-email@example.com";
formMsg.style.color = "#ef4444";
formMsg.style.display = "block";
} finally {
btn.textContent = "发送留言";
btn.disabled = false;
}
});
FormData vs JSON: 两种方式都可以,FormData 方式更简洁,JSON 方式可以更灵活地添加额外字段。
React 实现
import { useState } from "react";
export default function ContactForm() {
const [result, setResult] = useState("");
const [isSuccess, setIsSuccess] = useState(false); // 提交结果是否成功:true 绿字 / false 红字,用于结果提示配色
const [isSubmitting, setIsSubmitting] = useState(false); // 是否正在提交:true 时禁用按钮并显示"发送中...",防重复提交
const ACCESS_KEY = "YOUR_ACCESS_KEY"; // ⚠️ 替换为 Dashboard 中的真实 Key
const onSubmit = async event => {
event.preventDefault();
setIsSubmitting(true);
const formData = new FormData(event.target);
formData.append("access_key", ACCESS_KEY);
try {
const response = await fetch("https://api.web3forms.com/submit", {
method: "POST",
body: formData,
});
const data = await response.json();
if (data.success) {
setResult("留言已发送,我们会尽快回复!");
setIsSuccess(true);
event.target.reset();
} else {
setResult("发送失败,请稍后重试");
setIsSuccess(false);
}
} catch (error) {
setResult("发送失败,请稍后重试");
setIsSuccess(false);
} finally {
setIsSubmitting(false);
}
};
return (
<form onSubmit={onSubmit}>
<input
type="text"
name="name"
placeholder="您的姓名"
required
disabled={isSubmitting}
/>
<input
type="email"
name="email"
placeholder="电子邮箱"
required
disabled={isSubmitting}
/>
<textarea
name="message"
placeholder="留言内容"
required
disabled={isSubmitting}
></textarea>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "发送中..." : "发送留言"}
</button>
{result && <p style={{ color: isSuccess ? "#4ade80" : "#ef4444" }}>{result}</p>}
</form>
);
}
三种实现方式对比:
- 纯 HTML:最简单,但会跳页,用户体验差
- 纯 JS:异步无跳页,适合传统网页
- React:组件化,状态管理清晰,适合现代前端框架项目
高级配置
自定义邮件主题: 在 Web3Forms Dashboard → Form Settings 中设置 subject,多个站点可用不同主题区分来源。
自动回复(免费): Dashboard → Form Settings → 开启 AutoResponder,用户提交后收到自动确认邮件。
自定义成功跳转: 在 fetch body 中添加 redirect 字段:
body: JSON.stringify({
access_key: ACCESS_KEY,
redirect: "https://你的域名/thanks.html",
...Object.fromEntries(new FormData(form)),
});
但更推荐用异步 JS 控制成功提示,比跳页体验更好。
三、方案二:Formspree(备选)
官网: https://formspree.io
定位: 最老牌的无后端表单服务,50 万+ 用户,生态最成熟
适合: 需要 Dashboard 管理提交记录、需要集成 Slack / Notion 等工具的场景
核心参数
| 项 | 值 |
|---|---|
| 免费额度 | 50 提交/月 |
| 注册要求 | 必须(邮箱注册 → 创建表单 → 获取 endpoint) |
| 提交方式 | JS fetch() 异步 POST(推荐)或原生 form POST |
| JS 依赖 | 推荐有(不加则会跳页到 Formspree 成功页) |
| 反垃圾 | Formshield ML 过滤 + reCAPTCHA + 自定义规则 |
| 数据保留 | ⚠️ 免费版仅 30 天(超期自动删除,无法恢复) |
| 文件上传 | ❌ 免费版不支持 |
| 自动回复 | ❌ 免费版不支持 |
| Dashboard | ✅ 丰富:搜索、导出 CSV、查看详情 |
| 第三方集成 | ✅ Slack、Notion、Airtable、Google Sheets 等 25+ |
| 付费起步 | $10/月(年付,200 提交/月,无限归档,1GB 上传) |
注册与获取 Endpoint
- 打开 https://formspree.io → 注册
- 创建新表单 → 获得类似
https://formspree.io/f/xxxxxxxx的 endpoint - 验证邮箱(首次收邮件点确认)
HTML + JS(fetch 方式,无跳页)
<form id="contactForm">
<input type="text" name="name" placeholder="您的姓名" required />
<input type="email" name="email" placeholder="电子邮箱" required />
<textarea name="message" placeholder="留言内容" required></textarea>
<button type="submit">发送留言</button>
<p id="formMsg" style="display:none;"></p>
</form>
<script>
const form = document.getElementById("contactForm");
const formMsg = document.getElementById("formMsg");
form.addEventListener("submit", async function (e) {
e.preventDefault();
const btn = form.querySelector("button");
btn.textContent = "发送中...";
btn.disabled = true;
try {
// ⚠️ Formspree 用 FormData,不是 JSON;Accept header 必须带
const res = await fetch("https://formspree.io/f/YOUR_FORM_ID", {
method: "POST",
headers: { Accept: "application/json" },
body: new FormData(form),
});
if (res.ok) {
formMsg.textContent = "留言已发送,我们会尽快回复!";
formMsg.style.color = "#4ade80";
formMsg.style.display = "block";
form.reset();
} else {
throw new Error("提交失败");
}
} catch (err) {
formMsg.textContent = "发送失败,请稍后重试或直接发送邮件至 your-email@example.com";
formMsg.style.color = "#ef4444";
formMsg.style.display = "block";
} finally {
btn.textContent = "发送留言";
btn.disabled = false;
}
});
</script>
与 Web3Forms JS 的关键区别:
- 两者都支持
FormData与JSON两种提交方式(本文 Web3Forms 主示例用 FormData,亦可改用JSON.stringify,见上方 JSON 方式)。- Formspree 必须带
Accept: application/json,否则返回 HTML 跳页;Web3Forms 两种方式都不需要该头。- 判断成功:Formspree 用
res.ok,Web3Forms 用响应体里的data.success字段判断(即使 HTTP 200 也可能success:false)。
免费版关键限制
| 限制 | 影响 |
|---|---|
| 数据仅保留 30 天 | 超期的提交记录永久丢失,无法恢复 |
| 无文件上传 | 用户无法提交附件 |
| 仅 2 个邮箱 | 只能关联两个收件邮箱 |
| 无自动回复 | 用户提交后不会收到确认邮件 |
| 50 提交/月 | 比 Web3Forms 的 250/月 少了 5 倍 |
如果你不会每天登录 Dashboard 导出数据,Formspree 免费版的 30 天归档窗口是个硬伤。
四、已关停 — FormSubmit.co
原域名: https://formsubmit.co
状态: 源服务器已不可访问,处于永久离线状态。
FormSubmit.co 曾是静态网站表单的”杀手级应用”——无需注册,一行 action="https://formsubmit.co/你的邮箱" 搞定,极低学习成本。其核心机制是通过 HTML 隐藏字段配置行为,所有配置都在 <input type="hidden" name="_xxx" value="..."> 中完成。
⚠️ 安全隐患
除了服务已离线外,FormSubmit.co 还被多个安全平台列为可疑网站:
- 信任评分极低:因所有权信息公开不透明,多家安全平台将其评为”不可信”
- 已被拉黑:多家安全机构将其列入黑名单
- 浏览器拦截:部分浏览器会拦截其页面或误报为网络钓鱼
- 敏感数据风险:如果曾有用户在你的表单中输入过邮箱等个人信息,这些数据经过了不受信任的第三方中转
结论: 即便将来该域名恢复访问,也不应再使用。它将用户提交的表单数据经由不可信实体转发,存在隐私泄漏风险。
关停教训
不要依赖无收益商业模式的免费服务,迁移成本在关停那一刻才真正计算清楚。 网上的旧教程全部失效。
旧版隐藏字段速查(仅供历史参考,已全部失效)
| 字段 | 值 | 说明 |
|---|---|---|
_captcha |
false |
跳过验证码(默认开启) |
_subject |
任意字符串 | 邮件主题 |
_template |
table / plain |
邮件格式,推荐 table |
_next |
URL | 提交成功后跳转地址 |
_cc |
邮箱地址 | 抄送 |
_autoresponse |
文本 | 自动回复(需 Pro) |
_honey |
任意 | 反垃圾蜜罐字段名 |
_replyto |
邮件字段名 | 回复时指向提交者邮箱 |
_webhook |
URL | 提交后回调 Webhook(Pro) |
迁移路线:FormSubmit.co → Web3Forms
| 旧功能 | Web3Forms 替代方式 |
|---|---|
| 零注册 | 注册一次 → 拿 Access Key → 再也不需要注册 |
| 一行 action | 注册一次 → Key 填入 JS → 永久使用 |
| 50 免费/月 | 250 免费/月(5 倍于旧版) |
_captcha |
内置 botcheck(AI 反垃圾),无需手动配置验证码 |
_subject |
Dashboard 配置 或 JSON body 中 subject 字段 |
_template |
Dashboard 可配置 HTML 邮件模板 |
_next 跳转 |
JSON body 中 redirect 字段 或 JS then() 控制(推荐后者) |
_cc |
Dashboard 配置 |
_autoresponse |
免费自带(Dashboard 开启 AutoResponder) |
_honey |
内置 Honeypot(<input name="botcheck">),不建议额外加 |
核心建议: 如果你有基于 FormSubmit.co 搭建的存量项目,迁移到 Web3Forms 是最平滑的路径——功能覆盖最完整,免费额度更高,且唯一需要改动的是把 HTML 隐藏字段替换为 JS fetch + Dashboard 配置。
五、FormSubmit.site(不推荐)
FormSubmit.site 是一个需要注册的商业化付费表单服务(按提交量付费,$10 起),采用 CLI + Dashboard 双模操作,运营者联系邮箱为 nikunj@formsubmit.site。目前没有公开信息直接表明它与 FormSubmit.co 属于同一实体,从产品形态看两者是独立项目:
- FormSubmit.co(已离线):经典免费表单后端,无需注册,HTML action 直接填邮箱
- FormSubmit.site(商业化):需要注册账户,按量付费,提供仪表盘和数据管理
FormSubmit.site 不兼容旧版 _xxx 隐藏字段体系(无 _captcha、_next、_cc、_autoresponse 等),反垃圾使用启发式评分而非验证码,是一款从零设计的独立新产品。考虑到它是 CLI 命令行产品、无免费层、且版本仍为 v0.1.1,对于静态网站表单需求来说,Web3Forms 或 Formspree 是更直接的选择。
六、综合对比
6.1 核心参数
| 维度 | Web3Forms | Formspree |
|---|---|---|
| 官网 | web3forms.com | formspree.io |
| 免费额度 | 250 封/月 | 50 封/月 |
| 注册要求 | 必须注册,获取 Access Key | 必须注册,创建表单 → 获取 endpoint |
| 入门成本 | $0 | $0 |
| Pro 起步 | $7/月(无限量 + 自定义域名) | $10/月(年付,200 提交/月) |
| 提交方式 | JS fetch() 异步 POST(JSON body) |
JS fetch() 异步 POST(FormData body)或原生 form |
| JS 依赖 | 必须(fetch + JSON) | 推荐(fetch + FormData);也可原生 form(会跳页) |
| 验证码 | 内置 botcheck(AI 反垃圾)+ Honeypot | ML Formshield + reCAPTCHA |
| 邮件模板 | 可自定义 HTML 模板 | 基础模板,Dashboard 可配置 |
6.2 功能特性
| 特性 | Web3Forms | Formspree |
|---|---|---|
| 文件上传 | Pro 支持,免费 ≤3MB | ❌ 免费版不支持 |
| 自动回复(给提交者) | ✅ 免费自带(Dashboard 开启 AutoResponder) | ❌ 付费功能 |
| 成功回调 / 跳转 | JS then() 自定义;也可 redirect 字段 |
JS then() 或原生 form |
| 抄送(CC) | Dashboard 配置 | Dashboard 配置 |
| Honeypot 反垃圾 | 不建议额外加(冲突内置 botcheck) | ✅ 支持自定义隐藏字段 |
| 自定义邮件主题 | subject 字段或 Dashboard |
Dashboard 配置 |
| 多站点区分 | Access Key 绑定域名 | 创建多个表单 |
| 入站白名单 | Pro 功能 | 企业版功能 |
| 数据保留(免费) | 不存储(转发即删) | ⚠️ 仅 30 天,超期删除 |
| 第三方集成 | 基础(Zapier 等) | 25+(Slack、Notion、Airtable、Google Sheets 等) |
| Dashboard | ✅ 基础(提交记录、配置) | ✅ 丰富(搜索、导出 CSV、详情) |
| CLI / AI 工具链 | ❌ | ❌ |
6.3 用户体验
| 维度 | Web3Forms | Formspree |
|---|---|---|
| 提交体验 | 异步无刷新,停留在当前页 | 异步(fetch)无刷新;原生 form 会跳页 |
| 自定义成功页 | ✅ JS 完全控制 | ✅ JS 控制 |
| 首次启动流程 | 注册 → 拿 Key → 写代码 | 注册 → 创建表单 → 拿 endpoint → 验证邮箱 |
| 收件箱改动 | 无需(转发即达) | 首次需点确认链接 |
| 学习成本 | 中等(需了解 fetch API) | 中等(需了解 fetch API) |
| 调试难度 | 浏览器 DevTools Network 面板 | 浏览器 DevTools Network 面板 |
6.4 安全 & 隐私
| 维度 | Web3Forms | Formspree |
|---|---|---|
| Key / Token 暴露 | ⚠️ Access Key 会暴露在前端 HTML 中 | ⚠️ Form ID 会暴露在前端 |
| 垃圾邮件防护 | AI botcheck + 速率限制 | ML Formshield + reCAPTCHA + 自定义规则 |
| 可限制提交来源 | Pro 可限制白名单域名 | 企业版可限制 |
| 数据存储策略 | 不存储(转发即删) | 不存储(转发即删) |
| GDPR 合规 | ✅ 合规 | ✅ 合规 |
| 稳定性 | 成熟 | 最老牌(50 万+ 用户) |
七、切换指南
7.1 迁移到 Web3Forms(从任意方案)
- 注册 Web3Forms → https://web3forms.com → 拿 Access Key
- 改 HTML 表单:
- 删除
action="..."改为无 action 的<form id="contactForm"> - 删除所有
_xxx隐藏字段(原 FormSubmit.co 用法) - 添加
<input type="checkbox" name="botcheck" style="display:none;">(必须)
- 删除
- 替换 JS:用本文第二节的异步代码
- 填入 Key:把
YOUR_ACCESS_KEY换成真实 Key - 测试:提交一条留言,检查目标邮箱是否收到
7.2 切换到 Formspree(从 Web3Forms)
- 注册 Formspree → 创建表单 → 拿到
https://formspree.io/f/xxxxxxxx - 改 HTML:删除
botcheck字段,表单无需特殊字段 - 替换 JS:把
fetch目标换为 Formspree endpoint;body 改用new FormData(form);添加Accept: application/jsonheader;判断改为res.ok - 验证邮箱:首次提交后去收件箱点确认
- 测试:再提交,确认邮件正常送达
八、故障排查
Web3Forms
- Access Key 是否已填? — 确认 JS 中
YOUR_ACCESS_KEY已替换为真实 Key - botcheck 字段是否存在? — 表单中必须有
<input name="botcheck" style="display:none;"> - Network 面板检查 — 看
api.web3forms.com/submit返回的data.success是否为true - Dashboard 检查 — 登录 Web3Forms 查看是否有提交记录,或被反垃圾拦截
- 垃圾箱 — 首次注册确认邮件是否在邮箱垃圾箱
Formspree
- 表单 ID 是否正确? — endpoint 中
/f/xxxxxxxx与 Dashboard 一致 - 邮箱是否已验证? — 首次收到激活邮件需点击确认
- Accept header — fetch 是否带
'Accept': 'application/json'(不带会跳页) - body 格式 — 是否用
new FormData(form)而非 JSON.stringify - Dashboard 检查 — 登录 Formspree 查看提交记录
通用排查
- name 属性 — 所有
<input>、<textarea>都必须有name属性 - 垃圾箱 — 首次邮件经常被误判为垃圾邮件
- 网络问题 — 检查浏览器控制台有无 CORS 或网络错误
- 服务冲突 — 确保没有 Netlify Forms 等其他服务拦截表单提交
九、速查卡片
Web3Forms
注册 → 拿 Access Key → JS fetch('https://api.web3forms.com/submit', {JSON body})
必须加 <input name="botcheck" style="display:none;">(Honeypot,防垃圾)
免费 250/月 | Pro $7/月
优势:异步不跳页 | 自动回复免费 | 250/月够用 | 配置简单
劣势:Key 暴露在前端 | 必须 JSFormspree(备选)
注册 → 创建表单 → fetch('https://formspree.io/f/ID', {FormData + Accept:json})
免费 50/月(数据仅保留 30 天)| Pro $10/月
优势:最老牌 | Dashboard 丰富 | 25+ 集成
劣势:免费版 30 天删数据 | 无自动回复 | 无文件上传 | 额度少