1. 程式人生 > >Ajax+PHPMailer實現郵箱找回密碼功能

Ajax+PHPMailer實現郵箱找回密碼功能

       前兩天實現了一個通過郵箱找回密碼的功能,今天來做一個總結:

首先,需要開啟郵箱的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>";
}
?>

以上就是整個郵箱找回密碼功能實現的流程,核心程式碼都有註釋,網上也有很多,我也是從別人那裡看的;其次,密碼判斷這些還不夠嚴謹,這需要自己想辦法去涉及驗證規則;我只是把這整個流程跑通了而已,更多的東西需要後面自己實現。

不忘初心,放得始終!