在部署到阿里云服务器上的Maven+SpringMVC项目中实现邮箱接收验证码验证功能的方法

文章首发地址:https://www.dawnsite.cn/archives/101.html
最近个人开发项目需要做一个找回密码功能,但鉴于成本,不考虑手机验证码,这里记录一下通过邮箱获取验证码来验证的开发过程

首先要实现邮箱验证验证码,无论是使用网易还是腾讯QQ邮箱还是其他邮箱,我们都需要开启POP3/SMTP服务,获取账户授权码。

一. QQ邮箱开启POP3/SMTP

首先进入邮箱主页,然后依次进入设置–账户,在账户页面下方POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务一栏开启POP3/SMTP服务,只需要开启第一个即可,然后在下方点击获取授权码就可以了,详情如下图。PS:使用QQ邮箱发送在QQ安全中心不可设置邮箱验证,另外修改密码等影响登录的行为需要重新获取授权码。
QQ邮箱POP3/STMP

二. 发送验证码的实现流程

1.在pom.xml中导入邮件发送的支持,代码如下:

    <!-- 邮件发送的支持包 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

<!-- 邮件发送 -->
<dependency>
	<groupId>javax.mail</groupId>
	<artifactId>mail</artifactId>
	<version>1.4.7</version>
</dependency>

2.在springmvc配置文件里配置发件人的账号和授权码

<!--  class:发送邮件的核心代码的位置  -->
<bean id="sendMailUtil" class="com.zjq.utils.SendMailUtil">
    <!--  给属性赋值  name:账号   pwd:授权码 -->
    <property name="sendEmail" value="你的账号"/>
    <property name="pwd" value="你的授权码"/>
</bean>

3.创建工具类实现发送邮件 SendMailUtil.java

package com.zjq.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

import javax.mail.internet.MimeMessage;

import com.sun.mail.util.MailSSLSocketFactory;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

public class SendMailUtil {
private String sendEmail;//账号
private String pwd;//授权码

public void setSendEmail(String sendEmail) {
    this.sendEmail = sendEmail;
}
public void setPwd(String pwd) {
    this.pwd = pwd;
}

/**
 * 发送html格式的邮件
 * @param receiveEmail	收件箱
 * @param name	称呼
 * @param code	验证码
 * @return
 */
public boolean sendHtmlMail(String receiveEmail,String name,String code){

    try {
        JavaMailSenderImpl senderImpl=new JavaMailSenderImpl();

        //邮箱的主机  qq邮箱是smtp.qq.com,网易是smtp.163.com
        senderImpl.setHost("smtp.qq.com");
        //编码集
        senderImpl.setDefaultEncoding("utf-8");

        //建立邮件消息,我们需要发送的是html格式邮件
        MimeMessage mimeMessage=senderImpl.createMimeMessage();
        MimeMessageHelper messageHelper=new MimeMessageHelper(mimeMessage);

        //设置收件人,寄件人
        messageHelper.setTo(receiveEmail);//收件人
        messageHelper.setFrom(sendEmail);//发件人
        messageHelper.setSubject("发送验证码");//设置邮件的主题

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");

        String str="<!DOCTYPE html><html><head><meta charset='UTF-8'></head><body>"
                +"<p style='font-size:20px;font-weight:blod;'>尊敬的"+ name +",您好</p>"
                +"<p style='text-indent:2em;font-size:20px'>欢迎使用*****,您本次的验证码是"
                +"<span style='font-size:30px; font-weight:blod; color:red;'>"+ code +"</span>"
                +",3分钟内有效,如非本人操作,请忽略此邮件。</p><p style='text-align:right; padding-right:20px;'>"
                +"<a href='https://www.ciyintang.vip' style='font-size:18px;'>Dawn博客</a></p>"
                +"<span style='font-size:18px; float:right; margin-right:60px;'>"+ sdf.format(new Date()) +"</span></body></html>";

        //设置邮件的正文
        messageHelper.setText(str,true);

        //发件箱的名称
        senderImpl.setUsername(sendEmail);
        //发件箱的密码  状态码
        senderImpl.setPassword(pwd);

        Properties prop=new Properties();

        //SSL认证(阿里云默认禁用25端口,这里开启后使用465端口)
        MailSSLSocketFactory sf = new MailSSLSocketFactory();
        sf.setTrustAllHosts(true);
        prop.put("mail.smtp.ssl.enable", "true");
        prop.put("mail.smtp.ssl.socketFactory", sf);

        prop.put("mail.smtp.auth", "true");//让服务器去认证用户名和密码
        prop.put("mail.smtp.timeout", "2500");//连接超时时间
        senderImpl.setJavaMailProperties(prop);
        senderImpl.send(mimeMessage);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }

    return false;
}
}

4.控制器代码,处理请求 SendEmailController.java

package com.zjq.controller;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zjq.utils.SendMailUtil;

@Controller
public class SendEmailController {

@Autowired
private SendMailUtil sendMailUtil;

@RequestMapping("/code")
@ResponseBody
public int sendEmail(String email, HttpSession session) {

    String code = "";
    if (session.getAttribute("email") != null) {
        if (email.equals(session.getAttribute("email").toString()) && session.getAttribute("vcode") != null) {
            code = session.getAttribute("vcode").toString();
        } else {
            //随机产生验证码
            Random rd = new Random();
            while (code.length() < 6) {
                code += rd.nextInt(10);
            }
        }
    } else if (session.getAttribute("vcode") == null && session.getAttribute("email") == null) {
        //随机产生验证码
        Random rd = new Random();
        while (code.length() < 6) {
            code += rd.nextInt(10);
        }
    } else {
        code = session.getAttribute("vcode").toString();
    }
    //如果验证码发送成功
    if (sendMailUtil.sendHtmlMail(email, "用户", code)) {
        session.setAttribute("vcode", code);
        session.setAttribute("email", email);

        //创建TimerTask用来三分钟之后移出vcode
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
                session.removeAttribute("vcode");
                session.removeAttribute("email");
            }
        };

        //实例化这个task任务
        Timer timer = new Timer();
        timer.schedule(task, 180000);//三分钟之后执行task任务
        return 1;
    }

    return 0;
}
}

5.前端请求,前端页面使用layui forgetPassword.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta http-equiv="Cache-Control" content="no-siteapp"/>
<link rel="stylesheet" href="${ctx }/layui/css/layui.css" media="all"/>
<script>
    <%--JS gloable varilible--%>
    var ctx = "${ctx}";
</script>
<style type="text/css">
    .layui-form-item .layui-inline {
        width: 33.333%;
        float: left;
        margin-right: 0;
    }

    @media ( max-width: 1240px) {
        .layui-form-item .layui-inline {
            width: 100%;
            float: none;
        }
    }
</style>
</head>
<body class="childrenBody">
<div class="layui-row" style="margin-top: 50px;">
        <form class="layui-form" style="width: 80%;" action="">
            <div class="layui-form-item">
                <label class="layui-form-label">邮箱</label>
                <div class="layui-input-block">
                    <input type="text" id="email" name="email" class="layui-input userName"
                           lay-verify="email" placeholder="请输入邮箱" value="">
                    <button style="position: absolute;top: 0;right: 0px;
cursor: pointer;" type="button" class="layui-btn layui-btn-warm" id="sendCode">点击发送验证码</button>
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">验证码</label>
                <div class="layui-input-block">
                    <input type="text" name="code" id="code" lay-verify="required" lay-reqtext="验证码不能为空" placeholder="请输入邮箱验证码" autocomplete="off" class="layui-input">
                </div>
            </div>

            <div class="layui-form-item">
                <label class="layui-form-label">密码</label>
                <div class="layui-input-block">
                    <input type="password" id="password" class="layui-input userName"
                           lay-verify="pass" placeholder="请输入密码" name="password" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <label class="layui-form-label">确认密码</label>
                <div class="layui-input-block">
                    <input type="password" class="layui-input userName"
                           lay-verify="repass" placeholder="请输入确认密码" value="">
                </div>
            </div>
            <div class="layui-form-item">
                <div class="layui-input-block">
                    <button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
                    <button type="reset" class="layui-btn layui-btn-primary">重置</button>
                </div>
            </div>
        </form>
</div>
</body>
<script src="${ctx }/layui/layui.js" type="text/javascript" charset="utf-8"> 
</script>
<script>
layui.config({
base: ctx + '/js/'
}).use([ 'jquery', 'form', 'layer'], function () {
var sliderVerify = layui.sliderVerify,
    $ = layui.jquery,
    layer = parent.layer === undefined ? layui.layer : parent.layer,
    form = layui.form;

//自定义验证规则
form.verify({
    pass: [/(.+){6,16}$/, '密码必须6到16位']
    , repass: function (value) {
        var repassvalue = $('#password').val();
        if (value != repassvalue) {
            return '两次输入的密码不一致!';
        }
    }
});
//监听提交
form.on('submit(formDemo)', function (data) {
    var index = layer.load(1, {
        shade: [0.5, '#000']
    });
    $.ajax({
        type: "post",
        async: false,
        url: ctx + "/admin/findPassword",
        data: data.field,
        dataType: "json",
        success: function (d) {
            if (d.code == 0) {
                layer.close(index);
                sessionStorage.removeItem('vcode');
                layer.msg("修改密码成功");
            } else {
                layer.close(index);
                sessionStorage.removeItem('vcode');
                layer.msg(d.msg);
            }

        },
    });
    setTimeout(function () {
        parent.location.reload();
    }, 2000);
    return false;

});

$("#sendCode").click(function () {  
    sendEmail();
    run();
    return false;
});
//发送验证码
function sendEmail() {
    //获取收件邮箱
    var email = document.getElementById('email').value;
    if (email == null || email == "") {
        return;
    }

    //发送请求
    $.post(ctx + "/code", {email: email}, function (data) {
    }, "text");
}

//邮箱验证码计时
var btn = document.getElementById('sendCode');

function run() {
    var time = 60;//定义时间变量。用于倒计时用
    var timer = null;//定义一个定时器;
    timer = setInterval(function () {///开启定时器。函数内执行
        btn.disabled = true;
        btn.innerText = time + "秒后可重新发送";    //点击发生后,按钮的文本内容变成之前定义好的时间值。
        time--;//时间值自减
        if (time == 0) {     //判断,当时间值小于等于0的时候
            btn.innerText = '点击重新发送';
            btn.disabled = false;
            clearInterval(timer); //清除定时器
        }
    }, 1000)

}
})
</script>
</html>

前端效果如图:
效果展示
邮箱收件效果如下图:
在这里插入图片描述

三. 阿里云安全组设置

手动添加安全组规则用于启用465端口,如下图:
在这里插入图片描述

四. 总结

以上就是邮箱验证的总体流程及实现,特此记录下来,希望能够帮助到看到这篇文章的你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值