在日常生活中,邮件已经被聊天软件、短信等更便捷的信息传送方式代替。但在日常工作中,我们的重要的信息通知等非常有必要去归档追溯,那么邮件就是不可或缺的信息传送渠道。对于我们工作中经常用到的系统,里面也基本都集成了邮件发送功能。
SpringBoot提供了基于JavaMail的starter,我们只要按照官方的说明配置邮件服务器信息,即可使我们的系统拥有发送电子邮件的功能。但是,在我们GitEgg开发框架的实际业务开发过程中,有两个问题需要解决:一个是SpringBoot邮箱服务器的配置是配置在配置文件中的,不支持灵活的界面配置。另外一个是我们的开发框架需要支持多租户,那么此时需要对SpringBoot提供的邮件发送功能进行扩展,以满足我们的需求。
那么,基于以上需求和问题,我们对GitEgg框架进行扩展,增加以下功能:
1、扩展系统配置:将邮箱服务器的配置信息持久化到数据库、Redis缓存,和配置文件一起使用,制定读取优先级。
2、扩展多租户配置:如果系统开启了多租户功能,那么在邮件发送时,首先读取租户的当前配置,如果没有配置,那么在读取系统配置。
3、自有选择服务器:用户可在系统界面上选择指定的邮箱服务器进行邮件发送。
4、提供邮件发送模板:用户可选择预先制定的邮件模板进行发送特定邮件。
5、增加发送数量、频率限制:增加配置,限制模板邮件的发送数量和频率。
6、保存邮件发送记录:不一定把所有附件都保存,只需保存邮件发送关键信息,如果需要保存所有附件等需要自己扩展。
同一个租户可以配置多个电子邮件服务器,但只可以设置一个服务器为启用状态。默认情况下,系统通知类的功能只使用启用状态的服务器进行邮件发送。在有定制化需求的情况下,比如从页面直接指定某个服务器进行邮件发送,那么提供可以选择的接口,指定某个服务器进行邮件发送。
一、集成spring-boot-starter-mail扩展基础邮件发送功能
1、在基础框架gitegg-platform中新建gitegg-platform-mail子项目,引入邮件必需的相关依赖包。
<dependencies>
<!-- gitegg Spring Boot自定义及扩展 -->
<dependency>
<groupId>com.gitegg.platform</groupId>
<artifactId>gitegg-platform-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<!-- 去除springboot默认的logback配置-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
2、扩展邮件服务器配置类,增加租户等信息,方便从缓存读取到信息之后进行配置转换。
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class GitEggMailProperties extends MailProperties {
/**
* 配置id
*/
private Long id;
/**
* 租户id
*/
private Long tenantId;
/**
* 渠道id
*/
private String channelCode;
/**
* 状态
*/
private Integer channelStatus;
/**
* 配置的md5值
*/
private String md5;
}
3、扩展邮件发送实现类JavaMailSenderImpl,添加多租户和邮箱服务器编码,便于多租户和渠道选择。
@Data
public class GitEggJavaMailSenderImpl extends JavaMailSenderImpl {
/**
* 配置id
*/
private Long id;
/**
* 租户id
*/
private Long tenantId;
/**
* 渠道编码
*/
private String channelCode;
/**
* 配置的md5值
*/
private String md5;
}
4、新建邮件发送实例工厂类JavaMailSenderFactory,在邮件发送时,根据需求生产需要的邮件发送实例。
@Slf4j
public class JavaMailSenderFactory {
private RedisTemplate redisTemplate;
private JavaMailSenderImpl javaMailSenderImpl;
/**
* 是否开启租户模式
*/
private Boolean enable;
/**
* JavaMailSender 缓存
* 尽管存在多个微服务,但是只需要在每个微服务初始化一次即可
*/
private final static Map<String, GitEggJavaMailSenderImpl> javaMailSenderMap = new ConcurrentHashMap<>();
public JavaMailSenderFactory(RedisTemplate redisTemplate, JavaMailSenderImpl javaMailSenderImpl, Boolean enable) {
this.redisTemplate = redisTemplate;
this.javaMailSenderImpl = javaMailSenderImpl;
this.enable = enable;
}
/**
* 指定邮件发送渠道
* @return
*/
public JavaMailSenderImpl getMailSender(String... channelCode){
if (null == channelCode || channelCode.length == GitEggConstant.COUNT_ZERO
|| null == channelCode[GitEggConstant.Number.ZERO])
{
return this.getDefaultMailSender();
}
// 首先判断是否开启多租户
String mailConfigKey = JavaMailConstant.MAIL_TENANT_CONFIG_KEY;
if (enable) {
mailConfigKey += GitEggAuthUtils.getTenantId();
} else {
mailConfigKey = JavaMailConstant.MAIL_