PHPMailer封装函数后无法发送验证码邮件求助
问题排查:PHPMailer封装函数后无法发送Gmail验证码邮件
问题描述
使用PHPMailer发送验证码邮件,将发送逻辑封装到sendmail函数后,提交表单时邮件无法正常发送。已使用有效Gmail账号配置SMTP,但邮件仍发送失败,相关配置及完整代码如下:
核心SMTP配置
$mail->Username = 'abc@gmail.com'; $mail->Password = 'secret'; $mail->setFrom('abc@gmail.com', 'Test Email');
完整代码
<?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; //Load Composer's autoloader require 'vendor/autoload.php'; function sendmail($email,$v_code) { //Create an instance; passing `true` enables exceptions $mail = new PHPMailer(true); try { //Server settings $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output $mail->isSMTP(); //Send using SMTP $mail->Host = 'smtp.gmail.com'; //Set the SMTP server to send through $mail->SMTPAuth = true; //Enable SMTP authentication $mail->Username = 'abc@gmail.com'; //SMTP username $mail->Password = 'secret'; //SMTP password $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` //Recipients $mail->setFrom('abc@gmail.com', 'Test Email'); $mail->addAddress($email); //Add a recipient //Content $mail->isHTML(true); //Set email format to HTML $mail->Subject = 'Email verification code'; $mail->Body = "click the link to verify<a href=''>click here</a>"; $mail->send(); return true; } catch (Exception $e) { return false; } } if(isset($_POST['signup-submit'])) { $username = $_POST['username']; $email = $_POST['email']; $password = $_POST['password']; $cnfmpwd = $_POST['repeatpsw']; if (empty($username)) { header("Location: ../signup.php?error=requiredusername"); exit(); } else if (!filter_var($email, FILTER_VALIDATE_EMAIL) && !preg_match("/^[a-zA-Z0-9]*$/", $username)) { header("Location: ../signup.php?error=invaliedusernameemail"); exit(); } else if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { header("Location: ../signup.php?error=invaliedemail"); exit(); } else if (!preg_match("/^[a-zA-Z0-9]*$/", $username)) { header("Location: ../signup.php?error=invalidusername"); exit(); } else if (empty($email)){ header("Location: ../signup.php?error=requiredemail"); exit(); } else if (empty($password)){ header("Location: ../signup.php?error=requiredpassword"); exit(); } else if (empty($cnfmpwd)){ header("Location: ../signup.php?error=requiredcnfmpwd"); exit(); } else if ($password !== $cnfmpwd) { header("Location: ../signup.php?error=pwddonotmatch"); exit(); } else { $check_user="SELECT * FROM users WHERE username ='$_POST[username]' OR email = '$_POST[email]'"; $result=mysqli_query($conn,$check_user); if($result) { if(mysqli_num_rows($result)>0) { $result_fetch = mysqli_fetch_assoc($result); if($result_fetch['username']==$_POST['username']) { header("Location: ../signup.php?error=usernameexists"); exit(); } else { header("Location: ../signup.php?error=emailexists"); exit(); } } else { $password = password_hash($_POST['password'], PASSWORD_BCRYPT); $v_code = bin2hex(random_bytes(16)); $query = "INSERT INTO `users`(`username`, `email`, `password`, `verification_code`, `v_user`) VALUES ('$username','$email','$password','$v_code','0')"; if(mysqli_query($conn,$query) && sendmail($email,$v_code) ) { // data inserted successfully header("Location: ../signup_success.php?signup=success"); exit(); } else { // if data cannot be inserted header("Location: ../signup.php?unsuccesss=unsuccesss"); exit(); } } } } mysqli_close($conn); } else { header("Location: ../signup.php"); exit(); } ?>
排查要点及解决方案
1. Gmail SMTP密码错误(最常见原因)
Gmail目前不支持使用普通账号密码进行SMTP验证,必须使用以下两种方式之一:
- 应用专用密码:先开启账号的两步验证,再在Google账号设置中生成应用专用密码,替换代码中的
'secret'。 - 启用不太安全的应用访问:若未开启两步验证,可在Google账号安全设置中开启该选项(但Google已逐步淘汰此方式,优先推荐应用专用密码)。
2. 错误信息被丢弃,无法定位问题
当前sendmail函数的catch块仅返回false,丢失了PHPMailer抛出的具体错误信息。修改catch块保留错误信息:
catch (Exception $e) { // 测试环境可直接输出,生产环境可存入会话 $_SESSION['mail_error'] = "邮件发送失败: {$mail->ErrorInfo}"; return false; }
之后在跳转后的页面读取$_SESSION['mail_error']即可查看具体错误原因。
3. 数据库连接未初始化,导致逻辑误判
代码中使用$conn执行数据库操作,但未看到$conn的初始化代码(如mysqli_connect)。若$conn未定义,mysqli_query($conn,$check_user)会直接失败,触发后续else分支,让你误以为是邮件发送失败,实际是数据库操作出错。
需提前完成数据库连接:
// 示例:添加数据库连接代码 $conn = mysqli_connect('localhost', 'db_user', 'db_password', 'db_name'); if (!$conn) { die("数据库连接失败: " . mysqli_connect_error()); }
4. SMTP配置的兼容性调整
部分服务器可能拦截465端口,可尝试切换为587端口+STARTTLS加密:
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587;
5. 邮件内容优化(不影响发送,但需修正)
当前邮件Body中的验证链接是空的,需替换为包含$v_code的实际验证地址:
$mail->Body = "点击链接完成验证: <a href='https://yourdomain.com/verify.php?code={$v_code}'>点击这里</a>";
内容的提问来源于stack exchange,提问作者T.Z
相关产品推荐
相关产品推荐

