You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:基于WordPress Contact Form 7实现邮件确认式表单提交流程

嘿,这个需求我帮很多人解决过——Contact Form 7本身确实没自带这种「用户确认后再发管理员」的双重验证功能,但咱们用几个钩子加自定义代码就能搞定,一步步来:

核心思路

咱们要做的是:拦截表单提交时的默认管理员邮件 → 暂存用户提交的数据并生成唯一确认令牌 → 给用户发带令牌链接的确认邮件 → 用户点击链接后,验证令牌并触发管理员邮件发送 → 清理暂存数据。

1. 拦截提交,暂存数据并发送确认邮件

用CF7的wpcf7_before_send_mail钩子,这个钩子会在邮件发送前触发,正好用来拦截默认的管理员邮件,同时生成令牌、暂存数据,再给用户发确认邮件。

把下面的代码加到你的主题functions.php里,记得替换注释里的表单ID和字段名:

add_action('wpcf7_before_send_mail', 'cf7_save_submission_for_verification');
function cf7_save_submission_for_verification($contact_form) {
    // 替换成你的目标表单ID(在CF7编辑页面看URL里的id参数)
    $target_form_id = 123;
    if ($contact_form->id() != $target_form_id) {
        return;
    }

    // 获取用户提交的所有数据
    $submission = WPCF7_Submission::get_instance();
    if (!$submission) return;
    $posted_data = $submission->get_posted_data();

    // 生成唯一的确认令牌(WordPress自带的UUID生成函数,安全可靠)
    $token = wp_generate_uuid4();

    // 把数据暂存在WordPress选项里,用令牌作为唯一标识
    $temp_key = 'cf7_temp_submission_' . $token;
    update_option($temp_key, array(
        'posted_data' => $posted_data,
        'form_id' => $target_form_id,
        'created_at' => current_time('mysql')
    ), false);

    // 拦截默认的管理员邮件,先不发
    $contact_form->set_prop('mail', null);

    // 准备给用户的确认邮件
    // 替换成你表单里的邮箱字段名(比如你的字段是[email* your-email],就用your-email)
    $user_email = $posted_data['your-email'];
    // 确认链接,后面我们会处理这个路由
    $confirm_url = home_url('/cf7-verify?token=' . $token);

    // 配置用户邮件内容,支持纯文本或HTML
    $user_mail = array(
        'subject' => '请确认你的表单提交',
        'sender' => get_option('admin_email'),
        'recipient' => $user_email,
        'body' => '您好,感谢你的提交!请点击下面的链接完成确认:' . "\n\n" . $confirm_url . "\n\n" . '如果这不是你操作的,请忽略此邮件。',
        'use_html' => false // 要发HTML邮件就改成true,body里写HTML代码
    );

    // 用CF7的mail_2发送用户邮件,不会覆盖你原来的表单设置
    $contact_form->set_prop('mail_2', $user_mail);
}

2. 处理确认链接的验证和邮件发送

接下来需要创建一个路由来处理用户点击确认链接的请求,用template_redirect钩子来捕获这个请求,验证令牌后触发管理员邮件发送:

同样加到主题functions.php里:

add_action('template_redirect', 'cf7_handle_verification');
function cf7_handle_verification() {
    // 检查是否是确认请求,没有token就直接跳过
    if (!isset($_GET['token']) || empty($_GET['token'])) {
        return;
    }

    $token = sanitize_text_field($_GET['token']);
    $temp_key = 'cf7_temp_submission_' . $token;
    $temp_submission = get_option($temp_key);

    // 验证暂存数据是否存在(链接可能过期或无效)
    if (!$temp_submission) {
        wp_die('无效的确认链接,或该链接已过期');
    }

    // 获取对应的表单和提交数据
    $form_id = $temp_submission['form_id'];
    $posted_data = $temp_submission['posted_data'];
    $contact_form = wpcf7_contact_form($form_id);
    if (!$contact_form) {
        wp_die('对应的表单不存在');
    }

    // 恢复表单原来的管理员邮件设置
    $original_admin_mail = $contact_form->prop('mail');
    if (!$original_admin_mail) {
        wp_die('表单未配置管理员邮件,请先在CF7里设置');
    }

    // 重新填充提交数据,触发邮件发送
    $submission = WPCF7_Submission::get_instance();
    if ($submission) {
        $submission->set_posted_data($posted_data);
    }

    // 发送管理员邮件
    $mailer = WPCF7_Mail::get_instance();
    $mailer->send($contact_form, 'mail', $original_admin_mail);

    // 删除暂存的数据,避免用户重复点击发送
    delete_option($temp_key);

    // 跳转到你的感谢页面,替换成实际的页面URL
    wp_redirect(home_url('/thank-you/'));
    exit;
}

3. 额外优化:自动清理过期的暂存数据

为了避免数据库里堆积大量过期的暂存数据,我们可以加一个定时任务,每天清理超过24小时的暂存数据:

// 注册定时任务
add_action('wp', 'cf7_schedule_temp_submission_cleanup');
function cf7_schedule_temp_submission_cleanup() {
    if (!wp_next_scheduled('cf7_cleanup_temp_submissions')) {
        wp_schedule_event(time(), 'daily', 'cf7_cleanup_temp_submissions');
    }
}

// 执行清理逻辑
add_action('cf7_cleanup_temp_submissions', 'cf7_cleanup_temp_submissions');
function cf7_cleanup_temp_submissions() {
    $expire_hours = 24; // 设置过期时间,比如24小时
    $expire_timestamp = strtotime("-$expire_hours hours");
    $all_options = wp_load_alloptions();

    foreach ($all_options as $key => $value) {
        // 筛选出我们暂存的数据键名
        if (strpos($key, 'cf7_temp_submission_') === 0) {
            $submission = get_option($key);
            // 如果创建时间早于过期时间,就删除
            if (strtotime($submission['created_at']) < $expire_timestamp) {
                delete_option($key);
            }
        }
    }
}

注意事项

  • 替换代码里的表单ID:在CF7编辑页面的URL里可以找到,比如wp-admin/admin.php?page=wpcf7&post=123&action=edit里的123就是表单ID。
  • 替换字段名:比如你的邮箱字段是[email* user-email],那代码里的$posted_data['your-email']要改成$posted_data['user-email']。
  • 测试邮件发送:确保你的WordPress已经配置好邮件发送功能(可以用WP Mail SMTP之类的插件优化邮件送达率)。

内容的提问来源于stack exchange,提问作者Envi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:31:00