Ajax+PHPMailer實現郵箱找回密碼功能
阿新 • • 發佈:2018-12-18
前兩天實現了一個通過郵箱找回密碼的功能,今天來做一個總結:
首先,需要開啟郵箱的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(/^\
[email protected]\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 = ' [email protected]';
// smtp登入的密碼 使用生成的授權碼
$mail->Password = 'uudwdedzxbhmhjhb';
// 設定發件人郵箱地址 同登入賬號
$mail->From = '[email protected]';
// 郵件正文是否為html編碼 注意此處是一個方法
$mail->isHTML(true);
// 設定收件人郵箱地址
$mail->addAddress($email);
// 新增多個收件人 則多次呼叫方法即可
//$mail->addAddress('[email protected]');
// 新增該郵件的主題
$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 = "[email protected]"; //SMTP伺服器的使用者郵箱
$smtpuser = "[email protected]"; //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>";
}
?>
以上就是整個郵箱找回密碼功能實現的流程,核心程式碼都有註釋,網上也有很多,我也是從別人那裡看的;其次,密碼判斷這些還不夠嚴謹,這需要自己想辦法去涉及驗證規則;我只是把這整個流程跑通了而已,更多的東西需要後面自己實現。
不忘初心,放得始終!