明月当天,不知道你有没有思念的人
前言之前其实已经写过SpringBoot异步发送邮件,但是今天在一个小项目中要用到发送邮件时,我突然觉得邮件发送人只有一个,并且固定写在yml文件中,就是非常的不妥当,就想着怎么整成一个动态的。
在写之前已经翻过很多博客了,该踩的坑都踩的差不多了,我是实现之后写的文章,有问题大家可以一起交流。
小声bb(对于CSDN我真的逐渐变得麻木了,简称CV大法现场,虽然我本人也是CSDN的一名小小博主,也是资深用户,对于文章的这块很多时候真的没法说,除了能说加油也没有了吧)。
于是就有了下面这篇文章啦....
一、需求分析默认大家都已经会 SpringBoot 集成 邮件发送啦哈,不行的,点一下上文的链接啦。
我先说说我想要达到什么样的效果:
邮件发送人可以是多个,yml文件中是兜底配置(即数据库中没有一个可用时,使用yml文件中配置的邮件发送人)
项目启动后,我也可以临时增加邮件发送人,或者禁用掉某个邮件发送人(操作完也无需重启项目即可生效)
发送邮件内容为html;另外异步发送邮件(可有可无,大家都会)
思路其实蛮简单的,就只要做到每次我们新添加或者修改邮件发送人配置的时候,对JavaSendMailImpl这个类重新初始化即可。这个地方没啥可讲的,就是不让框架给我们自动配置,我们手动来即可。
二、详细步骤 2.1、编码1)yml配置文件
spring: mail: host: smtp.163.com username: nxxxxxx@163.com password: IXXXXXXXXXN(开启允许第三方登录后的授权码) default-encoding: utf-8 protocol: smtps properties: mail: smtp: port: 465 auth: true starttls: enable: true required: true注意:关于邮件的协议protocol:smtps的配置,我最开始也是配置的smtp,我当时报的错误是一个no provider for smtp错误,我之前也写过一直用的是这个smtp协议,但是报了这个错误,我就去搜索,然后找到有篇博客说,
SMTPS协议
SMTPS (SMTP-over-SSL)是SMTP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPS和SMTP协议一样,也是用来发送邮件的,只是更安全些,防止邮件被黑客截取泄密,还可实现邮件发送者抗抵赖功能。防止发送者发送之后删除已发邮件,拒不承认发送过这样一份邮件。端口465和587便是基于SMTPS协议开放的。
465端口(SMTPS)︰它是SMTPS协议服务所使用的其中一个端口,它在邮件的传输过程中是加密传输(SSL/TLS)的,相比于SMTP协议攻击者无法获得邮件内容,邮件在一开始就被保护了起来。
所以实际上我们使用的配置应该是stmps。
另外建个properties资源类 与 配置文件一一对应
/** * @author crush */ @Data @Component @ConfigurationProperties(prefix = "spring.mail") public class MailProperties { /** * 用户名 */ private String username; /** * 授权码 */ private String password; /** * host */ private String host; /** * 端口 */ private Integer port; /*** 协议 */ private String protocol; /** * 默认编码*/ private String defaultEncoding; } 2.2、建表根据yml文件,我们大致知道了要建立张什么样的数据表了哈。
这些大家都可以自定义哈,根据自己需求来建哈。
根据数据表建一个pojo类。
/** * @Author: crush * @Date: 2021-11-26 18:28 * version 1.0 */ @Data @Accessors(chain = true) @TableName("tb_email") public class MailPO { private String emailHost; private String emailUsername; private String emailPassword; private Integer emailPort=465; /** * 协议 */ private String protocol="smtps"; /** * 默认编码 */ private String defaultEncoding="utf-8"; /** * 使用状态,1:正在使用,2:禁用,3:停用 * TODO 后期应该更改为 枚举类来进行实现 */ private Integer state=1; /** * 创建时间 */ @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; /*** 修改时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; }如果不是用mybatis-plus 可以把创建时间和修改时间去掉@TableField(fill = FieldFill.INSERT)是Mybatis-plus中的注解。另外我主键是设置了自增,所以就空了。至于返回的类我用的vo包下的。
2.3、mapper、service层 @Repository public interface MailMapper extends BaseMapper<MailPO> { }service
/** * @Author: crush * @Date: 2021-11-26 15:55 * version 1.0 */ public interface MailService { void send(MailDTO mailDTO); boolean addMailPerson(MailPO mailPO); }impl
import cn.hutool.core.util.IdUtil; /** * @author crush * 邮箱发送实现类 */ @Service public class MailServiceImpl implements MailService { @Autowired MailSenderConfig senderConfig; @Autowired MailProperties mailProperties; @Autowired MailMapper mailMapper; // 这里之前配置了一个线程池,上文的链接中有,就不说了哈 // @Async("taskExecutor") @Override public void send(MailDTO mailDTO) { String context = "<!DOCTYPE html>\n" + "<html lang=http://www.likecs.com/\"en\">\n" + "\n" + "<head>\n" + " <meta charset=http://www.likecs.com/\"UTF-8\" />\n" + " <meta name=http://www.likecs.com/\"viewport\" content=http://www.likecs.com/\"width=device-width, initial-scale=1.0\" />\n" + " <title>xxxx邮件</title>\n" + " <style>\n" + " body {\n" + " margin: 0;\n" + " padding: 0;\n" + " }\n" + " \n" + " .email {\n" + " position: relative;\n" + " width: 100%;\n" + " /* background-color: rgba(0, 0, 0, 1); */\n" + " }\n" + " \n" + " .main {\n" + " left: 0;\n" + " right: 0;\n" + " margin: auto;\n" + " width: 80%;\n" + " max-width: 800px;\n" + " box-sizing: content-box;\n" + " }\n" + " \n" + " .main .title {\n" + " /* color: white; */\n" + " display: inline-flex;\n" + " align-items: center;\n" + " }\n" + " \n" + " .main .title span {\n" + " margin: 0 10px;\n" + " }\n" + " \n" + " .main table {\n" + " width: 100%;\n" + " }\n" + " \n" + " .main table tbody td {\n" + " /* background-color: white; */\n" + " padding: 20px;\n" + " text-align: left;\n" + " border-bottom: 1px solid rgb(161, 161, 161);\n" + " }\n" + " \n" + " tfoot td p {\n" + " color: rgb(161, 161, 161);\n" + " font-size: 13px;\n" + " }\n" + " \n" + " a {\n" + " color: rgb(161, 161, 161);\n" + " text-decoration: none;\n" + " }\n" + " \n" + " a:hover {\n" + " border-bottom: 1px solid rgb(161, 161, 161);\n" + " }\n" + " </style>\n" + "</head>\n" + "\n" + "<body>\n" + " <div class=http://www.likecs.com/\"email\">\n" + " <div class=http://www.likecs.com/\"main\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <td>\n" + " <h1 class=http://www.likecs.com/\"title\">\n" + " <img width=http://www.likecs.com/\"60\" src=http://www.likecs.com/\"xxxxx\" alt=http://www.likecs.com/\"http://www.likecs.com/\" />\n" + " <span>" + mailDTO.getTitle() + "</span>\n" + " </h1>\n" + " </td>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td>\n" + " " + mailDTO.getContent() + "\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " <tfoot>\n" + " <tr>\n" + " <td>\n" + " <p>邮件由系统自动发送,请勿直接回复。</p>\n" + " <p>官方网站:\n" + " <a href=http://www.likecs.com/\"https://blog.csdn.net/weixin_45821811?spm=1000.2115.3001.5343\">宁在春博客</a>\n" + " </p>\n" + " </td>\n" + " </tr>\n" + " </tfoot>\n" + " </table>\n" + " </div>\n" + " </div>\n" + "</body>\n" + "\n" + "</html>"; JavaMailSenderImpl mailSender = senderConfig.getSender(); //创建一个SimpleMailMessage对象 MimeMessage mimeMessage = mailSender.createMimeMessage(); //需要创建一个MimeMessageHelper对象,相关参数和简单邮件类似 try { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); //发件人 helper.setFrom(mailSender.getUsername()); //收件人 这个收件人可以是数组的,只是我这只需要单个 就没多做了。 helper.setTo(mailDTO.getMail()); helper.setSubject("验证码"); //将邮件内容设置为html格式 // 发送 helper.setText( context, true); mailSender.send(mimeMessage); } catch (MessagingException e) { e.printStackTrace(); } } // 添加就清空初始化的信息,重新初始化一遍即可。 @Override public boolean addMailPerson(MailPO mailPO) { if(mailMapper.insert(mailPO)>0){ senderConfig.clear(); senderConfig.buildMailSender(); return true; } return false; } }