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

PHPMailer HTML邮件添加跳转按钮及token验证失败问题求助

问题分析与修复方案

核心问题:邮件模板变量未正确解析

你用单引号定义了$email_template,PHP不会解析单引号字符串内的变量,导致邮件链接里的$verify_token始终是字面量,而非实际生成的验证token值,所以跳转后verify.php找不到对应token,触发“token不存在”提示。

修复步骤

1. 修正邮件模板的变量解析逻辑

将模板定义的单引号改为双引号,确保PHP能正确替换变量;同时修复样式和HTML结构的小问题:

$email_template = "
<html>
<head>
    <link
        href='https://fonts.googleapis.com/css2?family=Montserrat:wght@200;300;500;700;800&family=Source+Sans+Pro:wght@700&display=swap'
        rel='stylesheet'
    />
    <style>
        body {
            width: 100%;
            min-height: 100vh;
            align-items: center;
            display: block;
            justify-content: center;
            user-select: none;
            position: absolute;
            top: 80px;
        }

        table {
            border-spacing: 0;
        }

        td {
            padding: 0;
            background-color: rgba(247, 189, 22, 0.8);
            width: 655px;
            height: 300px;
            border-radius: 10px;
            margin-top: 7%;
            align-items: center;
        }

        .webkit {
            max-width: 600px;
            background-color: #ffffff;
        }

        .main {
            font-family: 'Montserrat', sans-serif;
        }

        .main p {
            text-align: center;
            margin-left: 20px;
            margin-right: 20px;
            font-weight: 700;
            font-size: 14px;
        }

        .main h1 {
            font-size: 25px;
            text-align: center;
        }

        .reset-btn {
            background-color: rgba(45, 45, 45, 0.9);
            font-size: 14.5px;
            color: #fff;
            font-family: 'Montserrat', sans-serif;
            font-weight: 400;
            width: 100px;
            padding: 8px 60px;
            margin: 0 auto;
            cursor: pointer;
            justify-content: center;
            align-items: center;
            border: none;
            border-radius: 50px;
        }

        .reset-btn:hover {
            background: rgba(79, 79, 79, 0.9);
        }

        .reset-btn a {
            color: white;
            text-decoration: none;
        }
    </style>
</head>

<body>
    <center class='wrapper'>
        <div class='webkit'>
            <table class='main'>
                <tr>
                    <td>
                        <h1>Hi $name!</h1>
                        <p>
                            你最近在OFAD-APPSYS注册,使用的邮箱是:$email。
                        </p>
                        <p>点击下方按钮完成账号验证:</p>

                        <div class='reset-btn' style='text-align: center'>
                            <a href='http://localhost/appsys/website/verify.php?token=$verify_token'>验证邮箱</a>
                        </div>

                        <p>
                            若你未注册OFAD-APPSYS,请忽略此邮件。
                        </p>
                    </td>
                </tr>
            </table>
        </div>
    </center>
</body>
</html>
";

修正说明:

  • 把单引号改为双引号,让$name、$email、$verify_token变量被正确解析
  • 移除重复的</html>标签
  • 修复按钮样式,将无效的font-color改为color,并给a标签单独设置样式确保显示正常

2. 修复verify.php的SQL注入风险与稳定性

原代码直接拼接用户输入到SQL语句,存在注入风险,同时可能因token含特殊字符导致查询失败,改用预处理语句:

<?php
session_start();
include('db.php');

if(isset($_GET['token']))
{
    $token = $_GET['token'];
    // 预处理查询,防止SQL注入
    $verify_query = "SELECT verify_token, verify_status FROM register WHERE verify_token=? LIMIT 1";
    $stmt = mysqli_prepare($conn, $verify_query);
    mysqli_stmt_bind_param($stmt, "s", $token);
    mysqli_stmt_execute($stmt);
    $verify_query_run = mysqli_stmt_get_result($stmt);

    if (mysqli_num_rows($verify_query_run) > 0) 
    {
          $row = mysqli_fetch_array($verify_query_run);
          if($row['verify_status'] == "0")
          {
            $clicked_token = $row['verify_token'];
            // 预处理更新语句
            $update_query = "UPDATE register SET verify_status='1' WHERE verify_token = ? LIMIT 1";
            $update_stmt = mysqli_prepare($conn, $update_query);
            mysqli_stmt_bind_param($update_stmt, "s", $clicked_token);
            $update_query_run = mysqli_stmt_execute($update_stmt);

                if($update_query_run)
                {
                  $_SESSION['status'] = "账号验证成功!";
                  header("Location: verify-success.php");
                  exit(0);
                }
                else 
                {
                  $_SESSION['status'] = "验证失败,请重试";
                  header("Location: login.php");
                  exit(0);
                }
          }
          else 
          {
            $_SESSION['status'] = "该邮箱已完成验证,请直接登录";
            header("Location: login.php");
            exit(0);
          }
    }
    else 
    {
      $_SESSION['status'] = "无效的验证token";
      header("Location: login.php");
    }
}
else 
{
  $_SESSION['status'] = "非法访问";
  header("Location: login.php");
}
?>

3. 额外验证步骤

  • 发送邮件前,先echo $email_template;查看链接是否包含真实的token值,确认变量替换生效
  • 检查用户注册时,verify_token是否已正确存入register表的对应字段

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:41:30