query($sql)) { return "创建密码重置表失败: " . $conn->error; } return true; } // 生成随机令牌 function generateToken() { return bin2hex(random_bytes(32)); } // 使用QQ SMTP发送密码重置邮件 function sendResetEmailViaQQSMTP($toEmail, $resetLink, $smtpHost, $smtpPort, $smtpUsername, $smtpPassword, $fromName) { // 邮件主题 $subject = "=?UTF-8?B?" . base64_encode("密码重置请求 - 音乐分享网站") . "?="; // 邮件内容 $message = ' 密码重置请求 - 音乐分享网站

您请求重置密码

您好!我们收到了您的密码重置请求,若此操作非您本人发起,请忽略此邮件。

请点击下方按钮重置您的密码(链接有效期为1小时,过期后需重新申请):

若按钮无法点击,可将下方链接复制到浏览器地址栏访问:

' . htmlspecialchars($resetLink) . '

'; // 创建邮件头部 $headers = [ 'From' => $fromName . " <" . $smtpUsername . ">", 'Reply-To' => $smtpUsername, 'X-Mailer' => 'PHP/' . phpversion(), 'MIME-Version' => '1.0', 'Content-Type' => 'text/html; charset=UTF-8' ]; // 组装头部字符串 $headerString = ""; foreach ($headers as $key => $value) { $headerString .= $key . ": " . $value . "\r\n"; } // 使用stream_socket_client发送邮件 $socket = stream_socket_client( 'ssl://' . $smtpHost . ':' . $smtpPort, $errorNumber, $errorMessage, 30, STREAM_CLIENT_CONNECT ); if (!$socket) { throw new Exception("无法连接到SMTP服务器: $errorMessage ($errorNumber)"); } // 发送SMTP命令 fwrite($socket, "EHLO " . gethostname() . "\r\n"); fread($socket, 1024); fwrite($socket, "AUTH LOGIN\r\n"); fread($socket, 1024); fwrite($socket, base64_encode($smtpUsername) . "\r\n"); fread($socket, 1024); fwrite($socket, base64_encode($smtpPassword) . "\r\n"); fread($socket, 1024); fwrite($socket, "MAIL FROM: <" . $smtpUsername . ">\r\n"); fread($socket, 1024); fwrite($socket, "RCPT TO: <" . $toEmail . ">\r\n"); fread($socket, 1024); fwrite($socket, "DATA\r\n"); fread($socket, 1024); fwrite($socket, "Subject: " . $subject . "\r\n"); fwrite($socket, $headerString . "\r\n"); fwrite($socket, $message . "\r\n"); fwrite($socket, ".\r\n"); fread($socket, 1024); fwrite($socket, "QUIT\r\n"); fread($socket, 1024); fclose($socket); return true; } // 处理表单提交 if ($_SERVER["REQUEST_METHOD"] == "POST") { $email = trim($_POST['email'] ?? ''); if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $message = "请输入有效的邮箱地址"; $messageType = "error"; } else { $conn = new mysqli($servername, $dbusername, $dbpassword, $dbname); if ($conn->connect_error) { throw new Exception("数据库连接失败: " . $conn->connect_error); } $tableCheck = ensurePasswordResetTableExists($conn); if ($tableCheck !== true) { throw new Exception($tableCheck); } $stmt = $conn->prepare("SELECT id FROM users WHERE email = ?"); if (!$stmt) { throw new Exception("准备查询语句失败: " . $conn->error); } $stmt->bind_param("s", $email); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows == 1) { $stmt->bind_result($userId); $stmt->fetch(); $token = generateToken(); $expiry = date('Y-m-d H:i:s', strtotime('+1 hour')); $updateStmt = $conn->prepare("INSERT INTO password_reset_tokens (user_id, token, expiry) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE token = ?, expiry = ?"); if (!$updateStmt) { throw new Exception("准备更新语句失败: " . $conn->error); } $updateStmt->bind_param("issss", $userId, $token, $expiry, $token, $expiry); $updateStmt->execute(); // 生成重置链接 $resetLink = "http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . "/reset_password.php?token=" . $token; try { // 发送重置邮件 sendResetEmailViaQQSMTP( $email, $resetLink, $smtpHost, $smtpPort, $smtpUsername, $smtpPassword, $fromName ); $message = "密码重置链接已发送到您的邮箱,请查收(1小时内有效)"; $messageType = "success"; } catch (Exception $e) { $message = "邮件发送失败: " . $e->getMessage(); $messageType = "error"; error_log("邮件发送错误: " . $e->getMessage()); } $updateStmt->close(); } else { // 安全考虑,无论邮箱是否存在,都显示相同的成功消息 $message = "如果该邮箱已注册,密码重置链接将发送"; $messageType = "success"; } $stmt->close(); $conn->close(); } } } catch (Exception $e) { $message = "系统错误: " . $e->getMessage(); $messageType = "error"; error_log("Forgot Password Error: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine()); } ?> 忘记密码 - 音乐分享网站

忘记密码