674 行
22 KiB
PHP
674 行
22 KiB
PHP
<?php
|
||
// 引入数据库模块
|
||
require_once __DIR__ . '/../db.php';
|
||
|
||
// 生成ID
|
||
function generateId() {
|
||
return substr(md5(uniqid(mt_rand(), true)), 0, 13);
|
||
}
|
||
|
||
// 获取当前时间戳
|
||
function getCurrentTimestamp() {
|
||
return time();
|
||
}
|
||
|
||
// 生成随机验证码
|
||
function generateVerificationCode() {
|
||
return substr(md5(uniqid(mt_rand(), true)), 0, 32);
|
||
}
|
||
|
||
// 注册新用户
|
||
function register($username, $password, $email) {
|
||
$db = Database::getInstance();
|
||
|
||
// 检查用户名是否已存在
|
||
$result = $db->query("SELECT * FROM users WHERE username = :username", ['username' => $username]);
|
||
if (!empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
// 检查邮箱是否已存在
|
||
$result = $db->query("SELECT * FROM users WHERE email = :email", ['email' => $email]);
|
||
if (!empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
// 检查用户数量,第一个用户设为管理员
|
||
$userCount = $db->query("SELECT COUNT(*) as count FROM users");
|
||
$isAdmin = empty($userCount) || $userCount[0]['count'] == 0 ? 1 : 0;
|
||
|
||
// 生成验证码
|
||
$verificationCode = generateVerificationCode();
|
||
|
||
// 创建新用户
|
||
$newUser = [
|
||
'id' => generateId(),
|
||
'username' => $username,
|
||
'email' => $email,
|
||
'password' => password_hash($password, PASSWORD_DEFAULT),
|
||
'created_at' => getCurrentTimestamp(),
|
||
'last_login' => getCurrentTimestamp(),
|
||
'online' => 1,
|
||
'is_admin' => $isAdmin,
|
||
'is_banned' => 0,
|
||
'email_verified' => 0,
|
||
'verification_code' => $verificationCode
|
||
];
|
||
|
||
// 插入新用户
|
||
$sql = "INSERT INTO users (id, username, email, password, created_at, last_login, online, avatar, is_admin, is_banned, email_verified, verification_code)
|
||
VALUES (:id, :username, :email, :password, :created_at, :last_login, :online, '', :is_admin, :is_banned, :email_verified, :verification_code)";
|
||
|
||
$db->execute($sql, $newUser);
|
||
|
||
// 发送验证邮件
|
||
sendVerificationEmail($email, $verificationCode, $username);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 用户登录
|
||
function login($username, $password, $rememberMe = false) {
|
||
$db = Database::getInstance();
|
||
|
||
// 获取用户
|
||
$result = $db->query("SELECT * FROM users WHERE username = :username", ['username' => $username]);
|
||
if (empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
$user = $result[0];
|
||
|
||
// 检查用户是否被封禁
|
||
if ($user['is_banned'] === 1) {
|
||
return false;
|
||
}
|
||
|
||
// 验证密码
|
||
// 支持两种验证方式:
|
||
// 1. 直接验证(原始密码)- 使用 password_verify
|
||
// 2. SHA-256 哈希验证(前端已加密)- 检查是否是64位十六进制字符串
|
||
$passwordVerified = false;
|
||
|
||
// 检查密码是否是 SHA-256 哈希格式(64个十六进制字符)
|
||
$isSha256 = (strlen($password) === 64 && ctype_xdigit($password));
|
||
|
||
// 方案1:如果是 SHA-256 格式,直接比较(数据库存储的是 SHA-256 哈希)
|
||
if ($isSha256 && $user['password'] === $password) {
|
||
$passwordVerified = true;
|
||
}
|
||
|
||
// 方案2:尝试传统的 password_verify(兼容旧用户)
|
||
if (!$passwordVerified && password_verify($password, $user['password'])) {
|
||
$passwordVerified = true;
|
||
}
|
||
|
||
// 方案3:如果是 SHA-256,尝试用它来验证 bcrypt(新用户注册时使用 SHA-256 的 bcrypt)
|
||
if (!$passwordVerified && $isSha256) {
|
||
// 尝试用 SHA-256 哈希去匹配 bcrypt
|
||
if (password_verify($password, $user['password'])) {
|
||
$passwordVerified = true;
|
||
}
|
||
}
|
||
|
||
if (!$passwordVerified) {
|
||
return false;
|
||
}
|
||
|
||
// 获取用户真实IP
|
||
function getRealIP() {
|
||
$ip = $_SERVER['REMOTE_ADDR'];
|
||
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
|
||
$ip = trim($ips[0]);
|
||
}
|
||
return $ip;
|
||
}
|
||
|
||
// 更新用户在线状态、最后登录时间和IP地址
|
||
$sql = "UPDATE users SET online = 1, last_login = :last_login, last_ip = :last_ip WHERE id = :id";
|
||
$params = [
|
||
'last_login' => getCurrentTimestamp(),
|
||
'last_ip' => getRealIP(),
|
||
'id' => $user['id']
|
||
];
|
||
|
||
$db->execute($sql, $params);
|
||
|
||
// 设置会话
|
||
$_SESSION['user_id'] = $user['id'];
|
||
$_SESSION['username'] = $user['username'];
|
||
|
||
// 如果用户选择"记住我",创建记住我令牌
|
||
if ($rememberMe) {
|
||
createRememberMeToken($user['id']);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// 生成记住我令牌
|
||
function createRememberMeToken($userId) {
|
||
// 生成随机令牌
|
||
$token = bin2hex(random_bytes(32));
|
||
|
||
// 设置过期时间(30天)
|
||
$expires = getCurrentTimestamp() + (30 * 24 * 60 * 60);
|
||
|
||
$db = Database::getInstance();
|
||
|
||
// 更新用户的记住我令牌
|
||
$db->execute("UPDATE users SET remember_token = :token, remember_token_expires = :expires WHERE id = :user_id", [
|
||
'token' => $token,
|
||
'expires' => $expires,
|
||
'user_id' => $userId
|
||
]);
|
||
|
||
// 设置cookie(30天过期)
|
||
setcookie('remember_token', $token, $expires, '/', '', false, true);
|
||
}
|
||
|
||
// 清除记住我令牌
|
||
function clearRememberMeToken() {
|
||
// 清除cookie
|
||
setcookie('remember_token', '', time() - 3600, '/', '', false, true);
|
||
|
||
// 如果用户已登录,清除数据库中的令牌
|
||
if (isLoggedIn()) {
|
||
$db = Database::getInstance();
|
||
$db->execute("UPDATE users SET remember_token = '', remember_token_expires = 0 WHERE id = :user_id", [
|
||
'user_id' => $_SESSION['user_id']
|
||
]);
|
||
}
|
||
}
|
||
|
||
// 通过记住我令牌自动登录
|
||
function autoLoginWithRememberToken() {
|
||
// 如果已经登录,不需要自动登录
|
||
if (isLoggedIn()) {
|
||
return true;
|
||
}
|
||
|
||
// 检查是否有记住我cookie
|
||
if (!isset($_COOKIE['remember_token'])) {
|
||
return false;
|
||
}
|
||
|
||
$token = $_COOKIE['remember_token'];
|
||
$db = Database::getInstance();
|
||
|
||
// 查询用户
|
||
$result = $db->query("SELECT * FROM users WHERE remember_token = :token AND remember_token_expires > :now", [
|
||
'token' => $token,
|
||
'now' => getCurrentTimestamp()
|
||
]);
|
||
|
||
if (empty($result)) {
|
||
// 令牌无效或过期,清除cookie
|
||
clearRememberMeToken();
|
||
return false;
|
||
}
|
||
|
||
$user = $result[0];
|
||
|
||
// 检查用户是否被封禁
|
||
if ($user['is_banned'] === 1) {
|
||
clearRememberMeToken();
|
||
return false;
|
||
}
|
||
|
||
// 设置会话
|
||
$_SESSION['user_id'] = $user['id'];
|
||
$_SESSION['username'] = $user['username'];
|
||
|
||
// 更新在线状态
|
||
$db->execute("UPDATE users SET online = 1, last_login = :last_login WHERE id = :id", [
|
||
'last_login' => getCurrentTimestamp(),
|
||
'id' => $user['id']
|
||
]);
|
||
|
||
return true;
|
||
}
|
||
|
||
// 用户登出
|
||
function logout() {
|
||
if (isLoggedIn()) {
|
||
$db = Database::getInstance();
|
||
|
||
// 更新用户在线状态
|
||
$sql = "UPDATE users SET online = 0 WHERE id = :id";
|
||
$db->execute($sql, ['id' => $_SESSION['user_id']]);
|
||
|
||
// 清除记住我令牌
|
||
clearRememberMeToken();
|
||
|
||
// 销毁会话
|
||
session_destroy();
|
||
}
|
||
}
|
||
|
||
// 检查用户是否已登录
|
||
function isLoggedIn() {
|
||
return isset($_SESSION['user_id']) && isset($_SESSION['username']);
|
||
}
|
||
|
||
// 获取当前登录用户信息
|
||
function getCurrentUser() {
|
||
if (!isLoggedIn()) {
|
||
return null;
|
||
}
|
||
|
||
return [
|
||
'id' => $_SESSION['user_id'],
|
||
'username' => $_SESSION['username']
|
||
];
|
||
}
|
||
|
||
// 更新用户在线状态
|
||
function updateUserOnlineStatus($userId, $online) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET online = :online WHERE id = :id";
|
||
$db->execute($sql, [
|
||
'online' => $online ? 1 : 0,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 获取用户在线状态
|
||
function getUserOnlineStatus($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT online FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
return $result[0]['online'] === 1;
|
||
}
|
||
|
||
// 获取用户当前头像
|
||
function getCurrentUserAvatar($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT avatar FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return '';
|
||
}
|
||
|
||
return $result[0]['avatar'] ?? '';
|
||
}
|
||
|
||
// 更新用户头像
|
||
function updateUserAvatar($userId, $avatarPath) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET avatar = :avatar WHERE id = :id";
|
||
|
||
return $db->execute($sql, [
|
||
'avatar' => $avatarPath,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 更改用户名
|
||
function changeUsername($userId, $newUsername) {
|
||
$db = Database::getInstance();
|
||
|
||
// 检查新用户名是否已被其他用户使用
|
||
$result = $db->query("SELECT * FROM users WHERE username = :username AND id != :id", [
|
||
'username' => $newUsername,
|
||
'id' => $userId
|
||
]);
|
||
|
||
if (!empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
// 更新当前用户的用户名
|
||
$sql = "UPDATE users SET username = :username WHERE id = :id";
|
||
|
||
return $db->execute($sql, [
|
||
'username' => $newUsername,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 根据用户名获取用户
|
||
function getUserByUsername($username) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT * FROM users WHERE username = :username", ['username' => $username]);
|
||
|
||
return !empty($result) ? $result[0] : false;
|
||
}
|
||
|
||
// 根据ID获取用户
|
||
function getUserById($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT * FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
return !empty($result) ? $result[0] : false;
|
||
}
|
||
|
||
// 获取所有用户
|
||
function getAllUsers() {
|
||
$db = Database::getInstance();
|
||
return $db->query("SELECT * FROM users");
|
||
}
|
||
|
||
// 检查用户是否是管理员
|
||
function isAdmin($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT is_admin FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
return $result[0]['is_admin'] === 1;
|
||
}
|
||
|
||
// 检查用户是否被封禁
|
||
function isBanned($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT is_banned FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
return $result[0]['is_banned'] === 1;
|
||
}
|
||
|
||
// 封禁用户
|
||
function banUser($userId) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET is_banned = 1 WHERE id = :id";
|
||
return $db->execute($sql, ['id' => $userId]);
|
||
}
|
||
|
||
// 解除用户封禁
|
||
function unbanUser($userId) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET is_banned = 0 WHERE id = :id";
|
||
return $db->execute($sql, ['id' => $userId]);
|
||
}
|
||
|
||
// 修改用户密码
|
||
function changeUserPassword($userId, $newPassword) {
|
||
$db = Database::getInstance();
|
||
$hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);
|
||
$sql = "UPDATE users SET password = :password WHERE id = :id";
|
||
return $db->execute($sql, [
|
||
'password' => $hashedPassword,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 修改用户简介
|
||
function changeUserBio($userId, $newBio) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET bio = :bio WHERE id = :id";
|
||
return $db->execute($sql, [
|
||
'bio' => $newBio,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 设置用户管理员权限
|
||
function setAdmin($userId, $isAdmin) {
|
||
$db = Database::getInstance();
|
||
$sql = "UPDATE users SET is_admin = :is_admin WHERE id = :id";
|
||
return $db->execute($sql, [
|
||
'is_admin' => $isAdmin ? 1 : 0,
|
||
'id' => $userId
|
||
]);
|
||
}
|
||
|
||
// 记录邮箱操作日志
|
||
function logEmailOperation($operation, $userId, $email, $details = '') {
|
||
$logMessage = date('Y-m-d H:i:s') . " - [{$operation}] User ID: {$userId}, Email: {$email}, Details: {$details}\n";
|
||
$logFile = __DIR__ . '/../logs/email_operations.log';
|
||
|
||
// 确保日志目录存在
|
||
$logDir = dirname($logFile);
|
||
if (!is_dir($logDir)) {
|
||
mkdir($logDir, 0755, true);
|
||
}
|
||
|
||
error_log($logMessage, 3, $logFile);
|
||
}
|
||
|
||
// 发送验证邮件
|
||
function sendVerificationEmail($email, $verificationCode, $username, $userId = '') {
|
||
// 引入PHPMailer
|
||
require_once __DIR__ . '/../vendor/autoload.php';
|
||
|
||
// 创建PHPMailer实例
|
||
$mail = new PHPMailer\PHPMailer\PHPMailer();
|
||
|
||
try {
|
||
// 服务器设置
|
||
$mail->isSMTP();
|
||
$mail->Host = 'smtp.qiye.163.com'; // 网易企业邮SMTP服务器
|
||
$mail->SMTPAuth = true;
|
||
$mail->Username = 'noreply@parlz.com'; // SMTP用户名
|
||
$mail->Password = '#5q8HhphvBCWr4n8'; // SMTP授权码
|
||
$mail->SMTPSecure = 'tls'; // 使用STARTTLS加密
|
||
$mail->Port = 587; // STARTTLS端口
|
||
// 设置超时时间
|
||
$mail->Timeout = 30;
|
||
// 添加SSL选项(禁用证书验证)
|
||
$mail->SMTPOptions = array(
|
||
'ssl' => array(
|
||
'verify_peer' => false,
|
||
'verify_peer_name' => false,
|
||
'allow_self_signed' => true
|
||
)
|
||
);
|
||
$mail->setLanguage('zh_CN', __DIR__ . '/../vendor/phpmailer/phpmailer/language/');
|
||
$mail->SMTPDebug = 0; // 关闭调试模式
|
||
// 发件人(必须与SMTP用户名一致)
|
||
$mail->setFrom('noreply@parlz.com', 'Parlz');
|
||
|
||
// 收件人
|
||
$mail->addAddress($email, $username);
|
||
|
||
// 邮件内容
|
||
$mail->isHTML(true);
|
||
$mail->CharSet = 'UTF-8'; // 设置字符集为UTF-8
|
||
$mail->Encoding = 'base64'; // 使用base64编码
|
||
$mail->Subject = '邮箱验证 - Parlz';
|
||
$mail->Body = "
|
||
<html>
|
||
<body style='font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif; background-color: #f5f5f5; color: #333; line-height: 1.6; margin: 0; padding: 20px;'>
|
||
<div style='max-width: 600px; margin: 0 auto; background: white; border-radius: 10px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); padding: 30px;'>
|
||
<div style='text-align: center; margin-bottom: 30px;'>
|
||
<h1 style='color: #07c160; font-size: 28px; font-weight: bold; margin: 0;'>Parlz</h1>
|
||
<p style='color: #666; margin: 10px 0 0;'>实时聊天应用</p>
|
||
</div>
|
||
|
||
<div style='border-top: 1px solid #eee; padding-top: 20px;'>
|
||
<h2 style='color: #333; font-size: 20px; margin-bottom: 20px;'>欢迎使用Parlz!</h2>
|
||
|
||
<p style='margin-bottom: 15px;'>尊敬的 {$username},</p>
|
||
|
||
<p style='margin-bottom: 20px;'>感谢您注册Parlz账号!为了确保您的账号安全并解锁全部功能,请点击下方按钮验证您的邮箱:</p>
|
||
|
||
<div style='text-align: center; margin: 30px 0;'>
|
||
<a href='https://www.parlz.com/index.php?action=verify_email&code={$verificationCode}' style='display: inline-block; background-color: #07c160; color: white; text-decoration: none; padding: 12px 30px; border-radius: 25px; font-size: 16px; font-weight: bold; transition: all 0.3s ease;'>
|
||
点击验证邮箱
|
||
</a>
|
||
</div>
|
||
|
||
<p style='margin-bottom: 15px;'>如果按钮无法点击,请复制以下链接到浏览器地址栏访问:</p>
|
||
|
||
<p style='background-color: #f8f8f8; padding: 15px; border-radius: 5px; word-break: break-all; font-family: monospace; font-size: 14px;'>
|
||
https://www.parlz.com/index.php?action=verify_email&code={$verificationCode}
|
||
</p>
|
||
|
||
<p style='margin-top: 20px;'>验证邮箱后,您将可以:</p>
|
||
<ul style='margin: 15px 0 20px 20px;'>
|
||
<li style='margin-bottom: 8px;'>添加好友</li>
|
||
<li style='margin-bottom: 8px;'>创建群组</li>
|
||
<li style='margin-bottom: 8px;'>加入群组</li>
|
||
<li style='margin-bottom: 8px;'>发送和接收消息</li>
|
||
</ul>
|
||
|
||
<p style='margin-bottom: 15px;'>如果您没有注册Parlz账号,请忽略此邮件。</p>
|
||
</div>
|
||
|
||
<div style='border-top: 1px solid #eee; margin-top: 30px; padding-top: 20px; text-align: center;'>
|
||
<p style='color: #666; font-size: 14px;'>此致,<br>Parlz团队</p>
|
||
<p style='color: #999; font-size: 12px; margin-top: 10px;'>
|
||
此邮件由系统自动发送,请勿直接回复。<br>
|
||
© 2026 Parlz. 保留所有权利。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</body>
|
||
</html>
|
||
";
|
||
|
||
// 发送邮件
|
||
$success = $mail->send();
|
||
|
||
// 检查发送结果 - 使用isError()方法更准确
|
||
if ($mail->isError()) {
|
||
throw new Exception($mail->ErrorInfo);
|
||
}
|
||
|
||
// 记录邮件发送成功日志
|
||
if (empty($userId)) {
|
||
// 尝试获取用户ID
|
||
$user = getUserByUsername($username);
|
||
if ($user) {
|
||
$userId = $user['id'];
|
||
}
|
||
}
|
||
logEmailOperation('SEND_VERIFICATION_EMAIL', $userId, $email, 'Verification code: ' . $verificationCode);
|
||
|
||
return true;
|
||
} catch (Exception $e) {
|
||
// 邮件发送失败,记录错误
|
||
$errorMessage = '邮件发送失败: ' . $e->getMessage();
|
||
error_log($errorMessage);
|
||
|
||
// 记录邮件发送失败日志
|
||
if (empty($userId)) {
|
||
// 尝试获取用户ID
|
||
$user = getUserByUsername($username);
|
||
if ($user) {
|
||
$userId = $user['id'];
|
||
}
|
||
}
|
||
logEmailOperation('SEND_VERIFICATION_EMAIL_ERROR', $userId, $email, $e->getMessage());
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 验证邮箱
|
||
function verifyEmail($verificationCode) {
|
||
$db = Database::getInstance();
|
||
|
||
// 查找验证代码对应的用户
|
||
$result = $db->query("SELECT * FROM users WHERE verification_code = :code", ['code' => $verificationCode]);
|
||
if (empty($result)) {
|
||
// 记录验证失败日志
|
||
logEmailOperation('VERIFY_EMAIL_FAILED', '', '', 'Invalid verification code: ' . $verificationCode);
|
||
return false;
|
||
}
|
||
|
||
$user = $result[0];
|
||
|
||
// 更新用户邮箱验证状态
|
||
$sql = "UPDATE users SET email_verified = 1, verification_code = '' WHERE id = :id";
|
||
$success = $db->execute($sql, ['id' => $user['id']]);
|
||
|
||
// 记录验证结果日志
|
||
if ($success) {
|
||
logEmailOperation('VERIFY_EMAIL_SUCCESS', $user['id'], $user['email'], 'Verification code: ' . $verificationCode);
|
||
} else {
|
||
logEmailOperation('VERIFY_EMAIL_ERROR', $user['id'], $user['email'], 'Failed to update verification status');
|
||
}
|
||
|
||
return $success;
|
||
}
|
||
|
||
// 检查用户邮箱是否已验证
|
||
function isEmailVerified($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT email_verified FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return false;
|
||
}
|
||
|
||
return $result[0]['email_verified'] == 1;
|
||
}
|
||
|
||
// 获取用户邮箱
|
||
function getUserEmail($userId) {
|
||
$db = Database::getInstance();
|
||
$result = $db->query("SELECT email FROM users WHERE id = :id", ['id' => $userId]);
|
||
|
||
if (empty($result)) {
|
||
return '';
|
||
}
|
||
|
||
return $result[0]['email'];
|
||
}
|
||
|
||
// 更新用户邮箱
|
||
function updateUserEmail($userId, $email) {
|
||
$db = Database::getInstance();
|
||
|
||
// 检查邮箱是否已被其他用户使用
|
||
$result = $db->query("SELECT * FROM users WHERE email = :email AND id != :id", [
|
||
'email' => $email,
|
||
'id' => $userId
|
||
]);
|
||
|
||
if (!empty($result)) {
|
||
// 记录邮箱更新失败日志
|
||
logEmailOperation('UPDATE_EMAIL_FAILED', $userId, $email, 'Email already in use');
|
||
return false;
|
||
}
|
||
|
||
// 生成新的验证码
|
||
$verificationCode = generateVerificationCode();
|
||
|
||
// 更新用户邮箱和验证码
|
||
$sql = "UPDATE users SET email = :email, email_verified = 0, verification_code = :code WHERE id = :id";
|
||
$result = $db->execute($sql, [
|
||
'email' => $email,
|
||
'code' => $verificationCode,
|
||
'id' => $userId
|
||
]);
|
||
|
||
// 记录邮箱更新结果日志
|
||
if ($result) {
|
||
logEmailOperation('UPDATE_EMAIL_SUCCESS', $userId, $email, 'New verification code generated');
|
||
|
||
// 发送验证邮件(非阻塞,通过设置超时)
|
||
$user = getUserById($userId);
|
||
if ($user) {
|
||
$emailSent = sendVerificationEmail($email, $verificationCode, $user['username'], $userId);
|
||
} else {
|
||
// 即使获取用户信息失败,也尝试发送邮件
|
||
$emailSent = sendVerificationEmail($email, $verificationCode, 'User', $userId);
|
||
// 记录警告日志
|
||
logEmailOperation('UPDATE_EMAIL_WARNING', $userId, $email, 'Failed to get user info, but email sent with default username');
|
||
}
|
||
|
||
// 如果邮件发送失败,返回false
|
||
if (!$emailSent) {
|
||
logEmailOperation('UPDATE_EMAIL_EMAIL_FAILED', $userId, $email, 'Failed to send verification email');
|
||
return false;
|
||
}
|
||
} else {
|
||
logEmailOperation('UPDATE_EMAIL_ERROR', $userId, $email, 'Failed to update email in database');
|
||
}
|
||
|
||
return $result;
|
||
}
|
||
?>
|