前两天实现了一个通过邮箱找回密码的功能,今天来做一个总结:
首先,需要开启邮箱的IMAP/SMTP服务,我用的是QQ邮箱的,会获取一个IMAP/SMTP服务密码:如uudwdedzxbhmhjhb;在这个位置:
文件目录结构如下:
其中PHPMailer是php自带的发送邮件功能并封装好的代码,主要会用到src下PHPMailer.php和SMTP.php文件,这些文件在网上都是很容易找到的;
find_pwd.php是邮箱输入界面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>找回密码</title>
<link href="../bs4/css/bootstrap.min.css" rel="stylesheet">
<script src="../jquery3/jquery-3.0.0.min.js"></script>
<script src="../bs4/js/bootstrap.min.js"></script>
</head>
<body>
<form action="javascript:" method="post">
<div class="container">
<h3>找回密码</h3>
<p></p>
<div class="form-group">
<p>
<label><span style="font-size:20px;">注册邮箱:</span>
<input type="email" id="email" class="form-control" placeholder="请输入注册邮箱" maxlength=32>
<span style="font-size:5px;color:red;">请输入您注册时使用的邮箱账号,我们会发送邮件至您邮箱地址,请及时查收并修改密码!</span>
</label>
</p>
<input type="button" value="发送邮件" id="submit" class="btn btn-success">
<input type="reset" value="取消" id="reset" class="btn btn-default">
<a href="../login.php">返回登录界面</a>
</div>
</div>
</form>
</body>
<script>
$('#submit').click(function(){
email = $('#email').val();
if(email==""){
alert("请输入注册邮箱!");
}else{
if(email.match(/^\w+@\w+\.\w+$/)){
$('#submit').attr('disabled','disabled').val('提交中...').css({"cursor":"wait"});
$.ajax({
type:'post',
url:"send_email",
dataType:'json', //这里的T一定需要大写!!!
data:{'email':email},
beforeSend:function(){ //这里的S一定需要大写!!!
//alert("发送成功!");
},
success:function(data){
if(data.success==1){
$('#submit').removeAttr('disabled').val('提交').css({"cursor":"pointer"});
//alert(data.id+'--'+data.mess+'--'+data.success+'--'+data.token+'--'+data.email+'--'+data.msg+'--'+data.time);
}else{
//alert(data.id+'--'+data.mess+'--'+data.success+'--'+data.token+'--'+data.email+'--'+data.msg+'--'+data.time);
}
}
});
}else{
alert("邮箱格式有误!");
}
}
});
</script>
</html>
上面都是前端界面,通过Ajax的post提交值到后台send_email.php进行处理,其中$data是方便我测试数据是否测通用的,$url可能需要更改,用$_SERVER['REQUEST_URI']获取url地址更好,这个$url是发送到用户的邮箱中的用来修改密码的链接,对于我的require_once()的引用文件,PHPMailer.php和SMTP中的命名空间namespace需要注释掉,不然会报错;或者引用文件的路径换一下:
<?php
function getemail(){
require_once('../connectdb.php');
$email = stripslashes(trim($_POST['email']));
$sql = "select id,user,password,email from users where email='$email'";
$data = [];
if($smt=$pdo->query($sql)){
$row = $smt->fetch(PDO::FETCH_BOTH);
if($data['email'] = $row['email']){
$data['mess'] = "接受成功!";
$data['success'] = 1;
$u_id = $row['id'];
$data['id'] = $u_id;
$token = md5($u_id.$row['user'].$row['password']);
$data['token'] = $token;
$url = "http://localhost/project/interview_practice/20181017/2018101701/find_pwd/reset_pwd.php?email=".$email."&token=".$token;
$time = date('Y-m-d H:i:s');
$data['time'] = $time;
$result = sendemail($time,$email,$url);
if($result){
$msg = '系统已向您的邮箱发送了一封邮件<br/>请登录到您的邮箱及时重置您的密码!';
$update_time = time();
$sql1 = "update users set update_time='$update_time' where id='$u_id'";
$pdo->query($sql1);
}else{
$msg = $result;
}
$data['msg'] = $msg;
}else{
$data['mess'] = "接收失败!";
$data['email'] = "";
$data['id'] = "";
$data['token'] = "";
$time = date('Y-m-d H:i:s');
$data['time'] = $time;
$data['success'] = 0;
$data['msg'] = '';
}
}else{
$data['email'] = "";
$data['id'] = "";
$data['token'] = "";
$time = date('Y-m-d H:i:s');
$data['time'] = $time;
$data['mess'] = "该邮箱并未注册!";
$data['success'] = 0;
$data['msg'] = '';
}
echo json_encode($data);
}
getemail();
function sendemail($time,$email,$url){
// 引入PHPMailer的核心文件
require_once("PHPMailer/src/PHPMailer.php");
require_once("PHPMailer/src/SMTP.php");
// 实例化PHPMailer核心类
$mail = new PHPMailer();
// 是否启用smtp的debug进行调试 开发环境建议开启 生产环境注释掉即可 默认关闭debug调试模式
$mail->SMTPDebug = 1;
// 使用smtp鉴权方式发送邮件
$mail->isSMTP();
// smtp需要鉴权 这个必须是true
$mail->SMTPAuth = true;
// 链接qq域名邮箱的服务器地址
$mail->Host = 'smtp.qq.com';
// 设置使用ssl加密方式登录鉴权
$mail->SMTPSecure = 'ssl';
// 设置ssl连接smtp服务器的远程服务器端口号
$mail->Port = 465;
// 设置发送的邮件的编码
$mail->CharSet = 'UTF-8';
// 设置发件人昵称 显示在收件人邮件的发件人邮箱地址前的发件人姓名
$mail->FromName = '残阳';
// smtp登录的账号 QQ邮箱即可
$mail->Username = '1340863150@qq.com';
// smtp登录的密码 使用生成的授权码
$mail->Password = 'uudwdedzxbhmhjhb';
// 设置发件人邮箱地址 同登录账号
$mail->From = '1340863150@qq.com';
// 邮件正文是否为html编码 注意此处是一个方法
$mail->isHTML(true);
// 设置收件人邮箱地址
$mail->addAddress($email);
// 添加多个收件人 则多次调用方法即可
//$mail->addAddress('87654321@163.com');
// 添加该邮件的主题
$mail->Subject = "找回密码";
// 添加邮件正文
$mail->Body = "亲爱的".$email.":<br/>您在".$time."提交了找回密码请求。请点击下面的链接重置密码
(按钮24小时内有效)。<br/><a href='".$url."' target='_blank'>".$url."</a>";
// 为该邮件添加附件
//$mail->addAttachment('./example.pdf');
// 发送邮件 返回状态
$result = $mail->send();
return $result;
/* require_once("smtp.class.php");
$smtpserver = "smtp.qq.com"; //SMTP服务器,如smtp.163.com
$smtpserverport = 465; //SMTP服务器端口
$smtpusermail = "1340863150@qq.com"; //SMTP服务器的用户邮箱
$smtpuser = "1340863150@qq.com"; //SMTP服务器的用户帐号
$smtppass = ""; //SMTP服务器的用户密码
$smtp = new Smtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
//这里面的一个true是表示使用身份验证,否则不使用身份验证.
$emailtype = "HTML"; //信件类型,文本:text;网页:HTML
$smtpemailto = $email;
$smtpemailfrom = $smtpusermail;
$emailsubject = "Helloweba.com - 找回密码";
$emailbody = "亲爱的".$email.":<br/>您在".$time."提交了找回密码请求。请点击下面的链接重置密码
(按钮24小时内有效)。<br/><a href='".$url."' target='_blank'>".$url."</a>";
$result = $smtp->sendmail($smtpemailto, $smtpemailfrom, $emailsubject, $emailbody, $emailtype);
return $result; */
}
?>
当系统发送邮件至你邮箱之后,登录自己邮箱查看,发现一封来自系统的邮件并附上了一个链接,该链接就是上面的$url;
点击链接进行密码修改,在这个过程中,需要对链接地址进行判断reset.php:
<?php
require_once('../connectdb.php');
$token = stripslashes(trim($_GET['token']));
$email = stripslashes(trim($_GET['email']));
$sql = "select * from users where email='$email'";
$smt = $pdo->query($sql);
$row = $smt->fetch(PDO::FETCH_BOTH);
if($row){
$mt = md5($row['id'].$row['user'].$row['password']);
if($mt==$token){
if((time()-$row['update_time'])>24*60*60){
$msg = "该链接已过期!";
}else{
$msg = 1;
setcookie('email',$email,time()+3600,'/');
}
}else{
$msg = "无效的链接!";
}
}else{
$msg = "错误的链接!";
}
echo "<script>
if($msg==1){
alert('请重新设置密码!');
location='reset_pwd_ui.php';
}else{
alert($msg);
}
</script>";
?>
如果用户信息以及链接未过期,则进入reset_pwd_ui.php界面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>重置密码</title>
<link href="../bs4/css/bootstrap.min.css" rel="stylesheet">
<script src="../jquery3/jquery-3.0.0.min.js"></script>
<script src="../bs4/js/bootstrap.min.js"></script>
</head>
<body>
<form action="reset_pwd_check.php" method="post">
<div class="container">
<h4>重置密码</h4>
<p></p>
<div class="form-group">
<p>
<label>输入新密码:
<input type="password" name="password" id="password" class="form-control" placeholder="请输入新密码" maxlength=8>
</label>
</p>
<p>
<label>确认新密码:
<input type="password" name="repassword" id="repassword" class="form-control" placeholder="请确认新密码" maxlength=8>
</label>
</p>
<input type="submit" value="确认" id="submit" class="btn btn-success">
<input type="reset" value="取消" id="reset" class="btn btn-default">
<a href="../login.php">返回登录界面</a>
</div>
</div>
</form>
</body>
<script>
</script>
</html>
修改密码后,reset_pwd_check.php会对密码进行判断:
<?php
require_once('../connectdb.php');
if(isset($_POST['password']) || isset($_POST['repassword'])){
if($_POST['password']==null || $_POST['password']=='' || $_POST['repassword']==null || $_POST['repassword']==''){
echo "<script>alert('请输入密码!');location='reset_pwd_ui.php';</script>";
}else{
$password = trim($_POST['password']);
$repassword = trim($_POST['repassword']);
/* echo $_COOKIE['email']."<br>";
echo $password."<br>";
echo $repassword."<br>"; */
if($password == $repassword){
$pwd = md5($password);
$email = $_COOKIE['email'];
$time = date('Y-m-d H:i:s');
$sql = "update users set password='$pwd',reset_time='$time' where email='$email'";
if($pdo->query($sql)){
echo "<script>confirm('修改密码成功,即将跳转至登录页面!');location='../login.php'</script>";
setcookie('email','',time()-1,'/');
}else{
echo "<script>alert('修改密码失败!');location='reset_pwd_ui.php.php'</script>";
}
}else{
echo "<script>location='reset_pwd_ui.php';alert('两次输入密码不一致!');</script>";
}
}
}else{
echo "<script>alert('请输入密码!');location='reset_pwd_ui.php';</script>";
}
?>
以上就是整个邮箱找回密码功能实现的流程,核心代码都有注释,网上也有很多,我也是从别人那里看的;其次,密码判断这些还不够严谨,这需要自己想办法去涉及验证规则;我只是把这整个流程跑通了而已,更多的东西需要后面自己实现。
不忘初心,放得始终!