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

PHPMailer 6联系表单发信附件正常但reCaptcha V2校验被跳过

reCaptcha V2集成失效修复方案

你的代码存在3处直接导致验证逻辑失效、功能异常的问题,具体如下:

  • 逻辑分支语法错误:校验表单提交参数的if语句提前闭合了大括号,后续验证码校验、邮件发送的逻辑完全脱离了分支判断。当用户未勾选验证码时,$captchaResult变量未定义,PHP弱类型比较会直接判定条件成立,跳过验证发送邮件。
  • 附件字段名不匹配:HTML中文件上传控件的name属性为attachment[],PHP处理逻辑中错误引用为$_FILES['userfile'],会导致多附件上传功能完全失效。
  • 异常场景处理缺失:未兼容cURL请求失败、验证码返回参数为空、接口返回格式异常的边界情况,容易出现验证绕过或代码报错。

修正后的PHP后端代码

<?php

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require './src/Exception.php';
require './src/PHPMailer.php';
require './src/SMTP.php';

class CaptchaTest
{
  private $captchaSecretKey = '替换为你自己的reCaptcha私钥';

  public function testCaptchaResponse($captchaResponse)
  {
    // 空值直接返回验证失败
    if(empty($captchaResponse)) return false;
    $createGoogleUrl = 'https://www.google.com/recaptcha/api/siteverify?secret='.urlencode($this->captchaSecretKey).'&response='.urlencode($captchaResponse);
    $verifyRecaptcha = $this->sendHttpRequest($createGoogleUrl);
    // 接口请求失败直接返回失败
    if(!$verifyRecaptcha) return false;
    $decodeGoogleResponse = json_decode($verifyRecaptcha,true);
    // 返回格式校验
    if(!isset($decodeGoogleResponse['success'])) return false;
    return (bool)$decodeGoogleResponse['success'];
  }
  
  private function sendHttpRequest($url)
  {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, 80);
    
    $response = curl_exec($ch);
    curl_close($ch);
    return $response;
  }
}


$captchaResult = false;
// 修正大括号位置,所有业务逻辑放在提交判断分支内
if(isset($_POST['submit'])) {
    // 兼容captcha参数不存在的情况
    $captchaResp = isset($_POST['g-recaptcha-response']) ? $_POST['g-recaptcha-response'] : '';
    $cTest = new CaptchaTest();
    $captchaResult = $cTest->testCaptchaResponse($captchaResp); 

    if ($captchaResult == true) {

        $mail = new PHPMailer(true);
        $mail->SMTPDebug = 0;
        $mail->Host = 'in-v3.mailjet.com';
        $mail->SMTPAuth = true;
        $mail->Username = '替换为你的Mailjet账号';
        $mail->Password = '替换为你的Mailjet密码';
        $mail->SMTPSecure = 'tls';
        $mail->Port = 587;
        $mail->setFrom($_POST['email'], $_POST['name']);
        $mail->addAddress('替换为你的收件邮箱');
        $mail->addReplyTo($_POST['email'], $_POST['name']);
        

        // 修正附件字段名和前端匹配
        if(isset($_FILES['attachment']['tmp_name']) && is_array($_FILES['attachment']['tmp_name'])){
            for ($ct = 0; $ct < count($_FILES['attachment']['tmp_name']); $ct++) {
              // 过滤无效上传项
              if($_FILES['attachment']['error'][$ct] != UPLOAD_ERR_OK) continue;
              $uploadfile = tempnam(sys_get_temp_dir(), hash('sha256', $_FILES['attachment']['name'][$ct]));
              $filename = $_FILES['attachment']['name'][$ct];
        
              if (move_uploaded_file($_FILES['attachment']['tmp_name'][$ct], $uploadfile)) {
                $mail->addAttachment($uploadfile, $filename);
              } 
            }
        }

        $mail->isHTML(true);
        $mail->Subject = 'Website Enquiry';
        // 转义用户输入,防范XSS和邮件头注入风险
        $name = htmlspecialchars($_POST['name']);
        $company = htmlspecialchars($_POST['company']);
        $phone = htmlspecialchars($_POST['phone']);
        $email = htmlspecialchars($_POST['email']);
        $message = nl2br(htmlspecialchars($_POST['message']));
        $mail->Body = "<p>You received an enquiry from:</p>
          <b>Name:</b>  $name<br><br>
          <b>Company:</b>  $company<br><br>
          <b>Phone Number:</b>  $phone<br><br>
          <b>E-Mail:</b> $email<br><br>
          <b>Message:</b> $message";
          
        try {
             $mail->send();
             header('Location: thank.html');
             exit;
        } catch (Exception $e) {
            echo "Your message could not be sent! PHPMailer Error: {$mail->ErrorInfo}";
        }
    } 
    else
    {
        echo "Captcha failed, please try again";
    }
}
?>

可选前端体验优化

可以在表单提交前加一层JS校验,用户未勾选验证码时直接提示,减少无效后端请求:

$('#form').submit(function(e){
    if(grecaptcha.getResponse().length == 0){
        alert('请先完成人机验证');
        e.preventDefault();
        return false;
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:18:20