今天说一下这个SpringBoot多邮件源发送邮件

前言

  最近由于业务需要,需要使用邮件对用户进行通知,但是单个邮箱有发送限制,当推送量过多时,经常会出现失败,于是考虑使用多个邮箱进行发送,由于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("[email protected]");
        //邮件主题
        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()方法,等待下次发送的时候,会重新初始化配置。

结尾

  如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。

  我是不一样的科技宅,每天进步一点点,体验不一样的生活。我们下期见!

正文完