邮件发送

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 邮件发送

公众号merlinsea


发送邮件的过程

640.jpg


1、添加依赖,说明:添加完依赖以后记得刷新dependency,防止没有及时更新


!--发送邮件-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>


2、在application.xml中配置邮件信息(和application同级)


说明:对应的邮件服务器如网易邮箱要开启POP3 / SMTP服务

mail:
  host: smtp.163.com #发送邮件服务器
  username: merlinssea@163.com #发送邮件的邮箱地址
  password: PIJCHLGOSQAPDVFN #客户端授权码,不是邮箱密码,网易的是自己设置的
  from: merlinssea@163.com # 发送邮件的地址,和上面username一致
  properties.mail.smtp.starttls.enable: true
  properties.mail.smtp.starttls.required: true
  properties.mail.smtp.ssl.enable: true
  default-encoding: utf-8


3、编写业务类MailServicceImpl


@Service
@Slf4j
public class MailServiceImpl implements MailService {
    /**
     *  springboot 提供的一个发送邮件的简单抽象,直接注入即可
     */
    @Autowired
    private JavaMailSender mailSender;
    /**
     * 从application.yml中读取 merlinssea@163.com
     */
    @Value("${spring.mail.from}")
    private String from;
    /**
     * 发送邮件
     * @param to 收件人
     * @param subject 主题
     * @param content 内容
     */
    @Override
    public void sendMail(String to, String subject, String content) {
        //创建一个邮箱消息对象
        SimpleMailMessage message = new SimpleMailMessage();
        //配置邮箱发送人
        message.setFrom(from);
        //邮件的收件人
        message.setTo(to);
        //邮件的主题
        message.setSubject(subject);
        //邮件的内容
        message.setText(content);
        mailSender.send(message);
        log.info("邮件发送成功:{}",message.toString());
    }
}


4、编写NotifyServiceImpl类,只负责发送邮件验证码,如果上一次发送的验证码在60s内,那么就是重复发送,拒绝本次发送。方法:value拼接时间戳


@Service
@Slf4j
public class NotifyServiceImpl implements NotifyService {
    @Autowired
    private MailService mailService;
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 验证码的标题
     */
    private static final String SUBJECT= "lianglin 验证码";
    /**
     * 验证码的内容
     */
    private static final String CONTENT= "您的验证码是%s,有效时间是60秒";
    /**
     * 如果用户重复发送验证码,那么先判别之前60s没是否发送过验证码,发送过则拒绝发送,否则发送
     * 方法:在把验证码存入redis之前拼接时间戳   即:code_时间戳
     * @param sendCodeEnum
     * @param to
     * @return
     */
    @Override
    public JsonData sendCode(SendCodeEnum sendCodeEnum, String to) {
        String cacheKey = String.format(CacheKey.CHECK_CODE_KEY,sendCodeEnum.name(),to);
        String cacheValue = (String) redisTemplate.opsForValue().get(cacheKey);
        //如果不为空,则判断是否60秒内重复发送
        if(StringUtils.isNotBlank(cacheValue)){
            long ttl = Long.parseLong(cacheValue.split("_")[1]);
            //当前时间戳-验证码发送时间戳,如果小于60秒,则不给重复发送
            if(CommonUtil.getCurrentTimestamp() - ttl < 1000*60){
                log.info("重复发送验证码,时间间隔:{} 秒",(CommonUtil.getCurrentTimestamp()-ttl)/1000);
                return JsonData.buildResult(BizCodeEnum.CODE_LIMITED);
            }
        }
        String code = CommonUtil.getRandomCode(6);
        //通过对value拼接时间戳的f方法,可以避免在小范围时间内重复发送
        String value = code+"_"+CommonUtil.getCurrentTimestamp();
        if(CheckUtil.isEmail(to)){
            /**
             * 这里的code是自己生成的,和之前的图形验证码无关,只有图形验证码通过了,才会调用这个验证码
             */
           //后续这个code验证码还得存redis中
            mailService.sendMail(to,SUBJECT, String.format(CONTENT, value));
            return JsonData.buildSuccess();
        }else if(CheckUtil.isPhone(to)){
            //手机号发送手机验证码
            //TODO
        }
        return JsonData.buildResult(BizCodeEnum.CODE_TO_ERROR);
    }
}


3、编写NotifyController对外api接口[通过第一步可以提高被薅羊毛的成本]


   1、先匹配用户发来的图形验证码和redis中存的图形验证码是否一致

   2、再调用发送邮件验证码服务


/**
 * 发送邮箱验证码
 * 1、首先匹配图形验证码是否正常
 * 2、再发送邮箱验证码
 *
 * @param to      接收方邮箱
 * @param captcha 接收方输入的图形验证码
 * @param request
 * @return
 */
@ApiOperation("获取邮件注册验证码")
@GetMapping("send_code")
public JsonData sendRegisterCode(@RequestParam(value = "to", required = true) String to,
                                 @RequestParam(value = "captcha", required = true) String captcha,
                                 HttpServletRequest request) {
    String cacheKey = getCaptchaKey(request);//根据用户的request获取缓存key
    String cacheCaptcha = redisTemplate.opsForValue().get(cacheKey);
    if (captcha != null && cacheCaptcha != null && captcha.equalsIgnoreCase(cacheCaptcha)) {
        //图形验证码通过,发送邮件
        redisTemplate.delete(cacheKey);
        JsonData jsonData = notifyService.sendCode(SendCodeEnum.USER_REGISTER, to);
        return jsonData;
    } else {
        //图形验证码没通过
        return JsonData.buildResult(BizCodeEnum.CODE_CAPTCHA_ERROR);
    }
}


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
数据安全/隐私保护
邮件发送的原理,如何进行邮件发送
邮件发送的原理,如何进行邮件发送
|
2月前
|
搜索推荐 Go 网络安全
超详细的邮件发送,值得收藏分享
超详细的邮件发送,值得收藏分享
41 0
|
数据安全/隐私保护
使用MailUtils发送邮件
使用MailUtils发送邮件
|
存储 网络协议 数据安全/隐私保护
基于163邮箱实现的邮件发送功能
基于163邮箱实现的邮件发送功能
436 0
基于163邮箱实现的邮件发送功能
|
网络协议 安全
调用邮件服务器进行发邮件
业务部门需求,要求阿里云上的服务器通过TCP 25端口进行外部邮件的发送
791 0
调用邮件服务器进行发邮件
|
存储 Java Spring
发送邮件那些事
邮件历史 世界的第一封电子邮件 1969年10月世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短消息。 据《互联网周刊》报道世界上的第一封电子邮件是由计算机科学家Leonard K.教授发给他的同事的一条简短消息(时间应该是1969年10月),这条消息只有两个字母:"LO"。
2499 0
|
测试技术 网络安全 C#