mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	邮件模块 添加邮箱账号缓存 修改校验方式
This commit is contained in:
		@@ -57,7 +57,7 @@ public class MailAccountController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:getMailAccount 和 getMailAccountPage 这两个接口,定义一个对应的 Resp 类哈,参考别的模块。主要不要返回 password 字段。
 | 
			
		||||
    // 一个可以的做法,是 MailAccountBaseVO 不返回 password,然后 MailAccountCreateReqVO、MailAccountUpdateReqVO 添加这个字段
 | 
			
		||||
    // 一个可以的做法,是 MailAccountBaseVO 不返回 password,然后 MailAccountCreateReqVO、MailAccountUpdateReqVO 添加这个字段 DONE
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/get")
 | 
			
		||||
    @ApiOperation("获得邮箱账号")
 | 
			
		||||
@@ -76,7 +76,7 @@ public class MailAccountController {
 | 
			
		||||
        return success(MailAccountConvert.INSTANCE.convertPage(pageResult));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:getSimpleMailAccountList 单独定义一个类,只返回精简的信息,id,from 即可。像密码之类都是敏感信息,不应该返回
 | 
			
		||||
    // TODO @wangjingyi:getSimpleMailAccountList 单独定义一个类,只返回精简的信息,id,from 即可。像密码之类都是敏感信息,不应该返回 DONE
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/list-all-simple")
 | 
			
		||||
    @ApiOperation(value = "获得邮箱账号精简列表")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.mail;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.send.MailReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateBaseVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.*;
 | 
			
		||||
import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
 | 
			
		||||
@@ -29,9 +26,9 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
@RequestMapping("/system/mail-template")
 | 
			
		||||
public class MailTemplateController {
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:private
 | 
			
		||||
    // TODO @wangjingyi:private DONE
 | 
			
		||||
    @Autowired
 | 
			
		||||
    MailTemplateService mailTempleService;
 | 
			
		||||
    private MailTemplateService mailTempleService;
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/create")
 | 
			
		||||
    @ApiOperation("创建邮箱模版")
 | 
			
		||||
@@ -56,13 +53,13 @@ public class MailTemplateController {
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:下面几个 VO 也参考我在 account 给的建议
 | 
			
		||||
    // TODO @wangjingyi:下面几个 VO 也参考我在 account 给的建议 DONE RespVO中需要BaseVO 中哪些字段
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/get")
 | 
			
		||||
    @ApiOperation("获得邮箱模版")
 | 
			
		||||
    @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('system:mail-template:get')")
 | 
			
		||||
    public CommonResult<MailTemplateBaseVO> getMailTemplate(@RequestParam("id") Long id) {
 | 
			
		||||
    public CommonResult<MailTemplateRespVO> getMailTemplate(@RequestParam("id") Long id) {
 | 
			
		||||
        MailTemplateDO mailTemplateDO = mailTempleService.getMailTemplate(id);
 | 
			
		||||
        return success(MailTemplateConvert.INSTANCE.convert(mailTemplateDO));
 | 
			
		||||
    }
 | 
			
		||||
@@ -70,25 +67,17 @@ public class MailTemplateController {
 | 
			
		||||
    @GetMapping("/page")
 | 
			
		||||
    @ApiOperation("获得邮箱模版分页")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('system:mail-template:query')")
 | 
			
		||||
    public CommonResult<PageResult<MailTemplateBaseVO>> getMailTemplatePage(@Valid MailTemplatePageReqVO pageReqVO) {
 | 
			
		||||
    public CommonResult<PageResult<MailTemplateRespVO>> getMailTemplatePage(@Valid MailTemplatePageReqVO pageReqVO) {
 | 
			
		||||
        PageResult<MailTemplateDO> pageResult = mailTempleService.getMailTemplatePage(pageReqVO);
 | 
			
		||||
        return success(MailTemplateConvert.INSTANCE.convertPage(pageResult));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/list-all-simple")
 | 
			
		||||
    @ApiOperation(value = "获得邮箱模版精简列表")
 | 
			
		||||
    public CommonResult<List<MailTemplateBaseVO>> getSimpleTemplateList() {
 | 
			
		||||
    public CommonResult<List<MailTemplateRespVO>> getSimpleTemplateList() {
 | 
			
		||||
        List<MailTemplateDO> list = mailTempleService.getMailTemplateList();
 | 
			
		||||
        // 排序后,返回给前端
 | 
			
		||||
        list.sort(Comparator.comparing(MailTemplateDO::getId));
 | 
			
		||||
        return success(MailTemplateConvert.INSTANCE.convertList02(list));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/send")
 | 
			
		||||
    @ApiOperation("发送邮件")
 | 
			
		||||
    @PreAuthorize("@ss.hasPermission('system:mail-template:send')")
 | 
			
		||||
    public CommonResult<Boolean> sendMail(@Valid @RequestBody MailReqVO mailReqVO){
 | 
			
		||||
        mailTempleService.sendMail(mailReqVO);
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,6 @@ public class MailAccountBaseVO {
 | 
			
		||||
    @Email(message = "必须是Email格式")
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "密码",required = true,example = "123456")
 | 
			
		||||
    @NotNull(message = "密码必填")
 | 
			
		||||
    private String password;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "网站",required = true,example = "www.iocoder.cn")
 | 
			
		||||
    @NotNull(message = "网站必填")
 | 
			
		||||
    private String host;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,20 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
import lombok.ToString;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
 | 
			
		||||
@ApiModel("管理后台 - 邮箱账号创建 Request VO")
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@ToString(callSuper = true)
 | 
			
		||||
public class MailAccountCreateReqVO extends MailAccountBaseVO {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "密码",required = true,example = "123456")
 | 
			
		||||
    @NotNull(message = "密码必填")
 | 
			
		||||
    private String password;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,4 +18,7 @@ public class MailAccountUpdateReqVO extends MailAccountBaseVO {
 | 
			
		||||
    @NotNull(message = "编号不能为空")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "密码",required = true,example = "123456")
 | 
			
		||||
    @NotNull(message = "密码必填")
 | 
			
		||||
    private String password;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template;
 | 
			
		||||
 | 
			
		||||
public class MailTemplateRespVO extends MailTemplateBaseVO{
 | 
			
		||||
}
 | 
			
		||||
@@ -4,6 +4,7 @@ import cn.hutool.extra.mail.MailAccount;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountBaseVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
@@ -23,7 +24,7 @@ public interface MailAccountConvert {
 | 
			
		||||
 | 
			
		||||
    List<MailAccountBaseVO> convertList02(List<MailAccountDO> list);
 | 
			
		||||
 | 
			
		||||
    default MailAccount convertAccount(MailAccountDO mailAccountDO){
 | 
			
		||||
    default MailAccount convertAccount(MailSendMessage mailAccountDO){
 | 
			
		||||
        return new MailAccount()
 | 
			
		||||
                .setHost(mailAccountDO.getHost())
 | 
			
		||||
                .setPort(mailAccountDO.getPort())
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.convert.mail;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateBaseVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
@@ -14,9 +15,9 @@ public interface MailTemplateConvert {
 | 
			
		||||
 | 
			
		||||
    MailTemplateDO convert(MailTemplateBaseVO baseVO);
 | 
			
		||||
 | 
			
		||||
    MailTemplateBaseVO convert(MailTemplateDO mailTemplateDO);
 | 
			
		||||
    MailTemplateRespVO convert(MailTemplateDO mailTemplateDO);
 | 
			
		||||
 | 
			
		||||
    PageResult<MailTemplateBaseVO> convertPage(PageResult<MailTemplateDO> pageResult);
 | 
			
		||||
    PageResult<MailTemplateRespVO> convertPage(PageResult<MailTemplateDO> pageResult);
 | 
			
		||||
 | 
			
		||||
    List<MailTemplateBaseVO> convertList02(List<MailTemplateDO> list);
 | 
			
		||||
    List<MailTemplateRespVO> convertList02(List<MailTemplateDO> list);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,9 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import org.apache.ibatis.annotations.Mapper;
 | 
			
		||||
import org.apache.ibatis.annotations.Select;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface MailAccountMapper extends BaseMapperX<MailAccountDO> {
 | 
			
		||||
@@ -25,4 +28,18 @@ public interface MailAccountMapper extends BaseMapperX<MailAccountDO> {
 | 
			
		||||
        return selectOne(new QueryWrapperX<MailAccountDO>()
 | 
			
		||||
                .eqIfPresent("username" , userName));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    default MailAccountDO selectByUserNameAndId(String userName,Long id){
 | 
			
		||||
        return selectOne(new QueryWrapperX<MailAccountDO>()
 | 
			
		||||
                .eqIfPresent("username" , userName)
 | 
			
		||||
                .neIfPresent("id" , id));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    default MailAccountDO selectOneByFrom(String from){
 | 
			
		||||
        return selectOne(new QueryWrapperX<MailAccountDO>()
 | 
			
		||||
                .eqIfPresent("from" , from));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    @Select("SELECT COUNT(*) FROM system_mail_account WHERE update_time > #{maxUpdateTime}")
 | 
			
		||||
    Long selectCountByUpdateTimeGt(Date maxUpdateTime);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> {
 | 
			
		||||
                .eqIfPresent("code" , code));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    @Select("SELECT id FROM system_mail_template WHERE update_time > #{maxUpdateTime} LIMIT 1")
 | 
			
		||||
    @Select("SELECT COUNT(*) FROM system_mail_template WHERE update_time > #{maxUpdateTime} LIMIT 1")
 | 
			
		||||
    Long selectByMaxUpdateTime(Date maxUpdateTime);
 | 
			
		||||
 | 
			
		||||
    default MailTemplateDO selectOneByAccountId(Long accountId){
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,29 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.mq.consumer.mail;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.sms.SmsTemplateRefreshMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 针对 {@link MailTemplateRefreshMessage} 的消费者
 | 
			
		||||
 *
 | 
			
		||||
 * @author wangjingyi
 | 
			
		||||
 */
 | 
			
		||||
@Component
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class MailTemplateRefreshConsumer extends AbstractChannelMessageListener<MailTemplateRefreshMessage> {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private MailTemplateService mailTemplateService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onMessage(MailTemplateRefreshMessage message) {
 | 
			
		||||
        log.info("[onMessage][收到 MailTemplate 刷新信息]");
 | 
			
		||||
        mailTemplateService.initLocalCache();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.mq.message.mail;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  邮箱账号的数据刷新 Message
 | 
			
		||||
 *
 | 
			
		||||
 * @author wangjingyi
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class MailAccountRefreshMessage extends AbstractChannelMessage {
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getChannel() {
 | 
			
		||||
        return "system.mail-account.refresh";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -27,6 +27,16 @@ public class MailSendMessage extends AbstractStreamMessage {
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "邮箱地址不能为空")
 | 
			
		||||
    private String from;
 | 
			
		||||
    /**
 | 
			
		||||
     * 用户名
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "用户名不能为空")
 | 
			
		||||
    private String username;
 | 
			
		||||
    /**
 | 
			
		||||
     * 密码
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "密码不能为空")
 | 
			
		||||
    private String password;
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱模板编号
 | 
			
		||||
     */
 | 
			
		||||
@@ -45,6 +55,20 @@ public class MailSendMessage extends AbstractStreamMessage {
 | 
			
		||||
     * 内容
 | 
			
		||||
     */
 | 
			
		||||
    private String content;
 | 
			
		||||
    /**
 | 
			
		||||
     * 主机
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "host不能为空")
 | 
			
		||||
    private String host;
 | 
			
		||||
    /**
 | 
			
		||||
     * 端口
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "端口号不能为空")
 | 
			
		||||
    private Integer port;
 | 
			
		||||
    /**
 | 
			
		||||
     * 是否开启 SSL
 | 
			
		||||
     */
 | 
			
		||||
    private Boolean sslEnable;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getStreamKey() {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,19 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.mq.message.mail;
 | 
			
		||||
 | 
			
		||||
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *  邮箱模板的数据刷新 Message
 | 
			
		||||
 *
 | 
			
		||||
 * @author wangjingyi
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
public class MailTemplateRefreshMessage extends AbstractChannelMessage {
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getChannel() {
 | 
			
		||||
        return "system.mail-template.refresh";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
 | 
			
		||||
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.sms.SmsChannelRefreshMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.message.sms.SmsTemplateRefreshMessage;
 | 
			
		||||
@@ -28,18 +30,18 @@ public class MailProducer {
 | 
			
		||||
    private RedisMQTemplate redisMQTemplate;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 发送 {@link SmsChannelRefreshMessage} 消息
 | 
			
		||||
     * 发送 {@link MailTemplateRefreshMessage} 消息
 | 
			
		||||
     */
 | 
			
		||||
    public void sendMailChannelRefreshMessage() {
 | 
			
		||||
        SmsChannelRefreshMessage message = new SmsChannelRefreshMessage();
 | 
			
		||||
    public void sendMailTemplateRefreshMessage() {
 | 
			
		||||
        MailTemplateRefreshMessage message = new MailTemplateRefreshMessage();
 | 
			
		||||
        redisMQTemplate.send(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 发送 {@link SmsTemplateRefreshMessage} 消息
 | 
			
		||||
     * 发送 {@link MailTemplateRefreshMessage} 消息
 | 
			
		||||
     */
 | 
			
		||||
    public void sendMailTemplateRefreshMessage() {
 | 
			
		||||
        SmsTemplateRefreshMessage message = new SmsTemplateRefreshMessage();
 | 
			
		||||
    public void sendMailAccountRefreshMessage() {
 | 
			
		||||
        MailAccountRefreshMessage message = new MailAccountRefreshMessage();
 | 
			
		||||
        redisMQTemplate.send(message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +58,11 @@ public class MailProducer {
 | 
			
		||||
        MailSendMessage message = new MailSendMessage();
 | 
			
		||||
        message.setContent(content);
 | 
			
		||||
        message.setFrom(mailAccountDO.getFrom());
 | 
			
		||||
        message.setHost(mailAccountDO.getHost());
 | 
			
		||||
        message.setPort(mailAccountDO.getPort());
 | 
			
		||||
        message.setPassword(mailAccountDO.getPassword());
 | 
			
		||||
        message.setUsername(mailAccountDO.getUsername());
 | 
			
		||||
        message.setSslEnable(mailAccountDO.getSslEnable());
 | 
			
		||||
        message.setTemplateCode(mailTemplateDO.getCode());
 | 
			
		||||
        message.setTitle(title);
 | 
			
		||||
        message.setTos(tos);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,11 @@ import java.util.List;
 | 
			
		||||
 */
 | 
			
		||||
public interface MailAccountService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 初始化邮箱账号的本地缓存
 | 
			
		||||
     */
 | 
			
		||||
    void initLocalCache();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建邮箱账号
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -46,5 +46,11 @@ public interface MailLogService {
 | 
			
		||||
     */
 | 
			
		||||
    Long createMailLog(MailAccountDO mailAccountDO, MailTemplateDO mailTemplateDO, String from, String content, List<String> tos, String title, Boolean isSend);
 | 
			
		||||
 | 
			
		||||
    Long updateSmsSendResult(Long logId, String result);
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新邮件发送结果
 | 
			
		||||
     *
 | 
			
		||||
     * @param logId          发送日志Id
 | 
			
		||||
     * @param result         发送结果 默认返回messageId
 | 
			
		||||
     */
 | 
			
		||||
    void updateMailSendResult(Long logId, String result);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,9 @@ import java.util.Map;
 | 
			
		||||
 */
 | 
			
		||||
public interface MailTemplateService {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 初始化邮箱模版的本地缓存
 | 
			
		||||
     */
 | 
			
		||||
    void initLocalCache();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -73,18 +76,11 @@ public interface MailTemplateService {
 | 
			
		||||
     */
 | 
			
		||||
    MailTemplateDO getMailTemplateByCodeFromCache(String code);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 发送邮件
 | 
			
		||||
     *
 | 
			
		||||
     * @param mailReqVO 邮件发送信息
 | 
			
		||||
     */
 | 
			
		||||
    void sendMail(MailReqVO mailReqVO);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮件模版内容合成
 | 
			
		||||
     * @param content 邮箱模版
 | 
			
		||||
     * @param params 合成参数
 | 
			
		||||
     * @return
 | 
			
		||||
     */
 | 
			
		||||
    String formateMailTemplateContent(String content, Map<String, String> params);
 | 
			
		||||
    String formatMailTemplateContent(String content, Map<String, String> params);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,28 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.service.mail.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountCreateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.mail.MailAccountService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.PostConstruct;
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
 | 
			
		||||
@@ -28,6 +36,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
 | 
			
		||||
 */
 | 
			
		||||
@Service
 | 
			
		||||
@Validated
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class MailAccountServiceImpl implements MailAccountService {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
@@ -36,26 +45,71 @@ public class MailAccountServiceImpl implements MailAccountService {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private MailTemplateMapper mailTemplateMapper;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private MailProducer mailProducer;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮箱账号缓存
 | 
			
		||||
     * key:邮箱账号编码 {@link MailAccountDO#getId()}
 | 
			
		||||
     *
 | 
			
		||||
     * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
 | 
			
		||||
     */
 | 
			
		||||
    private volatile Map<Long, MailAccountDO> mailAccountCache;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 缓存菜单的最大更新时间,用于后续的增量轮询,判断是否有更新
 | 
			
		||||
     */
 | 
			
		||||
    private volatile Date maxUpdateTime;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @PostConstruct
 | 
			
		||||
    public void initLocalCache() {
 | 
			
		||||
        List<MailAccountDO> mailAccountDOList = this.loadMailAccountIfUpdate(maxUpdateTime);
 | 
			
		||||
        if (CollUtil.isEmpty(mailAccountDOList)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 写入缓存
 | 
			
		||||
        mailAccountCache = CollectionUtils.convertMap(mailAccountDOList, MailAccountDO::getId);
 | 
			
		||||
        maxUpdateTime = CollectionUtils.getMaxValue(mailAccountDOList, MailAccountDO::getUpdateTime);
 | 
			
		||||
        log.info("[initLocalCache][初始化 MailAccount 数量为 {}]", mailAccountDOList.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<MailAccountDO> loadMailAccountIfUpdate(Date maxUpdateTime) {
 | 
			
		||||
        //第一步 判断是否需要更新
 | 
			
		||||
        if(null == maxUpdateTime){ // 如果更新时间为空,说明 DB 一定有新数据
 | 
			
		||||
            log.info("[loadMailAccountIfUpdate][首次加载全量账号信息]");
 | 
			
		||||
        }else{ // 判断数据库中是否有更新的账号信息
 | 
			
		||||
            if (mailAccountMapper.selectCountByUpdateTimeGt(maxUpdateTime) == 0) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            log.info("[loadMailAccountIfUpdate][增量加载全量账号信息]");
 | 
			
		||||
        }
 | 
			
		||||
        return mailAccountMapper.selectList();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long create(MailAccountCreateReqVO createReqVO) {
 | 
			
		||||
        // username 要校验唯一
 | 
			
		||||
        validateMailAccountOnlyByUserName(createReqVO.getUsername());
 | 
			
		||||
        this.validateMailAccountOnlyByUserName(createReqVO.getUsername());
 | 
			
		||||
        MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(createReqVO);
 | 
			
		||||
        mailAccountMapper.insert(mailAccountDO);
 | 
			
		||||
 | 
			
		||||
        // 更新
 | 
			
		||||
        mailProducer.sendMailAccountRefreshMessage();
 | 
			
		||||
        return mailAccountDO.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(MailAccountUpdateReqVO updateReqVO) {
 | 
			
		||||
        // username 要校验唯一 TODO @wangjingyi:校验唯一的时候,需要排除掉自己
 | 
			
		||||
        validateMailAccountExists(updateReqVO.getId());
 | 
			
		||||
        // username 要校验唯一 TODO @wangjingyi:校验唯一的时候,需要排除掉自己 DONE
 | 
			
		||||
        this.validateMailAccountOnlyByUserNameAndId(updateReqVO.getUsername(),updateReqVO.getId());
 | 
			
		||||
        MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(updateReqVO);
 | 
			
		||||
        // 校验是否存在
 | 
			
		||||
        validateMailAccountExists(mailAccountDO.getId());
 | 
			
		||||
 | 
			
		||||
        // 更新
 | 
			
		||||
        mailProducer.sendMailAccountRefreshMessage();
 | 
			
		||||
        mailAccountMapper.updateById(mailAccountDO);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -65,9 +119,10 @@ public class MailAccountServiceImpl implements MailAccountService {
 | 
			
		||||
        validateMailAccountExists(id);
 | 
			
		||||
        // 校验是否存在关联模版
 | 
			
		||||
        validateMailTemplateByAccountId(id);
 | 
			
		||||
 | 
			
		||||
        // 删除
 | 
			
		||||
        mailAccountMapper.deleteById(id);
 | 
			
		||||
        // 更新
 | 
			
		||||
        mailProducer.sendMailAccountRefreshMessage();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -92,17 +147,26 @@ public class MailAccountServiceImpl implements MailAccountService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateMailAccountOnlyByUserName(String userName){
 | 
			
		||||
        MailAccountDO mailAccountDO = mailAccountMapper.selectByUserName(userName);
 | 
			
		||||
        if (mailAccountDO != null) {
 | 
			
		||||
            throw exception(MAIL_ACCOUNT_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
        mailAccountCache.forEach((key,value)->{
 | 
			
		||||
            if(value.getUsername().equals(userName)){
 | 
			
		||||
                throw exception(MAIL_ACCOUNT_EXISTS);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    private void validateMailAccountOnlyByUserNameAndId(String userName,Long id){
 | 
			
		||||
        mailAccountCache.forEach((key , value)->{
 | 
			
		||||
            if (value.getUsername().equals(userName)){
 | 
			
		||||
                if (!key.equals(id)){
 | 
			
		||||
                    throw exception(MAIL_ACCOUNT_EXISTS);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateMailTemplateByAccountId(Long accountId){
 | 
			
		||||
        MailTemplateDO mailTemplateDO =  mailTemplateMapper.selectOneByAccountId(accountId);
 | 
			
		||||
        if (mailTemplateDO != null) {
 | 
			
		||||
            // TODO wangjingyi:MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS
 | 
			
		||||
            throw exception(MAIL_RELATE_TEMPLATE_EXISTS);
 | 
			
		||||
            // TODO wangjingyi:MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS DONE
 | 
			
		||||
            throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,11 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.mail.MailLogService;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
 | 
			
		||||
import java.sql.Timestamp;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
@@ -61,21 +59,14 @@ public class MailLogServiceImpl implements MailLogService {
 | 
			
		||||
        return mailLogDO.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:不需要返回 id 呀
 | 
			
		||||
    // TODO @wangjingyi:不需要返回 id 呀 DONE
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long updateSmsSendResult(Long logId, String result) {
 | 
			
		||||
    public void updateMailSendResult(Long logId, String result) {
 | 
			
		||||
        MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder();
 | 
			
		||||
        logDOBuilder.id(logId);
 | 
			
		||||
        logDOBuilder.sendResult(result);
 | 
			
		||||
        MailLogDO mailLogDO = logDOBuilder.build();
 | 
			
		||||
        mailLogMapper.updateById(mailLogDO);
 | 
			
		||||
        return logId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:无用的方法,需要进行删除
 | 
			
		||||
    public Long create(){
 | 
			
		||||
        MailLogDO mailLogDO = new MailLogDO();
 | 
			
		||||
        mailLogMapper.insert(mailLogDO);
 | 
			
		||||
        return mailLogDO.getId();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.service.mail.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.extra.mail.MailAccount;
 | 
			
		||||
import cn.hutool.extra.mail.MailUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
 | 
			
		||||
@@ -21,8 +22,7 @@ import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
			
		||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_EXISTS;
 | 
			
		||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS;
 | 
			
		||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 邮箱模版 服务实现类
 | 
			
		||||
@@ -49,36 +49,47 @@ public class MailSendServiceImpl implements MailSendService {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void sendMail(String templateCode, String from , String content , List<String> tos , String title) {
 | 
			
		||||
        // TODO @@wangjingyi:发送的时候,参考下短信;
 | 
			
		||||
        // TODO @@wangjingyi:发送的时候,参考下短信;DONE
 | 
			
		||||
        //校验邮箱模版是否合法
 | 
			
		||||
        MailTemplateDO mailTemplateDO =  this.checkMailTemplateValid(templateCode);
 | 
			
		||||
        // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志
 | 
			
		||||
        Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(mailTemplateDO.getStatus());
 | 
			
		||||
        //查询账号信息
 | 
			
		||||
        MailAccountDO mailAccountDO = mailAccountMapper.selectOne(
 | 
			
		||||
                "from", from
 | 
			
		||||
        );
 | 
			
		||||
        //校验账号信息是否合法
 | 
			
		||||
        MailAccountDO mailAccountDO = this.checkMailAccountValid(from);
 | 
			
		||||
        Map<String , String> params = MailAccountConvert.INSTANCE.convertToMap(mailAccountDO , content);
 | 
			
		||||
        content = mailTemplateService.formateMailTemplateContent(mailTemplateDO.getContent(), params);
 | 
			
		||||
        content = mailTemplateService.formatMailTemplateContent(mailTemplateDO.getContent(), params);
 | 
			
		||||
        Long sendLogId = mailLogService.createMailLog(mailAccountDO , mailTemplateDO , from , content , tos , title , isSend);
 | 
			
		||||
 | 
			
		||||
        // 后续功能 TODO :附件查询
 | 
			
		||||
        //List<String> fileIds = mailSendVO.getFileIds();
 | 
			
		||||
 | 
			
		||||
        //装载账号信息
 | 
			
		||||
        MailAccount account  = MailAccountConvert.INSTANCE.convertAccount(mailAccountDO);
 | 
			
		||||
 | 
			
		||||
        // 发送 MQ 消息,异步执行发送短信
 | 
			
		||||
        if (isSend) {
 | 
			
		||||
            mailProducer.sendMailSendMessage(mailAccountDO , mailTemplateDO ,content , tos , title , sendLogId);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private MailAccountDO checkMailAccountValid(String from) {
 | 
			
		||||
        MailAccountDO mailAccountDO = mailAccountMapper.selectOneByFrom(from);
 | 
			
		||||
        if(null == mailAccountDO){
 | 
			
		||||
            throw exception(MAIL_ACCOUNT_NOT_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
        return mailAccountDO;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void doSendMail(MailSendMessage message) {
 | 
			
		||||
        // TODO @wangjingyi:直接使用 hutool 发送,不要封装 mail client 哈,因为短信的客户端都是比较统一的
 | 
			
		||||
        //MailClient mailClient = mailClientFactory.getMailClient();
 | 
			
		||||
        //String result = mailClient.sendMail(message.getFrom() , message.getContent() , message.getTitle() , message.getTos());
 | 
			
		||||
        //mailLogService.updateSmsSendResult(message.getLogId() , result);
 | 
			
		||||
        // TODO @wangjingyi:直接使用 hutool 发送,不要封装 mail client 哈,因为短信的客户端都是比较统一的 DONE
 | 
			
		||||
        //装载账号信息
 | 
			
		||||
        MailAccount account  = MailAccountConvert.INSTANCE.convertAccount(message);
 | 
			
		||||
        //发送邮件
 | 
			
		||||
        try{
 | 
			
		||||
            String messageId = MailUtil.send(account,message.getTos(),message.getTitle(),message.getContent(),false,null);
 | 
			
		||||
            mailLogService.updateMailSendResult(message.getLogId() , messageId);
 | 
			
		||||
        }catch (Exception e){
 | 
			
		||||
            mailLogService.updateMailSendResult(message.getLogId() , e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private MailTemplateDO checkMailTemplateValid(String templateCode) {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
@@ -48,59 +49,53 @@ public class MailTemplateServiceImpl implements MailTemplateService {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private MailTemplateMapper mailTemplateMapper;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private MailAccountMapper mailAccountMapper;
 | 
			
		||||
 | 
			
		||||
    private volatile List<MailTemplateDO> mailTemplateDOList;
 | 
			
		||||
    private MailProducer mailProducer;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 邮件模板缓存
 | 
			
		||||
     * key:邮箱模板编码 {@link MailTemplateDO#getCode()}
 | 
			
		||||
     * key:邮箱模板编码 {@link MailTemplateDO#getId()}
 | 
			
		||||
     *
 | 
			
		||||
     * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
 | 
			
		||||
     */
 | 
			
		||||
    private volatile Map<String, MailTemplateDO> mailTemplateCache;
 | 
			
		||||
    private volatile Map<Long, MailTemplateDO> mailTemplateCache;
 | 
			
		||||
 | 
			
		||||
    private volatile Date maxUpdateTime;
 | 
			
		||||
 | 
			
		||||
    // TODO @wangjingyi:参考下别的模块的 initLocalCache 的实现
 | 
			
		||||
    // TODO @wangjingyi:参考下别的模块的 initLocalCache 的实现 DONE
 | 
			
		||||
    @Override
 | 
			
		||||
    @PostConstruct
 | 
			
		||||
    public void initLocalCache() {
 | 
			
		||||
        if(maxUpdateTime == null){
 | 
			
		||||
            mailTemplateDOList = mailTemplateMapper.selectList();
 | 
			
		||||
        }else{
 | 
			
		||||
            if(mailTemplateMapper.selectByMaxUpdateTime(maxUpdateTime)<=0){
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        List<MailTemplateDO> mailTemplateDOList = this.loadMailTemplateIfUpdate(maxUpdateTime);
 | 
			
		||||
        if (CollUtil.isEmpty(mailTemplateDOList)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 写入缓存
 | 
			
		||||
        mailTemplateCache = CollectionUtils.convertMap(mailTemplateDOList, MailTemplateDO::getCode);
 | 
			
		||||
        mailTemplateCache = CollectionUtils.convertMap(mailTemplateDOList, MailTemplateDO::getId);
 | 
			
		||||
        maxUpdateTime = CollectionUtils.getMaxValue(mailTemplateDOList, MailTemplateDO::getUpdateTime);
 | 
			
		||||
        log.info("[initLocalCache][初始化 mailTemplate 数量为 {}]", mailTemplateDOList.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long create(MailTemplateCreateReqVO createReqVO) {
 | 
			
		||||
        // code 要校验唯一
 | 
			
		||||
        // TODO @wangjingyi:参考下我在 account 给的唯一校验的说明。
 | 
			
		||||
        this.validateMailTemplateOnlyByCode(createReqVO.getCode());
 | 
			
		||||
        //要校验存在
 | 
			
		||||
        this.validateMailTemplateExists(createReqVO.getId());
 | 
			
		||||
        MailTemplateDO mailTemplateDO = MailTemplateConvert.INSTANCE.convert(createReqVO);
 | 
			
		||||
        mailTemplateMapper.insert(mailTemplateDO);
 | 
			
		||||
        // TODO @wangjingyi:mq 更新
 | 
			
		||||
        // TODO @wangjingyi:mq 更新 DONE
 | 
			
		||||
        mailProducer.sendMailTemplateRefreshMessage();
 | 
			
		||||
        return mailTemplateDO.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(@Valid MailTemplateUpdateReqVO updateReqVO) {
 | 
			
		||||
        // 校验是否存在
 | 
			
		||||
        this.validateMailTemplateExists(updateReqVO.getId());
 | 
			
		||||
        // 校验是否唯一
 | 
			
		||||
        // TODO @wangjingyi:参考下我在 account 给的唯一校验的说明。
 | 
			
		||||
        this.validateMailTemplateOnlyByCode(updateReqVO.getId(),updateReqVO.getCode());
 | 
			
		||||
        MailTemplateDO mailTemplateDO = MailTemplateConvert.INSTANCE.convert(updateReqVO);
 | 
			
		||||
        mailTemplateMapper.updateById(mailTemplateDO);
 | 
			
		||||
        // TODO @wangjingyi:mq 更新
 | 
			
		||||
        // TODO @wangjingyi:mq 更新 DONE
 | 
			
		||||
        mailProducer.sendMailTemplateRefreshMessage();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -108,7 +103,8 @@ public class MailTemplateServiceImpl implements MailTemplateService {
 | 
			
		||||
        // 校验是否存在
 | 
			
		||||
        this.validateMailTemplateExists(id);
 | 
			
		||||
        mailTemplateMapper.deleteById(id);
 | 
			
		||||
        // TODO @wangjingyi:mq 更新
 | 
			
		||||
        // TODO @wangjingyi:mq 更新 DONE
 | 
			
		||||
        mailProducer.sendMailTemplateRefreshMessage();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -127,43 +123,45 @@ public class MailTemplateServiceImpl implements MailTemplateService {
 | 
			
		||||
        return mailTemplateCache.get(code);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @@wangjingyi:单词拼写错误 DONE
 | 
			
		||||
    @Override
 | 
			
		||||
    public void sendMail(MailReqVO mailReqVO) {
 | 
			
		||||
        // TODO @@wangjingyi:发送的时候,参考下短信;
 | 
			
		||||
        MailTemplateDO mailTemplateDO =  mailTemplateMapper.selectById(mailReqVO.getTemplateId());
 | 
			
		||||
        //查询账号信息
 | 
			
		||||
        MailAccountDO mailAccountDO = mailAccountMapper.selectOne(
 | 
			
		||||
                "from", mailReqVO.getFrom()
 | 
			
		||||
        );
 | 
			
		||||
        String content = mailReqVO.getContent();
 | 
			
		||||
        Map<String , String> params = MailAccountConvert.INSTANCE.convertToMap(mailAccountDO , content);
 | 
			
		||||
        content = StrUtil.format(mailTemplateDO.getContent(), params);
 | 
			
		||||
 | 
			
		||||
        // 后续功能 TODO :附件查询
 | 
			
		||||
        //List<String> fileIds = mailSendVO.getFileIds();
 | 
			
		||||
 | 
			
		||||
        //装载账号信息
 | 
			
		||||
        MailAccount account  = MailAccountConvert.INSTANCE.convertAccount(mailAccountDO);
 | 
			
		||||
 | 
			
		||||
        //发送
 | 
			
		||||
        MailUtil.send(account , mailReqVO.getTos() , mailReqVO.getTitle() , content , false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO @@wangjingyi:单词拼写错误
 | 
			
		||||
    @Override
 | 
			
		||||
    public String formateMailTemplateContent(String content, Map<String, String> params) {
 | 
			
		||||
    public String formatMailTemplateContent(String content, Map<String, String> params) {
 | 
			
		||||
        return StrUtil.format(content, params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateMailTemplateExists(Long id) {
 | 
			
		||||
        if (mailTemplateMapper.selectById(id) == null) {
 | 
			
		||||
        if (mailTemplateCache.get(id) == null) {
 | 
			
		||||
            throw exception(MAIL_TEMPLATE_NOT_EXISTS);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void validateMailTemplateOnlyByCode(String code){
 | 
			
		||||
        if (mailTemplateMapper.selectOneByCode(code) != null) {
 | 
			
		||||
            throw exception(MAIL_TEMPLATE_EXISTS);
 | 
			
		||||
    private void validateMailTemplateOnlyByCode(Long id ,String code){
 | 
			
		||||
        mailTemplateCache.forEach((key,value)->{
 | 
			
		||||
            if (value.getCode().equals(code)){
 | 
			
		||||
                if (!key.equals(id)){
 | 
			
		||||
                    throw exception(MAIL_TEMPLATE_EXISTS);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * 如果邮件模板发生变化,从数据库中获取最新的全量邮件模板。
 | 
			
		||||
     * 如果未发生变化,则返回空
 | 
			
		||||
     *
 | 
			
		||||
     * @param maxUpdateTime 当前邮件模板的最大更新时间
 | 
			
		||||
     * @return 邮件模板列表
 | 
			
		||||
     */
 | 
			
		||||
    private List<MailTemplateDO> loadMailTemplateIfUpdate(Date maxUpdateTime) {
 | 
			
		||||
        // 第一步,判断是否要更新。
 | 
			
		||||
        if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
 | 
			
		||||
            log.info("[loadMailTemplateIfUpdate][首次加载全量邮件模板]");
 | 
			
		||||
        } else { // 判断数据库中是否有更新的邮件模板
 | 
			
		||||
            if (mailTemplateMapper.selectByMaxUpdateTime(maxUpdateTime) == 0) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            log.info("[loadSmsTemplateIfUpdate][增量加载全量邮件模板]");
 | 
			
		||||
        }
 | 
			
		||||
        // 第二步,如果有更新,则从数据库加载所有邮件模板
 | 
			
		||||
        return mailTemplateMapper.selectList();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user