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
相关产品推荐
相关产品推荐

