Bootstrap

使用java程序实现发送邮箱验证码并进行邮箱注册

        首先我们来理一下思路,发送验证码的整个过程,前端输入邮箱账号,点击获取验证码,请求后台接口,由我们的后台java程序将验证码存储在redis并设置相应的过期时间,以及实现发送验证码到邮箱的功能,用户如果填写的自己的邮箱,就能成功获取验证码,进行注册的时候,获取用户输入邮箱对应的验证码与用户输入的验证码进行匹配,匹配成功就进行注册,否则就提示验证码无效。

接下来创建一个springboot项目,这里不多赘述。

要使用邮件服务还需要集成一下相关依赖

在pom.xml文件里添加相关依赖

<dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-email</artifactId>
            <version>1.5</version>
</dependency>
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.7.4</version>
</dependency>

因为需要将验证码需要具有时效性,我们将其保存在redis中,配置RedisTemplate

import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
​
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}
​

进行redis相关配置

spring:
  redis:
    database: 0
    host: localhost
    password:
    port: 6379

接下来编写我们的邮件发送工具类

import org.springframework.stereotype.Component;
​
import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
​
@Component
public class SendMailUtil  {
    
    /**
     * 验证邮箱格式
     * @param email
     * @return
     */
    public  boolean isEmail(String email) {
        if (email == null || email.length() < 1 || email.length() > 256) {
            return false;
        }
        Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        return pattern.matcher(email).matches();
    }
​
    /**
     * 发送验证码(可以根据需求更改相应参数)
     * @param sender    发送人的邮箱
     * @param pwd          邮箱授权码
     * @param receiver      收件人
     * @param code          验证码
     * @return
     */
    public String sendEmail(String sender, String pwd, String receiver, String code){
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "smtp");       //使用smpt的邮件传输协议
        props.setProperty("mail.smtp.host", "smtpout.secureserver.net");        //主机地址
        props.setProperty("mail.smtp.auth", "true");        //授权通过
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
​
        Session session = Session.getInstance(props);
​
        try {
            MimeMessage message = new MimeMessage(session);
            // 第二个参数可不填
            message.setFrom(new InternetAddress(sender,"sender"));      //设置发件人
            message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recevier,"用户","utf-8"));     //设置收件人
            message.setSubject("verification code");        //设置主题
            message.setSentDate(new Date());
​
            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:bold;'>Dear :"+receiver+"</p>"
                    + "<p style='text-indent:2em; font-size: 20px;'>Your verification code this time is "
                    + "<span style='font-size:30px;font-weight:bold;color:red'>" + code + "</span>,Valid within 60 SECONDS, please use as soon as possible! If not operated by yourself, please ignore!</p>"
                    + "<p style='text-align:right; padding-right: 20px;'"
                    + "<a href='http://120.79.29.170' style='font-size: 18px'>aof labs</a></p>"
                    + "<span style='font-size: 18px; float:right; margin-right: 60px;'>" + sdf.format(new Date()) + "</span></body></html>";
​
            Multipart mul=new MimeMultipart();  //新建一个MimeMultipart对象来存放多个BodyPart对象
            BodyPart mdp=new MimeBodyPart();  //新建一个存放信件内容的BodyPart对象
            mdp.setContent(str, "text/html;charset=utf-8");
            mul.addBodyPart(mdp);  //将含有信件内容的BodyPart加入到MimeMultipart对象中
            message.setContent(mul); //把mul作为消息内容
​
​
            message.saveChanges();
​
            //创建一个传输对象
            Transport transport=session.getTransport("smtp");
​
​
            //建立与服务器的链接  465端口是 SSL传输
            transport.connect("smtpout.secureserver.net", 465, sender, pwd);
​
            //发送邮件
            transport.sendMessage(message,message.getAllRecipients());
​
            //关闭邮件传输
            transport.close();
            return "验证码发送成功";
​
        } catch (MessagingException | UnsupportedEncodingException e) {
            e.printStackTrace();
            return "验证码发送失败";
        }
    }
    /**生成随机的六位验证码*/
    public StringBuilder CreateCode() {
        String dates = "0123456789";
        StringBuilder code = new StringBuilder();
        Random r = new Random();
        for (int i = 0; i < 6; i++) {
            int index = r.nextInt(dates.length());
            char c = dates.charAt(index);
            code.append(c);
        }
        return code;
    }
}
​
​

接下来编写我们的接口类(这里我为了图方便直接将业务代码直接将业务代码写在了controller中,规范写法应该是写在servicer层)

@CrossOrigin
@RestController
@RequestMapping("user")
@Api(tags = "userController")
public class UserController {

    @Autowired
    private UserMapper userMapper
    
    @Autowired
    private RedisTemplate redisTemplate;
​
    public SaResult getCode(String receiver){
        LambdaQueryWrapper<user> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(user::getEmail,email);
        User user= userMapper.selectOne(queryWrapper);
        // 首先判断邮箱是否已经注册,已经注册则提示已经注册过了,未注册则继续
        if (null != user){
            return SaResult.error("此邮箱已经注册过了");
        }
        // 定义返回消息
        String message;
        try {
            SendMailUtil sendMailUtil = new SendMailUtil();
            //判断邮箱格式是否正确
            if (sendMailUtil.isEmail(email)) {
                // 工具类生成6位随机码
                StringBuilder code = sendMailUtil.CreateCode();
                ValueOperations<String, String> operations = redisTemplate.opsForValue();
                // 如果redis的验证码还存在则提示
                if (operations.get(email) != null) {
                    message = "验证码已发送,请60秒后重试";
                } else {
                    operations.set(email, String.valueOf(code));
                    // 设置验证码过期时间,可以根据需求调整
                    redisTemplate.expire(email, 60, TimeUnit.SECONDS);
                    // 这里填写发送验证码的邮箱账号及授权码
                    message = sendMailUtil.sendEmail("", "", receiver, String.valueOf(code));
                }
            } else {
                message = "邮箱格式不正确";
            }
        } catch (Exception e) {
            e.printStackTrace();
            message = "出现未知错误";
        }
        return SaResult.data(message);
    }
​
​
    // 邮箱注册
    @PostMapping("emailRegister")
    @Transactional(rollbackFor = Exception.class)
    public SaResult emailRegister(String email, String password, String verifacationCode) {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        // 获取redis中的验证码
        String code = operations.get(email);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        User user= userMapper.selectOne(queryWrapper);
        if (user!= null) {
            return SaResult.error("邮箱已经注册");
        } else {
            // 如果验证码正确
            if (null != code && code.equals(verifacationCode)){
                // 进行正常注册流程
                
                // 删除验证码,保证验证码智能使用一次
                redisTemplate.del(email);
                return SaResult.ok();
            }else {
                return SaResult.error("验证码无效,请重新获取");
            }
        }
    }
}

以上就是使用java程序实现发送邮箱验证码并进行邮箱注册的相关代码。

;