首页>>后端>>SpringBoot->SpringBoot 动态设置邮件发送人

SpringBoot 动态设置邮件发送人

时间:2023-11-30 本站 点击:0

前言

今天在一个小项目中要用到发送邮件时,我突然觉得邮件发送人只有一个,并且固定写在yml文件中,就是非常的不妥当,就想着怎么整成一个动态的。

在写之前已经翻过很多博客了,该踩的坑都踩的差不多了,我是实现之后写的文章,有问题大家可以一起交流。

于是就有了下面这篇文章啦....

一、需求分析

默认大家都已经会 SpringBoot 集成 邮件发送啦哈,不行的,点一下上文的链接啦。

我先说说我想要达到什么样的效果:

邮件发送人可以是多个,yml文件中是兜底配置(即数据库中没有一个可用时,使用yml文件中配置的邮件发送人)

项目启动后,我也可以临时增加邮件发送人,或者禁用掉某个邮件发送人(操作完也无需重启项目即可生效)

发送邮件内容为html;另外异步发送邮件(可有可无,大家都会)

思路其实蛮简单的,就只要做到每次我们新添加或者修改邮件发送人配置的时候,对JavaSendMailImpl这个类重新初始化即可。这个地方没啥可讲的,就是不让框架给我们自动配置,我们手动来即可。

二、详细步骤

2.1、编码

1)yml配置文件

spring:mail:host:smtp.163.comusername:nxxxxxx@163.compassword:IXXXXXXXXXN(开启允许第三方登录后的授权码)default-encoding:utf-8protocol:smtpsproperties:mail:smtp:port:465auth:truestarttls:enable:truerequired:true

注意:关于邮件的协议protocol:smtps的配置,我最开始也是配置的smtp,我当时报的错误是一个no provider for smtp错误,我之前也写过一直用的是这个smtp协议,但是报了这个错误,我就去搜索,然后找到有篇博客说,

SMTPS协议

SMTPS (SMTP-over-SSL)是SMTP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPSSMTP协议一样,也是用来发送邮件的,只是更安全些,防止邮件被黑客截取泄密,还可实现邮件发送者抗抵赖功能。防止发送者发送之后删除已发邮件,拒不承认发送过这样一份邮件。端口465和587便是基于SMTPS协议开放的。

465端口(SMTPS)︰它是SMTPS协议服务所使用的其中一个端口,它在邮件的传输过程中是加密传输(SSL/TLS)的,相比于SMTP协议攻击者无法获得邮件内容,邮件在一开始就被保护了起来。

所以实际上我们使用的配置应该是stmps


另外建个properties资源类 与 配置文件一一对应

/***@authorcrush*/@Data@Component@ConfigurationProperties(prefix="spring.mail")publicclassMailProperties{/***用户名*/privateStringusername;/***授权码*/privateStringpassword;/***host*/privateStringhost;/***端口*/privateIntegerport;/***协议*/privateStringprotocol;/***默认编码*/privateStringdefaultEncoding;}

2.2、建表

根据yml文件,我们大致知道了要建立张什么样的数据表了哈。

这些大家都可以自定义哈,根据自己需求来建哈。

根据数据表建一个pojo类。

/***@Author:crush*@Date:2021-11-2618:28*version1.0*/@Data@Accessors(chain=true)@TableName("tb_email")publicclassMailPO{privateStringemailHost;privateStringemailUsername;privateStringemailPassword;privateIntegeremailPort=465;/***协议*/privateStringprotocol="smtps";/***默认编码*/privateStringdefaultEncoding="utf-8";/***使用状态,1:正在使用,2:禁用,3:停用*TODO后期应该更改为枚举类来进行实现*/privateIntegerstate=1;/***创建时间*/@TableField(fill=FieldFill.INSERT)privateLocalDateTimecreateTime;/***修改时间*/@TableField(fill=FieldFill.INSERT_UPDATE)privateLocalDateTimeupdateTime;}

如果不是用mybatis-plus 可以把创建时间和修改时间去掉@TableField(fill = FieldFill.INSERT)是Mybatis-plus中的注解。另外我主键是设置了自增,所以就空了。至于返回的类我用的vo包下的。

2.3、mapper、service层

@RepositorypublicinterfaceMailMapperextendsBaseMapper<MailPO>{}

service

/***@Author:crush*@Date:2021-11-2615:55*version1.0*/publicinterfaceMailService{voidsend(MailDTOmailDTO);booleanaddMailPerson(MailPOmailPO);}

impl

importcn.hutool.core.util.IdUtil;/***@authorcrush*邮箱发送实现类*/@ServicepublicclassMailServiceImplimplementsMailService{@AutowiredMailSenderConfigsenderConfig;@AutowiredMailPropertiesmailProperties;@AutowiredMailMappermailMapper;//这里之前配置了一个线程池,上文的链接中有,就不说了哈//@Async("taskExecutor")@Overridepublicvoidsend(MailDTOmailDTO){Stringcontext="<!DOCTYPEhtml>\n"+"<htmllang=\"en\">\n"+"\n"+"<head>\n"+"<metacharset=\"UTF-8\"/>\n"+"<metaname=\"viewport\"content=\"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.titlespan{\n"+"margin:010px;\n"+"}\n"+"\n"+".maintable{\n"+"width:100%;\n"+"}\n"+"\n"+".maintabletbodytd{\n"+"/*background-color:white;*/\n"+"padding:20px;\n"+"text-align:left;\n"+"border-bottom:1pxsolidrgb(161,161,161);\n"+"}\n"+"\n"+"tfoottdp{\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:1pxsolidrgb(161,161,161);\n"+"}\n"+"</style>\n"+"</head>\n"+"\n"+"<body>\n"+"<divclass=\"email\">\n"+"<divclass=\"main\">\n"+"<table>\n"+"<thead>\n"+"<tr>\n"+"<td>\n"+"<h1class=\"title\">\n"+"<imgwidth=\"60\"src=\"xxxxx\"alt=\"\"/>\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"+"<ahref=\"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>";JavaMailSenderImplmailSender=senderConfig.getSender();//创建一个SimpleMailMessage对象MimeMessagemimeMessage=mailSender.createMimeMessage();//需要创建一个MimeMessageHelper对象,相关参数和简单邮件类似try{MimeMessageHelperhelper=newMimeMessageHelper(mimeMessage,true);//发件人helper.setFrom(mailSender.getUsername());//收件人这个收件人可以是数组的,只是我这只需要单个就没多做了。helper.setTo(mailDTO.getMail());helper.setSubject("验证码");//将邮件内容设置为html格式//发送helper.setText(context,true);mailSender.send(mimeMessage);}catch(MessagingExceptione){e.printStackTrace();}}//添加就清空初始化的信息,重新初始化一遍即可。@OverridepublicbooleanaddMailPerson(MailPOmailPO){if(mailMapper.insert(mailPO)>0){senderConfig.clear();senderConfig.buildMailSender();returntrue;}returnfalse;}}

用到的MailDto

/***@authorcrush*邮箱发送-前端传输参数*/@DatapublicclassMailDTOimplementsSerializable{/***接受邮箱账户*/privateStringmail;/***邮箱标题*/privateStringtitle;/***要发送的内容*/privateStringcontent;}

2.4、MailSenderConfig 配置类

/***@authorcrush*/@Slf4j@Component@AllArgsConstructorpublicclassMailSenderConfig{privatefinalList<JavaMailSenderImpl>senderList;privatefinalMailPropertiesmailProperties;privatefinalMailMappermailMapper;/***初始化sender*PostConstruct注解用于需要在依赖注入完成后执行任何初始化的方法。必须在类投入使用之前调用此方法*因为刚开始我觉得这种方式(@PostConstruct)不合适,就是没能做到修改了马上就能用的那种感觉。*但是后来写完才发现,其实只要每次添加新的邮件发送人时,都重新初始化一次就可以了。*后来我又用启动事件监听器。@PostConstruct后来就没去测试了。*理论添加、修改完调用这个初始化方法就可以了。*///@PostConstructpublicvoidbuildMailSender(){log.info("初始化mailSender");List<MailPO>mails=mailMapper.selectList(newQueryWrapper<MailPO>().eq("state",1));/***需求:原本就是打算做成一个动态的邮件发送人,因为如果总是用一个邮件发送验证码或者是那种打扰短信,速度一旦太过于频繁,就会造成邮件发送错误。*思路:从数据库中拿到所有可用的邮件发送人,然后封装起来,之后发送邮件时,再进行随机的选择即可。*另外一种方式就是这是动态的。*最后就是加个兜底的,如果数据库中查询不到邮件发送人,我们使用配置文件中的发送邮件的配置。*/if(mails!=null&&!mails.isEmpty()){mails.forEach(mail->{JavaMailSenderImpljavaMailSender=newJavaMailSenderImpl();javaMailSender.setDefaultEncoding(mail.getDefaultEncoding());javaMailSender.setHost(mail.getEmailHost());javaMailSender.setPort(mail.getEmailPort());javaMailSender.setProtocol(mail.getProtocol());javaMailSender.setUsername(mail.getEmailUsername());javaMailSender.setPassword(mail.getEmailPassword());//添加数据senderList.add(javaMailSender);});}else{JavaMailSenderImpljavaMailSender=newJavaMailSenderImpl();javaMailSender.setDefaultEncoding(mailProperties.getDefaultEncoding());javaMailSender.setHost(mailProperties.getHost());javaMailSender.setPort(mailProperties.getPort());javaMailSender.setProtocol(mailProperties.getProtocol());javaMailSender.setUsername(mailProperties.getUsername());javaMailSender.setPassword(mailProperties.getPassword());//添加数据senderList.add(javaMailSender);}}/***获取MailSender**@returnCustomMailSender*/publicJavaMailSenderImplgetSender(){if(senderList.isEmpty()){buildMailSender();}//随机返回一个JavaMailSenderreturnsenderList.get(newRandom().nextInt(senderList.size()));}/***清理sender*/publicvoidclear(){senderList.clear();}}

2.5、监听器

一两句没啥说的,可以直接通过idea进去看源码上的doc注解。下次再一起研究。

/***初始化操作*目前只定义了动态设置邮件发送人的操作*@Author:crush*@Date:2021-11-2619:51*version1.0*/@Slf4j@Configuration@Order(Ordered.HIGHEST_PRECEDENCE)publicclassStartListenerimplementsApplicationListener<ApplicationStartedEvent>{MailSenderConfigmailSenderConfig;publicStartListener(MailSenderConfigmailSenderConfig){this.mailSenderConfig=mailSenderConfig;}@SneakyThrows@OverridepublicvoidonApplicationEvent(@NotNullApplicationStartedEventevent){this.mailSenderConfig.buildMailSender();}}

2.6、controller

/***@Author:crush*@Date:2021-11-2616:10*version1.0*/@RestController@RequestMapping("/email")publicclassMailController{@AutowiredprivateMailServicemailService;@PostMapping("/send")publicStringsend(@RequestBodyMailDTOmailDTO){mailService.send(mailDTO);return"发送成功!!!可能会稍有延迟,请查看邮箱信息!!";}@PostMapping("/addConfig")publicStringaddMailPerson(@RequestBodyMailPOmailPO){Stringmessage=mailService.addMailPerson(mailPO)?"添加成功!!!不过,请注意:可能会有延迟":"添加失败,请稍后重试!!";returnmessage;}}

三、测试

模板大致就是如下状态吧。 具体样式大家再自己调吧 ?

是添加进去的

多点了一次哈。

我再点击发送邮件,因为是随机数的方式,我们多测试几次,总会用到这个错误的邮件发送人的,用到了就表示我们已经成功啦哈。

因为添加的随便输入的,肯定是失败的哈。但是可以确定我们用到了我们项目启动后加入的邮件发送人啦。 你们可以填入争取的试一试。

结束了结束啦。

没写小demo,没啥源码。

后语

大家一起加油!!!如若文章中有不足之处,请大家及时指出,在此郑重感谢。

纸上得来终觉浅,绝知此事要躬行。

大家好,我是博主宁在春

一名喜欢文艺却踏上编程这条道路的小青年。

希望:我们,待别日相见时,都已有所成


难得回到后端肝篇文,又拾起后端了,之后还会接着写Vue的,肯定会把专栏写完的。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/SpringBoot/4380.html