前言
最近由于业务需要,需要使用邮件对用户进行通知,但是单个邮箱有发送限制,当推送量过多时,经常会出现失败,于是考虑使用多个邮箱进行发送,由于spring-boot-starter-mail
不支持同时配置多个邮件源,所以决定自己动手实现。
实现思路
spring-boot-starter-mail
会根据spring.mail.xxx
相关配置对JavaMailSender
进行自动配置。但是只支持单个邮箱。为了实现多邮件源,可以参照上述逻辑。在配置文件内配置好,多个邮件源。然后读取配置文件,手动对JavaMailSender
进行配置,并将其初始化完毕的JavaMailSender
存储容器内。然后发送时随机取出JavaMailSender
进行发送。
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
邮件yml配置
替换实际的邮件配置
# 配置邮件
mail:
configs:
# 账号
- username: fapiao@QQ.com
password: 123456
host: smtp.qq.com
port: 25
protocol: smtp
default-encoding: UTF-8
# 账号A
- username: fapiaoa@QQ.com
password: 123456
host: smtp.qq.com
port: 25
protocol: smtp
default-encoding: UTF-8
MailConfig
@Data
@Component
@ConfigurationProperties(prefix = "mail")
public class MailConfig {
private List<MailProperties> configs;
@Data
public static class MailProperties {
/**
* 密码
*/
private String username;
/**
* 密码
*/
private String password;
/**
* host
*/
private String host;
/**
* 端口
*/
private Integer port;
/**
* 协议
*/
private String protocol;
/**
* 默认编码
*/
private String defaultEncoding;
}
}
MailSenderConfig
@Slf4j
@Component
@AllArgsConstructor
public class MailSenderConfig {
private final MailConfig mailConfig;
private final List<JavaMailSenderImpl> senderList;
/**
* 初始化 sender
*/
@PostConstruct
public void buildMailSender(){
List<MailConfig.MailProperties> mailConfigs = mailConfig.getConfigs();
log.info("初始化mailSender");
mailConfigs.forEach(mailProperties -> {
// 邮件发送者
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
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
* @return CustomMailSender
*/
public JavaMailSenderImpl getSender(){
if(senderList.isEmpty()){
buildMailSender();
}
// 随机返回一个JavaMailSender
return senderList.get(new Random().nextInt(senderList.size()));
}
/**
* 清理 sender
*/
public void clear(){
senderList.clear();
}
}
MailService
public interface MailService {
/**
* 发送邮件
* @return 返回 true 或者 false
*/
boolean sendMail();
}
MailServiceImpl
@Service
@AllArgsConstructor
public class MailServiceImpl implements MailService {
private final MailSenderConfig senderConfig;
@Override
public boolean sendMail() {
JavaMailSenderImpl mailSender = senderConfig.getSender();
//创建SimpleMailMessage对象
SimpleMailMessage message = new SimpleMailMessage();
//邮件发送人
message.setFrom(Objects.requireNonNull(mailSender.getUsername()));
//邮件接收人
message.setTo("2583174414@qq.com");
//邮件主题
message.setSubject("测试邮件");
//邮件内容
message.setText("测试邮件内容");
//发送邮件
mailSender.send(message);
return true;
}
}
测试
@SpringBootTest
@RunWith(SpringRunner.class)
class MailServiceImplTest {
@Autowired
private MailServiceImpl mailService;
@Test
void sendMail() {
mailService.sendMail();
}
}
测试结果
注意的点
- 需要检查邮箱配置相关协议是否开启。
- 如果使用QQ邮箱进行发送,密码不是邮箱密码,而是授权码。
拓展
上述是将邮箱配置写入配置文件,在没有使用配置中心的情况下,如果邮箱源被限制,更改起来相对麻烦。可以将配置存入数据库,在启动的时候从数据库进行加载。如果邮箱源发生更改,可直接更改数据库邮箱源配置,然后调用MailSenderConfig.clear()
方法,等待下次发送的时候,会重新初始化配置。
结尾
如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。
我是不一样的科技宅,每天进步一点点,体验不一样的生活。我们下期见!