本文约 4,288 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:免费、轻量,但默认配置几乎不能直接用
Contact Form 7(简称 CF7)是安装量最大的 WordPress 表单插件之一,没有拖拽界面,全靠表单标签手写。它的优点是轻、灵活、不拖累性能;缺点是新手容易在三个地方卡住:表单标签写错导致字段无效、邮件模板里的变量用错导致收不到内容、以及最经典的「提交成功但邮箱没收到」。
第三点往往不是插件的问题——CF7 默认使用 WordPress 的 wp_mail() 发信,而 wp_mail() 依赖服务器的 PHP mail 函数。虚拟主机、国内云服务器大多没有配置可靠的发信通道,邮件直接被丢弃或进了垃圾箱。理解这条链路,才能对症下药:表单配置的问题在前台,发信的问题在服务器。
原理分析:CF7 的三层结构
| 层级 | 负责什么 | 常见配置项 |
|---|---|---|
| 表单(Form) | 字段与前端结构 | [text* your-name]、[email* your-email]、[submit] |
| 邮件(Mail) | 收件人、主题、正文模板 | [your-email]、[_site_title]、[_remote_ip] |
| 消息(Messages) | 提示文案与校验错误 | 发送成功、验证失败、提交失败提示 |
表单标签的语法规则很简单:[类型 名称 选项],名称后面加 * 表示必填。常用类型有 text、email、textarea、select、checkbox、radio、file、acceptance、quiz、date、number、hidden、submit。
邮件模板里两类变量:字段变量用表单里定义的字段名(如 [your-name]),特殊变量以下划线开头,由插件提供。常用的特殊变量包括:[_site_title]、[_site_url]、[_date]、[_time]、[_remote_ip]、[_user_agent]、[_url]、[_post_title]、[_post_url]、[_post_author]。用错变量名(比如写成 [site_title])不会报错,只会输出空字符串——这是很多人找不到原因的地方。
保姆级实操:从表单到收信一次配好
步骤1:写一份规范的表单。 字段名用小写字母加连字符,必填项加 *,提交按钮写明文案。
<label>姓名 (必填)
[text* your-name autocomplete:name]
</label>
<label>邮箱 (必填)
[email* your-email]
</label>
<label>电话
[tel your-tel]
</label>
<label>需求类型
[select inquiry-type "产品咨询" "技术支持" "商务合作"]
</label>
<label>留言
[textarea your-message x3]
</label>
[acceptance gdpr] 我已阅读并同意隐私政策 [/acceptance]
[submit "提交咨询"]
步骤2:配好邮件模板。 「邮件」选项卡里,收件人填真实邮箱(不要用 admin@example.com 这类占位地址),发件人建议填写与发信域名一致的邮箱,并在「邮件(2)」里配置自动回复。正文可以组合字段变量与特殊变量:
主题:[_site_title] 收到新的咨询([_date] [_time])
姓名:[your-name]
邮箱:[your-email]
电话:[your-tel]
需求:[inquiry-type]
留言:
[your-message]
——
来源页面:[_url]
IP:[_remote_ip]
UA:[_user_agent]
步骤3:处理发信通道。 这是收不到信的真正症结。安装 SMTP 插件(WP Mail SMTP 或 FluentSMTP),把发信改成真实的邮件服务,并用插件自带的测试邮件验证。具体接入参数与排错见WP Mail SMTP / FluentSMTP 插件详细配置。
步骤4:加自定义验证规则。 内置验证只管必填与邮箱格式,手机号、字数等业务规则要自己写。用 wpcf7_validate_{类型} 过滤器,配合 WPCF7_Validation 对象报错。
<?php
// 校验手机号字段:仅允许 11 位中国手机号
add_filter( 'wpcf7_validate_tel', function ( $result, $tag ) {
$tag = new WPCF7_FormTag( $tag );
if ( 'your-tel' !== $tag->name ) {
return $result;
}
$value = isset( $_POST['your-tel'] ) ? trim( wp_unslash( $_POST['your-tel'] ) ) : '';
if ( '' !== $value && ! preg_match( '/^1[3-9]\d{9}$/', $value ) ) {
$result->invalidate( $tag, '请填写有效的 11 位手机号。' );
}
return $result;
}, 10, 2 );
步骤5:只在需要页面加载资源。 CF7 默认在每个页面加载自己的 JS 与 CSS,对不使用表单的页面是浪费。关掉默认加载,再在联系页手动引入。
<?php
// 关闭全局加载
add_filter( 'wpcf7_load_js', '__return_false' );
add_filter( 'wpcf7_load_css', '__return_false' );
// 仅在指定页面加载
add_action( 'wp_enqueue_scripts', function () {
if ( is_page( 'contact' ) ) {
if ( function_exists( 'wpcf7_enqueue_scripts' ) ) {
wpcf7_enqueue_scripts();
}
if ( function_exists( 'wpcf7_enqueue_styles' ) ) {
wpcf7_enqueue_styles();
}
}
} );
步骤6:安装扩展补足能力。 CF7 本体不存储提交的条目,需要存储就装 Flamingo(把每条留言存为自定义文章类型,后台可查看与搜索);需要条件逻辑装 Conditional Fields;需要跳转装 Redirection for Contact Form 7。按需安装,别一次装一堆。
步骤7:排查发送失败。 若前台出现「There was an error trying to send your message. Please try again later.」,说明 wp_mail() 返回了 false。挂到 wp_mail_failed 上把错误记下来,比反复提交有效得多。
<?php
add_action( 'wp_mail_failed', function ( $wp_error ) {
error_log( '发信失败:' . $wp_error->get_error_message() );
} );
步骤8:处理文件上传与大小限制。 使用 [file] 字段时,注意服务器的 upload_max_filesize 与 post_max_size 限制,并在邮件模板里正确带上附件变量。
常见踩坑
- 收件人写成占位邮箱。默认模板里的收件人是示例地址,没改就永远收不到信。
- 变量名写错不报错。
[site_title](少了下划线)只会输出空值,邮件看起来「内容缺失」。 - 发件人与域名不一致被拒收。用
wordpress@example.com这种与站点域名无关的发件人,SPF/DKIM 校验失败,邮件直接进垃圾箱。 wpcf7_validate_*钩子名写错。类型名要跟表单标签一致,且必填字段的类型名带*(如wpcf7_validate_email*不适用于本例写法),不确定时直接用wpcf7_validate通用钩子。- reCAPTCHA 未配置导致提交一直失败。CF7 5.x 的集成页需要填站点密钥与密钥,只启用不填密钥会反复报错。
- 案例:某企业站反馈「客户说提交成功了,但销售说没收到」。排查发现邮件收件人填的是离职员工的邮箱,且该邮箱已失效退信;同时服务器没配 SMTP,
wp_mail()静默失败。整改时改为 SMTP 发信、收件人改成团队邮箱组、并挂上wp_mail_failed记录日志,之后再没出现过「丢了线索」的情况。 - 邮件正文里塞了文件上传链接导致信息泄露。CF7 的附件以服务器上的临时链接形式出现在邮件里,链接过期后打不开,需要装 Flamingo 才能长期保存。
- 缓存插件缓存了含 nonce 的表单页面。用户提交时校验失败,需要把联系页排除出缓存。
总结
CF7 的配置可以归纳为一条链路:表单字段正确 → 邮件模板变量正确 → 发信通道可靠 → 条目有地方存。前两步是插件配置问题,第三步是服务器问题(必须配 SMTP),第四步靠 Flamingo 之类的扩展。排查顺序也应遵循这条链路:先在插件里看有没有生成提交记录,再看 SMTP 日志,最后看收件箱垃圾邮件。若你需要拖拽式搭建、条件逻辑和数据报表,CF7 可能不是最优解,可以对比WPForms / Fluent Forms 拖拽表单配置教程;表单数据如何留存与导出,见表单数据存储与导出(GDPR 考量)。
