Commit d7305739d3fcef6efe25c12d33c02b903c181308
1 parent
d1812761
邮件模块 添加邮件发送api
Showing
44 changed files
with
1085 additions
and
59 deletions
yudao-framework/pom.xml
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | <module>yudao-spring-boot-starter-biz-operatelog</module> | 30 | <module>yudao-spring-boot-starter-biz-operatelog</module> |
| 31 | <module>yudao-spring-boot-starter-biz-dict</module> | 31 | <module>yudao-spring-boot-starter-biz-dict</module> |
| 32 | <module>yudao-spring-boot-starter-biz-sms</module> | 32 | <module>yudao-spring-boot-starter-biz-sms</module> |
| 33 | + <module>yudao-spring-boot-starter-biz-mail</module> | ||
| 33 | <module>yudao-spring-boot-starter-activiti</module> | 34 | <module>yudao-spring-boot-starter-activiti</module> |
| 34 | <module>yudao-spring-boot-starter-biz-pay</module> | 35 | <module>yudao-spring-boot-starter-biz-pay</module> |
| 35 | <module>yudao-spring-boot-starter-biz-weixin</module> | 36 | <module>yudao-spring-boot-starter-biz-weixin</module> |
yudao-framework/yudao-spring-boot-starter-biz-mail/pom.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 5 | + <parent> | ||
| 6 | + <groupId>cn.iocoder.boot</groupId> | ||
| 7 | + <artifactId>yudao-framework</artifactId> | ||
| 8 | + <version>${revision}</version> | ||
| 9 | + </parent> | ||
| 10 | + <modelVersion>4.0.0</modelVersion> | ||
| 11 | + <artifactId>yudao-spring-boot-starter-biz-mail</artifactId> | ||
| 12 | + <packaging>jar</packaging> | ||
| 13 | + | ||
| 14 | + <dependencies> | ||
| 15 | + <dependency> | ||
| 16 | + <groupId>cn.iocoder.boot</groupId> | ||
| 17 | + <artifactId>yudao-common</artifactId> | ||
| 18 | + </dependency> | ||
| 19 | + | ||
| 20 | + <!-- Spring 核心 --> | ||
| 21 | + <dependency> | ||
| 22 | + <groupId>org.springframework.boot</groupId> | ||
| 23 | + <artifactId>spring-boot-starter</artifactId> | ||
| 24 | + </dependency> | ||
| 25 | + | ||
| 26 | + <!-- 监控相关 --> | ||
| 27 | + <dependency> | ||
| 28 | + <groupId>io.opentracing</groupId> | ||
| 29 | + <artifactId>opentracing-util</artifactId> <!-- aliyun 短信需要,进行链路追踪 --> | ||
| 30 | + </dependency> | ||
| 31 | + | ||
| 32 | + <!-- Test 测试相关 --> | ||
| 33 | + <dependency> | ||
| 34 | + <groupId>cn.iocoder.boot</groupId> | ||
| 35 | + <artifactId>yudao-spring-boot-starter-test</artifactId> | ||
| 36 | + <scope>test</scope> | ||
| 37 | + </dependency> | ||
| 38 | + | ||
| 39 | + <!-- 工具类相关 --> | ||
| 40 | + <dependency> | ||
| 41 | + <groupId>com.google.guava</groupId> | ||
| 42 | + <artifactId>guava</artifactId> | ||
| 43 | + <optional>true</optional> <!-- 设置为可选,因为使用到 @VisibleForTesting 用于单元测试 --> | ||
| 44 | + </dependency> | ||
| 45 | + | ||
| 46 | + <dependency> | ||
| 47 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 48 | + <artifactId>jackson-databind</artifactId> | ||
| 49 | + </dependency> | ||
| 50 | + <dependency> | ||
| 51 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
| 52 | + <artifactId>jackson-core</artifactId> | ||
| 53 | + </dependency> | ||
| 54 | + | ||
| 55 | + <dependency> | ||
| 56 | + <groupId>jakarta.validation</groupId> | ||
| 57 | + <artifactId>jakarta.validation-api</artifactId> | ||
| 58 | + </dependency> | ||
| 59 | + <dependency> | ||
| 60 | + <groupId>org.projectlombok</groupId> | ||
| 61 | + <artifactId>lombok</artifactId> | ||
| 62 | + </dependency> | ||
| 63 | + </dependencies> | ||
| 64 | + | ||
| 65 | +</project> | ||
| 0 | \ No newline at end of file | 66 | \ No newline at end of file |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/config/YudaoMailAutoConfiguration.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.config; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mail.core.client.MailClientFactory; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.client.impl.MailClientFactoryImpl; | ||
| 5 | +import org.springframework.context.annotation.Bean; | ||
| 6 | +import org.springframework.context.annotation.Configuration; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 邮箱配置类 | ||
| 10 | + * | ||
| 11 | + * @author 芋道源码 | ||
| 12 | + */ | ||
| 13 | +@Configuration | ||
| 14 | +public class YudaoMailAutoConfiguration { | ||
| 15 | + | ||
| 16 | + @Bean | ||
| 17 | + public MailClientFactory mailClientFactory() { | ||
| 18 | + return new MailClientFactoryImpl(); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/MailClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client; | ||
| 2 | + | ||
| 3 | +import java.util.List; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 邮件客户端,用于对接各邮箱平台的 SDK,实现邮件发送等功能 | ||
| 7 | + * | ||
| 8 | + * @author wangjingyi | ||
| 9 | + * @date 2021/4/19 19:21 | ||
| 10 | + */ | ||
| 11 | +public interface MailClient { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 发送邮件 | ||
| 15 | + * | ||
| 16 | + * @param from 邮箱账号 | ||
| 17 | + * @param content 内容 | ||
| 18 | + * @param title 标题 | ||
| 19 | + * @param tos 收件人 | ||
| 20 | + * @return 邮件发送结果 | ||
| 21 | + */ | ||
| 22 | + String sendMail(String from, String content, String title, List<String> tos); | ||
| 23 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/MailClientFactory.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/MailCodeMapping.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.enums.MailFrameworkErrorCodeConstants; | ||
| 5 | + | ||
| 6 | +import java.util.function.Function; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 将 API 的错误码,转换为通用的错误码 | ||
| 10 | + * | ||
| 11 | + * @see MailCommonResult | ||
| 12 | + * @see MailFrameworkErrorCodeConstants | ||
| 13 | + * | ||
| 14 | + * @author 芋道源码 | ||
| 15 | + */ | ||
| 16 | +public interface MailCodeMapping extends Function<String, ErrorCode> { | ||
| 17 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/MailCommonResult.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.exceptions.ExceptionUtil; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 5 | +import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 6 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import lombok.EqualsAndHashCode; | ||
| 9 | +import lombok.ToString; | ||
| 10 | +import cn.iocoder.yudao.framework.mail.core.enums.MailFrameworkErrorCodeConstants; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * 短信的 CommonResult 拓展类 | ||
| 14 | + * | ||
| 15 | + * 考虑到不同的平台,返回的 code 和 msg 是不同的,所以统一额外返回 {@link #apiCode} 和 {@link #apiMsg} 字段 | ||
| 16 | + * | ||
| 17 | + * 另外,一些短信平台(例如说阿里云、腾讯云)会返回一个请求编号,用于排查请求失败的问题,我们设置到 {@link #apiRequestId} 字段 | ||
| 18 | + * | ||
| 19 | + * @author 芋道源码 | ||
| 20 | + */ | ||
| 21 | +@Data | ||
| 22 | +@EqualsAndHashCode(callSuper = true) | ||
| 23 | +@ToString(callSuper = true) | ||
| 24 | +public class MailCommonResult<T> extends CommonResult<T> { | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * API 返回错误码 | ||
| 28 | + * | ||
| 29 | + * 由于第三方的错误码可能是字符串,所以使用 String 类型 | ||
| 30 | + */ | ||
| 31 | + private String apiCode; | ||
| 32 | + /** | ||
| 33 | + * API 返回提示 | ||
| 34 | + */ | ||
| 35 | + private String apiMsg; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * API 请求编号 | ||
| 39 | + */ | ||
| 40 | + private String apiRequestId; | ||
| 41 | + | ||
| 42 | + private MailCommonResult() { | ||
| 43 | + } | ||
| 44 | + | ||
| 45 | + public static <T> MailCommonResult<T> build(String apiCode, String apiMsg, String apiRequestId, | ||
| 46 | + T data, MailCodeMapping codeMapping) { | ||
| 47 | + Assert.notNull(codeMapping, "参数 codeMapping 不能为空"); | ||
| 48 | + MailCommonResult<T> result = new MailCommonResult<T>().setApiCode(apiCode).setApiMsg(apiMsg).setApiRequestId(apiRequestId); | ||
| 49 | + result.setData(data); | ||
| 50 | + // 翻译错误码 | ||
| 51 | + if (codeMapping != null) { | ||
| 52 | + ErrorCode errorCode = codeMapping.apply(apiCode); | ||
| 53 | + if (errorCode == null) { | ||
| 54 | + errorCode = MailFrameworkErrorCodeConstants.MAIL_UNKNOWN; | ||
| 55 | + } | ||
| 56 | + result.setCode(errorCode.getCode()).setMsg(errorCode.getMsg()); | ||
| 57 | + } | ||
| 58 | + return result; | ||
| 59 | + } | ||
| 60 | + | ||
| 61 | + public static <T> MailCommonResult<T> error(Throwable ex) { | ||
| 62 | + MailCommonResult<T> result = new MailCommonResult<>(); | ||
| 63 | + result.setCode(MailFrameworkErrorCodeConstants.EXCEPTION.getCode()); | ||
| 64 | + result.setMsg(ExceptionUtil.getRootCauseMessage(ex)); | ||
| 65 | + return result; | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/dto/MailReceiveRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.dto; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import java.util.Date; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 消息接收 Response DTO | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +@Data | ||
| 13 | +public class MailReceiveRespDTO { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 是否接收成功 | ||
| 17 | + */ | ||
| 18 | + private Boolean success; | ||
| 19 | + /** | ||
| 20 | + * API 接收结果的编码 | ||
| 21 | + */ | ||
| 22 | + private String errorCode; | ||
| 23 | + /** | ||
| 24 | + * API 接收结果的说明 | ||
| 25 | + */ | ||
| 26 | + private String errorMsg; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 手机号 | ||
| 30 | + */ | ||
| 31 | + private String mobile; | ||
| 32 | + /** | ||
| 33 | + * 用户接收时间 | ||
| 34 | + */ | ||
| 35 | + private Date receiveTime; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 短信 API 发送返回的序号 | ||
| 39 | + */ | ||
| 40 | + private String serialNo; | ||
| 41 | + /** | ||
| 42 | + * 短信日志编号 | ||
| 43 | + * | ||
| 44 | + * 对应 SysSmsLogDO 的编号 | ||
| 45 | + */ | ||
| 46 | + private Long logId; | ||
| 47 | + | ||
| 48 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/dto/MailSendRespDTO.java
0 → 100644
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/dto/MailTemplateRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.dto; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 短信模板 Response DTO | ||
| 7 | + * | ||
| 8 | + * @author 芋道源码 | ||
| 9 | + */ | ||
| 10 | +@Data | ||
| 11 | +public class MailTemplateRespDTO { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 模板编号 | ||
| 15 | + */ | ||
| 16 | + private String id; | ||
| 17 | + /** | ||
| 18 | + * 短信内容 | ||
| 19 | + */ | ||
| 20 | + private String content; | ||
| 21 | + /** | ||
| 22 | + * 审核状态 | ||
| 23 | + * | ||
| 24 | + */ | ||
| 25 | + private Integer auditStatus; | ||
| 26 | + /** | ||
| 27 | + * 审核未通过的理由 | ||
| 28 | + */ | ||
| 29 | + private String auditReason; | ||
| 30 | + | ||
| 31 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/impl/AbstractMailClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.impl; | ||
| 2 | + | ||
| 3 | +import lombok.extern.slf4j.Slf4j; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.client.MailClient; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 短信客户端的抽象类,提供模板方法,减少子类的冗余代码 | ||
| 8 | + * | ||
| 9 | + * @author zzf | ||
| 10 | + * @date 2021/2/1 9:28 | ||
| 11 | + */ | ||
| 12 | +@Slf4j | ||
| 13 | +public abstract class AbstractMailClient implements MailClient { | ||
| 14 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/impl/MailClientFactoryImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.impl; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.mail.core.client.MailClient; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.client.impl.hutool.HutoolMailClient; | ||
| 5 | +import lombok.extern.slf4j.Slf4j; | ||
| 6 | +import cn.iocoder.yudao.framework.mail.core.client.MailClientFactory; | ||
| 7 | +import cn.iocoder.yudao.framework.mail.core.enums.MailChannelEnum; | ||
| 8 | +import org.springframework.validation.annotation.Validated; | ||
| 9 | + | ||
| 10 | +import java.util.Arrays; | ||
| 11 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 12 | +import java.util.concurrent.ConcurrentMap; | ||
| 13 | +@Validated | ||
| 14 | +@Slf4j | ||
| 15 | +public class MailClientFactoryImpl implements MailClientFactory { | ||
| 16 | + | ||
| 17 | + private final ConcurrentMap<String, AbstractMailClient> channelCodeClients = new ConcurrentHashMap<>(); | ||
| 18 | + | ||
| 19 | + public MailClientFactoryImpl (){ | ||
| 20 | + Arrays.stream(MailChannelEnum.values()).forEach(mailChannelEnum -> { | ||
| 21 | + AbstractMailClient abstractMailClient = createMailClient(mailChannelEnum); | ||
| 22 | + channelCodeClients.put(mailChannelEnum.getCode() , abstractMailClient); | ||
| 23 | + }); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + private AbstractMailClient createMailClient(MailChannelEnum mailChannelEnum) { | ||
| 27 | + switch (mailChannelEnum){ | ||
| 28 | + case HUTOOL: return new HutoolMailClient(); | ||
| 29 | + } | ||
| 30 | + // 创建失败,错误日志 + 抛出异常 | ||
| 31 | + log.error("[createMailClient][配置({}) 找不到合适的客户端实现]" , mailChannelEnum); | ||
| 32 | + throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", mailChannelEnum)); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @Override | ||
| 36 | + public MailClient getMailClient() { | ||
| 37 | + return channelCodeClients.get("HUTOOL"); | ||
| 38 | + } | ||
| 39 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/impl/hutool/HutoolMailClient.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.impl.hutool; | ||
| 2 | + | ||
| 3 | +import cn.hutool.extra.mail.MailUtil; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.client.impl.AbstractMailClient; | ||
| 5 | +import lombok.extern.slf4j.Slf4j; | ||
| 6 | + | ||
| 7 | +import java.util.List; | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 邮件客户端实现 | ||
| 12 | + * | ||
| 13 | + * @author wangjingyi | ||
| 14 | + * @date 2021/4/25 14:25 | ||
| 15 | + */ | ||
| 16 | +@Slf4j | ||
| 17 | +public class HutoolMailClient extends AbstractMailClient { | ||
| 18 | + | ||
| 19 | + @Override | ||
| 20 | + public String sendMail(String from, String content, String title, List<String> tos) { | ||
| 21 | + try{ | ||
| 22 | + return MailUtil.send(from , title , content , false , null); | ||
| 23 | + }catch (Exception e){ | ||
| 24 | + log.error(e.getMessage()); | ||
| 25 | + } | ||
| 26 | + return ""; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/client/impl/hutool/HutoolMailCodeMapping.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.client.impl.hutool; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.client.MailCodeMapping; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 阿里云的 SmsCodeMapping 实现类 | ||
| 8 | + * | ||
| 9 | + * 参见 https://help.aliyun.com/document_detail/101346.htm 文档 | ||
| 10 | + * | ||
| 11 | + * @author 芋道源码 | ||
| 12 | + */ | ||
| 13 | +public class HutoolMailCodeMapping implements MailCodeMapping { | ||
| 14 | + | ||
| 15 | + @Override | ||
| 16 | + public ErrorCode apply(String apiCode) { | ||
| 17 | + return null; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/enums/MailChannelEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.enums; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ArrayUtil; | ||
| 4 | +import lombok.AllArgsConstructor; | ||
| 5 | +import lombok.Getter; | ||
| 6 | + | ||
| 7 | +/** | ||
| 8 | + * 短信渠道枚举 | ||
| 9 | + * | ||
| 10 | + * @author zzf | ||
| 11 | + * @date 2021/1/25 10:56 | ||
| 12 | + */ | ||
| 13 | +@Getter | ||
| 14 | +@AllArgsConstructor | ||
| 15 | +public enum MailChannelEnum { | ||
| 16 | + HUTOOL("HUTOOL" , "HUTOOL"), | ||
| 17 | + ; | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 编码 | ||
| 21 | + */ | ||
| 22 | + private final String code; | ||
| 23 | + /** | ||
| 24 | + * 名字 | ||
| 25 | + */ | ||
| 26 | + private final String name; | ||
| 27 | + | ||
| 28 | + public static MailChannelEnum getByCode(String code) { | ||
| 29 | + return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/enums/MailFrameworkErrorCodeConstants.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.enums; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 短信框架的错误码枚举 | ||
| 7 | + * | ||
| 8 | + * 短信框架,使用 2-001-000-000 段 | ||
| 9 | + * | ||
| 10 | + * @author 芋道源码 | ||
| 11 | + */ | ||
| 12 | +public interface MailFrameworkErrorCodeConstants { | ||
| 13 | + | ||
| 14 | + ErrorCode MAIL_UNKNOWN = new ErrorCode(2001000000, "未知错误,需要解析"); | ||
| 15 | + | ||
| 16 | + // ========== 权限 / 限流等相关 2001000100 ========== | ||
| 17 | + | ||
| 18 | + ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2001000100, "没有发送短信的权限"); | ||
| 19 | + // 云片:可以配置 IP 白名单,只有在白名单中才可以发送短信 | ||
| 20 | + ErrorCode SMS_IP_DENY = new ErrorCode(2001000100, "IP 不允许发送短信"); | ||
| 21 | + | ||
| 22 | + // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 | ||
| 23 | + ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2001000102, "指定手机的发送限流"); | ||
| 24 | + // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 | ||
| 25 | + ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2001000103, "每天的发送限流"); | ||
| 26 | + | ||
| 27 | + ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2001000104, "短信内容有敏感词"); | ||
| 28 | + | ||
| 29 | + // ========== 模板相关 2001000200 ========== | ||
| 30 | + ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2001000200, "短信模板不合法"); // 包括短信模板不存在 | ||
| 31 | + ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2001000201, "模板参数不正确"); | ||
| 32 | + | ||
| 33 | + // ========== 签名相关 2001000300 ========== | ||
| 34 | + ErrorCode SMS_SIGN_INVALID = new ErrorCode(2001000300, "短信签名不可用"); | ||
| 35 | + | ||
| 36 | + // ========== 账户相关 2001000400 ========== | ||
| 37 | + ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2001000400, "账户余额不足"); | ||
| 38 | + ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2001000401, "apiKey 不存在"); | ||
| 39 | + | ||
| 40 | + // ========== 其它相关 2001000900 开头 ========== | ||
| 41 | + ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2001000900, "请求参数缺失"); | ||
| 42 | + ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2001000901, "手机格式不正确"); | ||
| 43 | + ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2001000902, "手机号在黑名单中"); | ||
| 44 | + | ||
| 45 | + ErrorCode EXCEPTION = new ErrorCode(2001000999, "调用异常"); | ||
| 46 | + | ||
| 47 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/enums/MailTemplateAuditStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.enums; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 短信模板的审核状态枚举 | ||
| 8 | + * | ||
| 9 | + * @author 芋道源码 | ||
| 10 | + */ | ||
| 11 | +@AllArgsConstructor | ||
| 12 | +@Getter | ||
| 13 | +public enum MailTemplateAuditStatusEnum { | ||
| 14 | + | ||
| 15 | + CHECKING(1), | ||
| 16 | + SUCCESS(2), | ||
| 17 | + FAIL(3); | ||
| 18 | + | ||
| 19 | + private final Integer status; | ||
| 20 | + | ||
| 21 | +} |
yudao-framework/yudao-spring-boot-starter-biz-mail/src/main/java/cn/iocoder/yudao/framework/mail/core/property/MailChannelProperties.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.mail.core.property; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | +import cn.iocoder.yudao.framework.mail.core.enums.MailChannelEnum; | ||
| 5 | +import org.springframework.validation.annotation.Validated; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotEmpty; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | + | ||
| 10 | +/** | ||
| 11 | + * 短信渠道配置类 | ||
| 12 | + * | ||
| 13 | + * @author zzf | ||
| 14 | + * @date 2021/1/25 17:01 | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +@Validated | ||
| 18 | +public class MailChannelProperties { | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 渠道编号 | ||
| 22 | + */ | ||
| 23 | + @NotNull(message = "短信渠道 ID 不能为空") | ||
| 24 | + private Long id; | ||
| 25 | + /** | ||
| 26 | + * 短信签名 | ||
| 27 | + */ | ||
| 28 | + @NotEmpty(message = "短信签名不能为空") | ||
| 29 | + private String signature; | ||
| 30 | + /** | ||
| 31 | + * 渠道编码 | ||
| 32 | + * | ||
| 33 | + * 枚举 {@link MailChannelEnum} | ||
| 34 | + */ | ||
| 35 | + @NotEmpty(message = "渠道编码不能为空") | ||
| 36 | + private String code; | ||
| 37 | + /** | ||
| 38 | + * 短信 API 的账号 | ||
| 39 | + */ | ||
| 40 | + @NotEmpty(message = "短信 API 的账号不能为空") | ||
| 41 | + private String apiKey; | ||
| 42 | + /** | ||
| 43 | + * 短信 API 的秘钥 | ||
| 44 | + */ | ||
| 45 | + @NotEmpty(message = "短信 API 的秘钥不能为空") | ||
| 46 | + private String apiSecret; | ||
| 47 | + /** | ||
| 48 | + * 短信发送回调 URL | ||
| 49 | + */ | ||
| 50 | + private String callbackUrl; | ||
| 51 | + | ||
| 52 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApi.java
0 → 100644
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/mail/dto/MailSendReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.mail.dto; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.Email; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | +import java.util.List; | ||
| 10 | + | ||
| 11 | +@ApiModel("管理后台 - 邮件发送 Req VO") | ||
| 12 | +@Data | ||
| 13 | +public class MailSendReqDTO { // TODO @wangjingqi:1), 不用空格;2)应该只要传递 templateCode、参数就好,title、from、content、附件应该都是参数里的 | ||
| 14 | + | ||
| 15 | + @ApiModelProperty(value = "邮箱",required = true,example = "yudaoyuanma@123.com") | ||
| 16 | + @NotNull(message = "邮箱账号不能为空") | ||
| 17 | + @Email(message = "邮箱账号格式错误") | ||
| 18 | + private String from; | ||
| 19 | + | ||
| 20 | + @ApiModelProperty(value = "标题",example = "标题") | ||
| 21 | + private String title; | ||
| 22 | + | ||
| 23 | + @ApiModelProperty(value = "内容",example = "内容") | ||
| 24 | + private String content; | ||
| 25 | + | ||
| 26 | + @ApiModelProperty(value = "邮箱模版id",example = "1024") | ||
| 27 | + @NotNull(message = "邮箱模版id不能为空") | ||
| 28 | + private Integer templateId; | ||
| 29 | + | ||
| 30 | + @ApiModelProperty(value = "收件人",required = true,example = "yudaoyuanma@123.com") | ||
| 31 | + @NotNull(message = "收件人不能为空") | ||
| 32 | + private List<String> tos; | ||
| 33 | + | ||
| 34 | + @ApiModelProperty(value = "附件",example = "附件编码") | ||
| 35 | + private List<String> fileIds; | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| @@ -126,5 +126,6 @@ public interface ErrorCodeConstants { | @@ -126,5 +126,6 @@ public interface ErrorCodeConstants { | ||
| 126 | // ========== 邮箱模版 1002020000 ========== | 126 | // ========== 邮箱模版 1002020000 ========== |
| 127 | ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1002020000 , "邮箱模版不存在"); | 127 | ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1002020000 , "邮箱模版不存在"); |
| 128 | ErrorCode MAIL_TEMPLATE_EXISTS = new ErrorCode(1002020001, "邮箱模版存在"); | 128 | ErrorCode MAIL_TEMPLATE_EXISTS = new ErrorCode(1002020001, "邮箱模版存在"); |
| 129 | + ErrorCode MAIL_RELATE_TEMPLATE_EXISTS = new ErrorCode(1002020002, "存在关联邮箱模版"); | ||
| 129 | 130 | ||
| 130 | } | 131 | } |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/mail/MailSendStatusEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.enums.mail; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 邮件的发送状态枚举 | ||
| 8 | + * | ||
| 9 | + * @author wangjingyi | ||
| 10 | + * @date 2022/4/10 13:39 | ||
| 11 | + */ | ||
| 12 | +@Getter | ||
| 13 | +@AllArgsConstructor | ||
| 14 | +public enum MailSendStatusEnum { | ||
| 15 | + | ||
| 16 | + INIT(0), // 初始化 | ||
| 17 | + SUCCESS(10), // 发送成功 | ||
| 18 | + FAILURE(20), // 发送失败 | ||
| 19 | + IGNORE(30), // 忽略,即不发送 | ||
| 20 | + ; | ||
| 21 | + | ||
| 22 | + private final int status; | ||
| 23 | + | ||
| 24 | +} |
yudao-module-system/yudao-module-system-impl/pom.xml
| @@ -49,6 +49,10 @@ | @@ -49,6 +49,10 @@ | ||
| 49 | </dependency> | 49 | </dependency> |
| 50 | <dependency> | 50 | <dependency> |
| 51 | <groupId>cn.iocoder.boot</groupId> | 51 | <groupId>cn.iocoder.boot</groupId> |
| 52 | + <artifactId>yudao-spring-boot-starter-biz-mail</artifactId> | ||
| 53 | + </dependency> | ||
| 54 | + <dependency> | ||
| 55 | + <groupId>cn.iocoder.boot</groupId> | ||
| 52 | <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId> | 56 | <artifactId>yudao-spring-boot-starter-biz-data-permission</artifactId> |
| 53 | </dependency> | 57 | </dependency> |
| 54 | <dependency> | 58 | <dependency> |
| @@ -102,6 +106,7 @@ | @@ -102,6 +106,7 @@ | ||
| 102 | <artifactId>yudao-spring-boot-starter-excel</artifactId> | 106 | <artifactId>yudao-spring-boot-starter-excel</artifactId> |
| 103 | </dependency> | 107 | </dependency> |
| 104 | 108 | ||
| 109 | + | ||
| 105 | </dependencies> | 110 | </dependencies> |
| 106 | 111 | ||
| 107 | </project> | 112 | </project> |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.mail; | ||
| 2 | + | ||
| 3 | +import org.springframework.stereotype.Service; | ||
| 4 | +import org.springframework.validation.annotation.Validated; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 邮件发送 API 接口 | ||
| 8 | + * | ||
| 9 | + * @author wangjingyi | ||
| 10 | + */ | ||
| 11 | +@Service | ||
| 12 | +@Validated | ||
| 13 | +public class MailSendApiImpl implements MailSendApi{ | ||
| 14 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/account/MailAccountBaseVO.java
| @@ -4,28 +4,34 @@ import io.swagger.annotations.ApiModel; | @@ -4,28 +4,34 @@ import io.swagger.annotations.ApiModel; | ||
| 4 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
| 5 | import lombok.Data; | 5 | import lombok.Data; |
| 6 | 6 | ||
| 7 | +import javax.validation.constraints.Email; | ||
| 7 | import javax.validation.constraints.NotNull; | 8 | import javax.validation.constraints.NotNull; |
| 8 | 9 | ||
| 9 | @ApiModel("管理后台 - 邮箱账号基类 Base VO") | 10 | @ApiModel("管理后台 - 邮箱账号基类 Base VO") |
| 10 | @Data | 11 | @Data |
| 11 | -public class MailAccountBaseVO { // TODO @wangjingqi:1), 不用空格;2)from、username、password、host、sslEnable 都要参数校验,非空;3)username 要 Email 格式;port Integer; | 12 | +public class MailAccountBaseVO { |
| 12 | 13 | ||
| 13 | - @ApiModelProperty(value = "邮箱" , required = true , example = "yudaoyuanma@123.com") | 14 | + @ApiModelProperty(value = "邮箱",required = true,example = "yudaoyuanma@123.com") |
| 15 | + @NotNull(message = "邮箱必填") | ||
| 14 | private String from; | 16 | private String from; |
| 15 | 17 | ||
| 16 | - @ApiModelProperty(value = "用户名" , required = true , example = "yudao") | 18 | + @ApiModelProperty(value = "用户名",required = true,example = "yudao") |
| 17 | @NotNull(message = "用户名必填") | 19 | @NotNull(message = "用户名必填") |
| 20 | + @Email(message = "必须是Email格式") | ||
| 18 | private String username; | 21 | private String username; |
| 19 | 22 | ||
| 20 | - @ApiModelProperty(value = "密码" , required = true , example = "123456") | 23 | + @ApiModelProperty(value = "密码",required = true,example = "123456") |
| 24 | + @NotNull(message = "密码必填") | ||
| 21 | private String password; | 25 | private String password; |
| 22 | 26 | ||
| 23 | - @ApiModelProperty(value = "网站" , required = true , example = "www.iocoder.cn") | 27 | + @ApiModelProperty(value = "网站",required = true,example = "www.iocoder.cn") |
| 28 | + @NotNull(message = "网站必填") | ||
| 24 | private String host; | 29 | private String host; |
| 25 | 30 | ||
| 26 | - @ApiModelProperty(value = "端口" , required = true , example = "80") | ||
| 27 | - private String port; | 31 | + @ApiModelProperty(value = "端口",required = true,example = "80") |
| 32 | + private Integer port; | ||
| 28 | 33 | ||
| 29 | - @ApiModelProperty(value = "是否开启ssl" , required = true , example = "2") | 34 | + @ApiModelProperty(value = "是否开启ssl",required = true,example = "2") |
| 35 | + @NotNull(message = "是否开启ssl必填") | ||
| 30 | private Boolean sslEnable; | 36 | private Boolean sslEnable; |
| 31 | } | 37 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogExcelVO.java
| @@ -6,6 +6,7 @@ import lombok.Data; | @@ -6,6 +6,7 @@ import lombok.Data; | ||
| 6 | import org.springframework.format.annotation.DateTimeFormat; | 6 | import org.springframework.format.annotation.DateTimeFormat; |
| 7 | 7 | ||
| 8 | import java.sql.Timestamp; | 8 | import java.sql.Timestamp; |
| 9 | +import java.util.Date; | ||
| 9 | 10 | ||
| 10 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | 11 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| 11 | 12 | ||
| @@ -30,10 +31,10 @@ public class MailLogExcelVO { | @@ -30,10 +31,10 @@ public class MailLogExcelVO { | ||
| 30 | 31 | ||
| 31 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | 32 | @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) |
| 32 | @ExcelProperty(value = "发送时间" ) | 33 | @ExcelProperty(value = "发送时间" ) |
| 33 | - private Timestamp sendTime; | 34 | + private Date sendTime; |
| 34 | 35 | ||
| 35 | @ExcelProperty(value = "发送状态") | 36 | @ExcelProperty(value = "发送状态") |
| 36 | - private Boolean sendStatus; | 37 | + private Integer sendStatus; |
| 37 | 38 | ||
| 38 | @ExcelProperty(value = "发送结果") | 39 | @ExcelProperty(value = "发送结果") |
| 39 | private String sendResult; | 40 | private String sendResult; |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/log/MailLogRespVO.java
| @@ -36,7 +36,7 @@ public class MailLogRespVO { | @@ -36,7 +36,7 @@ public class MailLogRespVO { | ||
| 36 | private Timestamp sendTime; | 36 | private Timestamp sendTime; |
| 37 | 37 | ||
| 38 | @ApiModelProperty(value = "发送状态" , required = false , example = "1") | 38 | @ApiModelProperty(value = "发送状态" , required = false , example = "1") |
| 39 | - private Boolean sendStatus; | 39 | + private Integer sendStatus; |
| 40 | 40 | ||
| 41 | @ApiModelProperty(value = "发送结果" , required = false , example = "yudaoyuanma@123.com") | 41 | @ApiModelProperty(value = "发送结果" , required = false , example = "yudaoyuanma@123.com") |
| 42 | private String sendResult; | 42 | private String sendResult; |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/send/MailReqVO.java
| @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel; | @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModel; | ||
| 4 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
| 5 | import lombok.Data; | 5 | import lombok.Data; |
| 6 | 6 | ||
| 7 | +import javax.validation.constraints.Email; | ||
| 7 | import javax.validation.constraints.NotNull; | 8 | import javax.validation.constraints.NotNull; |
| 8 | import java.util.List; | 9 | import java.util.List; |
| 9 | 10 | ||
| @@ -11,25 +12,26 @@ import java.util.List; | @@ -11,25 +12,26 @@ import java.util.List; | ||
| 11 | @Data | 12 | @Data |
| 12 | public class MailReqVO { // TODO @wangjingqi:1), 不用空格;2)应该只要传递 templateCode、参数就好,title、from、content、附件应该都是参数里的 | 13 | public class MailReqVO { // TODO @wangjingqi:1), 不用空格;2)应该只要传递 templateCode、参数就好,title、from、content、附件应该都是参数里的 |
| 13 | 14 | ||
| 14 | - @ApiModelProperty(value = "邮箱" , required = true , example = "yudaoyuanma@123.com") | 15 | + @ApiModelProperty(value = "邮箱",required = true,example = "yudaoyuanma@123.com") |
| 15 | @NotNull(message = "邮箱账号不能为空") | 16 | @NotNull(message = "邮箱账号不能为空") |
| 17 | + @Email(message = "邮箱账号格式错误") | ||
| 16 | private String from; | 18 | private String from; |
| 17 | 19 | ||
| 18 | - @ApiModelProperty(value = "标题" , example = "标题") | 20 | + @ApiModelProperty(value = "标题",example = "标题") |
| 19 | private String title; | 21 | private String title; |
| 20 | 22 | ||
| 21 | - @ApiModelProperty(value = "内容" , example = "内容") | 23 | + @ApiModelProperty(value = "内容",example = "内容") |
| 22 | private String content; | 24 | private String content; |
| 23 | 25 | ||
| 24 | - @ApiModelProperty(value = "邮箱模版id" , example = "1024") | 26 | + @ApiModelProperty(value = "邮箱模版id",example = "1024") |
| 25 | @NotNull(message = "邮箱模版id不能为空") | 27 | @NotNull(message = "邮箱模版id不能为空") |
| 26 | private Integer templateId; | 28 | private Integer templateId; |
| 27 | 29 | ||
| 28 | - @ApiModelProperty(value = "收件人" , required = true , example = "yudaoyuanma@123.com") | 30 | + @ApiModelProperty(value = "收件人",required = true,example = "yudaoyuanma@123.com") |
| 29 | @NotNull(message = "收件人不能为空") | 31 | @NotNull(message = "收件人不能为空") |
| 30 | private List<String> tos; | 32 | private List<String> tos; |
| 31 | 33 | ||
| 32 | - @ApiModelProperty(value = "附件" , example = "附件编码") | 34 | + @ApiModelProperty(value = "附件",example = "附件编码") |
| 33 | private List<String> fileIds; | 35 | private List<String> fileIds; |
| 34 | 36 | ||
| 35 | 37 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplateBaseVO.java
| @@ -4,15 +4,18 @@ import io.swagger.annotations.ApiModel; | @@ -4,15 +4,18 @@ import io.swagger.annotations.ApiModel; | ||
| 4 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
| 5 | import lombok.Data; | 5 | import lombok.Data; |
| 6 | 6 | ||
| 7 | +import javax.validation.constraints.Email; | ||
| 7 | import javax.validation.constraints.NotNull; | 8 | import javax.validation.constraints.NotNull; |
| 8 | 9 | ||
| 9 | @ApiModel("管ç†åŽå° - 邮箱模版基类 Base VO") | 10 | @ApiModel("管ç†åŽå° - 邮箱模版基类 Base VO") |
| 10 | @Data | 11 | @Data |
| 11 | -public class MailTemplateBaseVO { // TODO @wangjingqi:1)swagger 注解ä¸å®Œå–„ï¼›2)idã€nameã€codeã€usernameã€titleã€contentã€status æ˜¯ä¸æ˜¯è¦å‚æ•°æ ¡éªŒå‘€ | 12 | +public class MailTemplateBaseVO { |
| 12 | @ApiModelProperty("主键") | 13 | @ApiModelProperty("主键") |
| 14 | + @NotNull(message = "主键ä¸èƒ½ä¸ºç©º") | ||
| 13 | private Long id; | 15 | private Long id; |
| 14 | 16 | ||
| 15 | @ApiModelProperty("åç§°") | 17 | @ApiModelProperty("åç§°") |
| 18 | + @NotNull(message = "åç§°ä¸èƒ½ä¸ºç©º") | ||
| 16 | private String name; | 19 | private String name; |
| 17 | 20 | ||
| 18 | @ApiModelProperty("æ ‡è¯†") | 21 | @ApiModelProperty("æ ‡è¯†") |
| @@ -20,16 +23,21 @@ public class MailTemplateBaseVO { // TODO @wangjingqi:1)swagger 注解ä¸å® | @@ -20,16 +23,21 @@ public class MailTemplateBaseVO { // TODO @wangjingqi:1)swagger 注解ä¸å® | ||
| 20 | private String code; | 23 | private String code; |
| 21 | 24 | ||
| 22 | @ApiModelProperty("å‘件人") | 25 | @ApiModelProperty("å‘件人") |
| 26 | + @NotNull(message = "å‘件人ä¸èƒ½ä¸ºç©º") | ||
| 27 | + @Email(message = "å‘ä»¶äººæ ¼å¼æœ‰è¯¯") | ||
| 23 | private String username; | 28 | private String username; |
| 24 | 29 | ||
| 25 | @ApiModelProperty("æ ‡é¢˜") | 30 | @ApiModelProperty("æ ‡é¢˜") |
| 31 | + @NotNull(message = "æ ‡é¢˜ä¸èƒ½ä¸ºç©º") | ||
| 26 | private String title; | 32 | private String title; |
| 27 | 33 | ||
| 28 | @ApiModelProperty("内容") | 34 | @ApiModelProperty("内容") |
| 35 | + @NotNull(message = "内容ä¸èƒ½ä¸ºç©º") | ||
| 29 | private String content; | 36 | private String content; |
| 30 | 37 | ||
| 31 | @ApiModelProperty("状æ€") | 38 | @ApiModelProperty("状æ€") |
| 32 | - private String status; | 39 | + @NotNull(message = "状æ€ä¸èƒ½ä¸ºç©º") |
| 40 | + private Integer status; | ||
| 33 | 41 | ||
| 34 | @ApiModelProperty("备注") | 42 | @ApiModelProperty("备注") |
| 35 | private String remark; | 43 | private String remark; |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/mail/vo/template/MailTemplatePageReqVO.java
| @@ -31,7 +31,7 @@ public class MailTemplatePageReqVO extends PageParam { | @@ -31,7 +31,7 @@ public class MailTemplatePageReqVO extends PageParam { | ||
| 31 | private String content; | 31 | private String content; |
| 32 | 32 | ||
| 33 | @ApiModelProperty("状态") | 33 | @ApiModelProperty("状态") |
| 34 | - private String status; | 34 | + private Integer status; |
| 35 | 35 | ||
| 36 | @ApiModelProperty("备注") | 36 | @ApiModelProperty("备注") |
| 37 | private String remark; | 37 | private String remark; |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailLogDO.java
| 1 | package cn.iocoder.yudao.module.system.dal.dataobject.mail; | 1 | package cn.iocoder.yudao.module.system.dal.dataobject.mail; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 3 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 4 | +import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | ||
| 4 | import com.baomidou.mybatisplus.annotation.TableName; | 5 | import com.baomidou.mybatisplus.annotation.TableName; |
| 5 | -import lombok.Data; | ||
| 6 | -import lombok.EqualsAndHashCode; | 6 | +import lombok.*; |
| 7 | 7 | ||
| 8 | import java.io.Serializable; | 8 | import java.io.Serializable; |
| 9 | -import java.sql.Timestamp; | 9 | +import java.util.Date; |
| 10 | 10 | ||
| 11 | /** | 11 | /** |
| 12 | * 邮箱日志 | 12 | * 邮箱日志 |
| @@ -18,6 +18,10 @@ import java.sql.Timestamp; | @@ -18,6 +18,10 @@ import java.sql.Timestamp; | ||
| 18 | @TableName(value = "system_mail_log", autoResultMap = true) | 18 | @TableName(value = "system_mail_log", autoResultMap = true) |
| 19 | @Data | 19 | @Data |
| 20 | @EqualsAndHashCode(callSuper = true) | 20 | @EqualsAndHashCode(callSuper = true) |
| 21 | +@ToString(callSuper = true) | ||
| 22 | +@Builder | ||
| 23 | +@AllArgsConstructor | ||
| 24 | +@NoArgsConstructor | ||
| 21 | public class MailLogDO extends BaseDO implements Serializable { | 25 | public class MailLogDO extends BaseDO implements Serializable { |
| 22 | 26 | ||
| 23 | /** | 27 | /** |
| @@ -29,7 +33,7 @@ public class MailLogDO extends BaseDO implements Serializable { | @@ -29,7 +33,7 @@ public class MailLogDO extends BaseDO implements Serializable { | ||
| 29 | /** | 33 | /** |
| 30 | * 邮箱账号编号 | 34 | * 邮箱账号编号 |
| 31 | */ | 35 | */ |
| 32 | - private String accountCode; | 36 | + private Long accountId; |
| 33 | 37 | ||
| 34 | // TODO @wangjingyi:如果是冗余字段,记得 @ 下; | 38 | // TODO @wangjingyi:如果是冗余字段,记得 @ 下; |
| 35 | /** | 39 | /** |
| @@ -40,7 +44,7 @@ public class MailLogDO extends BaseDO implements Serializable { | @@ -40,7 +44,7 @@ public class MailLogDO extends BaseDO implements Serializable { | ||
| 40 | /** | 44 | /** |
| 41 | * 模版主键 | 45 | * 模版主键 |
| 42 | */ | 46 | */ |
| 43 | - private String templateId; | 47 | + private Long templateId; |
| 44 | 48 | ||
| 45 | /** | 49 | /** |
| 46 | * 模版编号 | 50 | * 模版编号 |
| @@ -65,16 +69,18 @@ public class MailLogDO extends BaseDO implements Serializable { | @@ -65,16 +69,18 @@ public class MailLogDO extends BaseDO implements Serializable { | ||
| 65 | /** | 69 | /** |
| 66 | * 发送时间 | 70 | * 发送时间 |
| 67 | */ | 71 | */ |
| 68 | - private Timestamp sendTime; | 72 | + private Date sendTime; |
| 69 | 73 | ||
| 70 | /** | 74 | /** |
| 71 | * 发送状态 | 75 | * 发送状态 |
| 76 | + * | ||
| 77 | + * 枚举 {@link MailSendStatusEnum} | ||
| 72 | */ | 78 | */ |
| 73 | - // TODO @wangjingyi:四个状态,参考短信模块 | ||
| 74 | - private Boolean sendStatus; | 79 | + private Integer sendStatus; |
| 75 | 80 | ||
| 76 | /** | 81 | /** |
| 77 | * 发送结果 | 82 | * 发送结果 |
| 83 | + * | ||
| 78 | */ | 84 | */ |
| 79 | private String sendResult; | 85 | private String sendResult; |
| 80 | 86 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/mail/MailTemplateDO.java
| @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableName; | @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableName; | ||
| 6 | import lombok.Data; | 6 | import lombok.Data; |
| 7 | import lombok.EqualsAndHashCode; | 7 | import lombok.EqualsAndHashCode; |
| 8 | 8 | ||
| 9 | +import java.util.Date; | ||
| 10 | + | ||
| 9 | /** | 11 | /** |
| 10 | * 邮箱模版 | 12 | * 邮箱模版 |
| 11 | * | 13 | * |
| @@ -29,11 +31,10 @@ public class MailTemplateDO extends BaseDO { | @@ -29,11 +31,10 @@ public class MailTemplateDO extends BaseDO { | ||
| 29 | * 模版编号 | 31 | * 模版编号 |
| 30 | */ | 32 | */ |
| 31 | private String code; | 33 | private String code; |
| 32 | - // TODO @wangjingyi:应该使用 accountId 呀 | ||
| 33 | /** | 34 | /** |
| 34 | - * 用户名 | 35 | + * 邮箱账号主键 |
| 35 | */ | 36 | */ |
| 36 | - private String username; | 37 | + private Long accountId; |
| 37 | /** | 38 | /** |
| 38 | * 标题 | 39 | * 标题 |
| 39 | */ | 40 | */ |
| @@ -47,7 +48,7 @@ public class MailTemplateDO extends BaseDO { | @@ -47,7 +48,7 @@ public class MailTemplateDO extends BaseDO { | ||
| 47 | * | 48 | * |
| 48 | * 枚举 {@link CommonStatusEnum} | 49 | * 枚举 {@link CommonStatusEnum} |
| 49 | */ | 50 | */ |
| 50 | - private String status; // TODO @wangjingyi:Integer | 51 | + private Integer status; |
| 51 | /** | 52 | /** |
| 52 | * 备注 | 53 | * 备注 |
| 53 | */ | 54 | */ |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailAccountMapper.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | ||
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; |
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 10 | ||
| 10 | @Mapper | 11 | @Mapper |
| @@ -21,9 +22,7 @@ public interface MailAccountMapper extends BaseMapperX<MailAccountDO> { | @@ -21,9 +22,7 @@ public interface MailAccountMapper extends BaseMapperX<MailAccountDO> { | ||
| 21 | } | 22 | } |
| 22 | 23 | ||
| 23 | default MailAccountDO selectByUserName(String userName){ | 24 | default MailAccountDO selectByUserName(String userName){ |
| 24 | - // TODO @wangjingyi:selectOne 有封装的方法;然后,编码一定要学会使用泛型呀。例如说 QueryWrapperX<MailAccountDO> queryWrapperX = new QueryWrapperX<>(); | ||
| 25 | - QueryWrapperX<MailAccountDO> queryWrapperX = new QueryWrapperX<>(); | ||
| 26 | - queryWrapperX.eqIfPresent("username", userName); | ||
| 27 | - return this.selectOne(queryWrapperX); | 25 | + return selectOne(new QueryWrapperX<MailAccountDO>() |
| 26 | + .eqIfPresent("username" , userName)); | ||
| 28 | }; | 27 | }; |
| 29 | } | 28 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/mail/MailTemplateMapper.java
| @@ -6,6 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | @@ -6,6 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | +import org.apache.ibatis.annotations.Select; | ||
| 10 | + | ||
| 11 | +import java.util.Date; | ||
| 9 | 12 | ||
| 10 | 13 | ||
| 11 | @Mapper | 14 | @Mapper |
| @@ -23,7 +26,15 @@ public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> { | @@ -23,7 +26,15 @@ public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> { | ||
| 23 | } | 26 | } |
| 24 | 27 | ||
| 25 | default MailTemplateDO selectOneByCode(String code){ | 28 | default MailTemplateDO selectOneByCode(String code){ |
| 26 | - // TODO @wangjingyi:优先使用 lambada 查询 | ||
| 27 | - return selectOne("code" , code); | 29 | + return selectOne(new QueryWrapperX<MailTemplateDO>() |
| 30 | + .eqIfPresent("code" , code)); | ||
| 31 | + }; | ||
| 32 | + | ||
| 33 | + @Select("SELECT id FROM system_mail_template WHERE update_time > #{maxUpdateTime} LIMIT 1") | ||
| 34 | + Long selectByMaxUpdateTime(Date maxUpdateTime); | ||
| 35 | + | ||
| 36 | + default MailTemplateDO selectOneByAccountId(Long accountId){ | ||
| 37 | + return selectOne(new QueryWrapperX<MailTemplateDO>() | ||
| 38 | + .eqIfPresent("account_id" , accountId)); | ||
| 28 | }; | 39 | }; |
| 29 | } | 40 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/mail/MailSendConsumer.java
| @@ -2,17 +2,23 @@ package cn.iocoder.yudao.module.system.mq.consumer.mail; | @@ -2,17 +2,23 @@ package cn.iocoder.yudao.module.system.mq.consumer.mail; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; | 3 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; |
| 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; |
| 5 | +import cn.iocoder.yudao.module.system.service.mail.MailSendService; | ||
| 5 | import lombok.extern.slf4j.Slf4j; | 6 | import lombok.extern.slf4j.Slf4j; |
| 6 | import org.springframework.stereotype.Component; | 7 | import org.springframework.stereotype.Component; |
| 7 | 8 | ||
| 8 | -// TODO 芋艿:这个暂未实现 | 9 | +import javax.annotation.Resource; |
| 10 | + | ||
| 11 | + | ||
| 9 | @Component | 12 | @Component |
| 10 | @Slf4j | 13 | @Slf4j |
| 11 | public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> { | 14 | public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> { |
| 12 | 15 | ||
| 16 | + @Resource | ||
| 17 | + private MailSendService mailSendService; | ||
| 13 | @Override | 18 | @Override |
| 14 | public void onMessage(MailSendMessage message) { | 19 | public void onMessage(MailSendMessage message) { |
| 15 | log.info("[onMessage][消息内容({})]", message); | 20 | log.info("[onMessage][消息内容({})]", message); |
| 21 | + mailSendService.doSendMail(message); | ||
| 16 | } | 22 | } |
| 17 | 23 | ||
| 18 | } | 24 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java
| @@ -5,6 +5,7 @@ import lombok.Data; | @@ -5,6 +5,7 @@ import lombok.Data; | ||
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | 6 | ||
| 7 | import javax.validation.constraints.NotNull; | 7 | import javax.validation.constraints.NotNull; |
| 8 | +import java.util.List; | ||
| 8 | import java.util.Map; | 9 | import java.util.Map; |
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| @@ -17,28 +18,33 @@ import java.util.Map; | @@ -17,28 +18,33 @@ import java.util.Map; | ||
| 17 | public class MailSendMessage extends AbstractStreamMessage { | 18 | public class MailSendMessage extends AbstractStreamMessage { |
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| 21 | + * 日志id | ||
| 22 | + */ | ||
| 23 | + @NotNull(message = "邮箱日志id不能为空") | ||
| 24 | + private Long logId; | ||
| 25 | + /** | ||
| 20 | * 邮箱地址 | 26 | * 邮箱地址 |
| 21 | */ | 27 | */ |
| 22 | @NotNull(message = "邮箱地址不能为空") | 28 | @NotNull(message = "邮箱地址不能为空") |
| 23 | - private String address; | 29 | + private String from; |
| 24 | /** | 30 | /** |
| 25 | - * 短信模板编号 | 31 | + * 邮箱模板编号 |
| 26 | */ | 32 | */ |
| 27 | - @NotNull(message = "短信模板编号不能为空") | 33 | + @NotNull(message = "邮箱模板编号不能为空") |
| 28 | private String templateCode; | 34 | private String templateCode; |
| 29 | /** | 35 | /** |
| 30 | - * 短信模板参数 | 36 | + * 收件人 |
| 31 | */ | 37 | */ |
| 32 | - private Map<String, Object> templateParams; | ||
| 33 | - | 38 | + @NotNull(message = "收件人不能为空") |
| 39 | + private List<String> tos; | ||
| 34 | /** | 40 | /** |
| 35 | - * 用户编号,允许空 | 41 | + * 标题 |
| 36 | */ | 42 | */ |
| 37 | - private Integer userId; | 43 | + private String title; |
| 38 | /** | 44 | /** |
| 39 | - * 用户类型,允许空 | 45 | + * 内容 |
| 40 | */ | 46 | */ |
| 41 | - private Integer userType; | 47 | + private String content; |
| 42 | 48 | ||
| 43 | @Override | 49 | @Override |
| 44 | public String getStreamKey() { | 50 | public String getStreamKey() { |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.mq.producer.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.core.KeyValue; | ||
| 4 | +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; | ||
| 5 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 6 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 7 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 8 | +import cn.iocoder.yudao.module.system.mq.message.sms.SmsChannelRefreshMessage; | ||
| 9 | +import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; | ||
| 10 | +import cn.iocoder.yudao.module.system.mq.message.sms.SmsTemplateRefreshMessage; | ||
| 11 | +import lombok.extern.slf4j.Slf4j; | ||
| 12 | +import org.springframework.stereotype.Component; | ||
| 13 | + | ||
| 14 | +import javax.annotation.Resource; | ||
| 15 | +import java.util.List; | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * Mail 邮件相关消息的 Producer | ||
| 19 | + * | ||
| 20 | + * @author wangjingyi | ||
| 21 | + * @date 2021/4/19 13:33 | ||
| 22 | + */ | ||
| 23 | +@Slf4j | ||
| 24 | +@Component | ||
| 25 | +public class MailProducer { | ||
| 26 | + | ||
| 27 | + @Resource | ||
| 28 | + private RedisMQTemplate redisMQTemplate; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 发送 {@link SmsChannelRefreshMessage} 消息 | ||
| 32 | + */ | ||
| 33 | + public void sendMailChannelRefreshMessage() { | ||
| 34 | + SmsChannelRefreshMessage message = new SmsChannelRefreshMessage(); | ||
| 35 | + redisMQTemplate.send(message); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * 发送 {@link SmsTemplateRefreshMessage} 消息 | ||
| 40 | + */ | ||
| 41 | + public void sendMailTemplateRefreshMessage() { | ||
| 42 | + SmsTemplateRefreshMessage message = new SmsTemplateRefreshMessage(); | ||
| 43 | + redisMQTemplate.send(message); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 发送 {@link MailSendMessage} 消息 | ||
| 48 | + * | ||
| 49 | + * @param mailAccountDO 邮箱账号信息 | ||
| 50 | + * @param mailTemplateDO 邮箱模版信息 | ||
| 51 | + * @param content 内容 | ||
| 52 | + * @param tos 收件人 | ||
| 53 | + * @param title 标题 | ||
| 54 | + */ | ||
| 55 | + public void sendMailSendMessage(MailAccountDO mailAccountDO, MailTemplateDO mailTemplateDO, String content, List<String> tos, String title , Long sendLogId) { | ||
| 56 | + MailSendMessage message = new MailSendMessage(); | ||
| 57 | + message.setContent(content); | ||
| 58 | + message.setFrom(mailAccountDO.getFrom()); | ||
| 59 | + message.setTemplateCode(mailTemplateDO.getCode()); | ||
| 60 | + message.setTitle(title); | ||
| 61 | + message.setTos(tos); | ||
| 62 | + message.setLogId(sendLogId); | ||
| 63 | + redisMQTemplate.send(message); | ||
| 64 | + } | ||
| 65 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailLogService.java
| @@ -4,7 +4,9 @@ package cn.iocoder.yudao.module.system.service.mail; | @@ -4,7 +4,9 @@ package cn.iocoder.yudao.module.system.service.mail; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogExportReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogExportReqVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; |
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | 10 | ||
| 9 | import java.util.List; | 11 | import java.util.List; |
| 10 | 12 | ||
| @@ -28,4 +30,18 @@ public interface MailLogService { | @@ -28,4 +30,18 @@ public interface MailLogService { | ||
| 28 | * @return | 30 | * @return |
| 29 | */ | 31 | */ |
| 30 | List<MailLogDO> getMailLogList(MailLogExportReqVO exportReqVO); | 32 | List<MailLogDO> getMailLogList(MailLogExportReqVO exportReqVO); |
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 创建邮箱日志 | ||
| 36 | + * @param mailAccountDO 邮箱账号信息 | ||
| 37 | + * @param mailTemplateDO 模版信息 | ||
| 38 | + * @param from 邮箱 | ||
| 39 | + * @param content 内容 | ||
| 40 | + * @param tos 收件人 | ||
| 41 | + * @param title 标题 | ||
| 42 | + * @param isSend 是否发送成功 | ||
| 43 | + */ | ||
| 44 | + Long createMailLog(MailAccountDO mailAccountDO, MailTemplateDO mailTemplateDO, String from, String content, List<String> tos, String title, Boolean isSend); | ||
| 45 | + | ||
| 46 | + Long updateSmsSendResult(Long logId, String result); | ||
| 31 | } | 47 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.send.MailReqVO; | ||
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | ||
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 10 | + | ||
| 11 | +import javax.validation.Valid; | ||
| 12 | +import java.util.List; | ||
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 邮箱模版服务类 | ||
| 17 | + * | ||
| 18 | + * @author wangjingyi | ||
| 19 | + * @since 2022-03-21 | ||
| 20 | + */ | ||
| 21 | +public interface MailSendService { | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 发送邮件 | ||
| 25 | + * | ||
| 26 | + * @param templateCode 邮件模版编码 | ||
| 27 | + * @param from 邮箱 | ||
| 28 | + * @param content 内容 | ||
| 29 | + * @param tos 收件人 | ||
| 30 | + * @param title 标题 | ||
| 31 | + */ | ||
| 32 | + void sendMail(String templateCode, String from , String content , List<String> tos , String title); | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 执行真正的邮件发送 | ||
| 36 | + * 注意,该方法仅仅提供给 MQ Consumer 使用 | ||
| 37 | + * | ||
| 38 | + * @param message 邮件 | ||
| 39 | + */ | ||
| 40 | + void doSendMail(MailSendMessage message); | ||
| 41 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateService.java
| @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | 9 | ||
| 10 | import javax.validation.Valid; | 10 | import javax.validation.Valid; |
| 11 | import java.util.List; | 11 | import java.util.List; |
| 12 | +import java.util.Map; | ||
| 12 | 13 | ||
| 13 | /** | 14 | /** |
| 14 | * 邮箱模版服务类 | 15 | * 邮箱模版服务类 |
| @@ -18,6 +19,7 @@ import java.util.List; | @@ -18,6 +19,7 @@ import java.util.List; | ||
| 18 | */ | 19 | */ |
| 19 | public interface MailTemplateService { | 20 | public interface MailTemplateService { |
| 20 | 21 | ||
| 22 | + void initLocalCache(); | ||
| 21 | /** | 23 | /** |
| 22 | * 邮箱模版创建 | 24 | * 邮箱模版创建 |
| 23 | * | 25 | * |
| @@ -62,6 +64,13 @@ public interface MailTemplateService { | @@ -62,6 +64,13 @@ public interface MailTemplateService { | ||
| 62 | * @return 模版数组 | 64 | * @return 模版数组 |
| 63 | */ | 65 | */ |
| 64 | List<MailTemplateDO> getMailTemplateList(); | 66 | List<MailTemplateDO> getMailTemplateList(); |
| 67 | + /** | ||
| 68 | + *从缓存中获取邮箱模版 | ||
| 69 | + * | ||
| 70 | + * @param code 模板编码 | ||
| 71 | + * @return 邮箱模板 | ||
| 72 | + */ | ||
| 73 | + MailTemplateDO getMailTemplateByCodeFromCache(String code); | ||
| 65 | 74 | ||
| 66 | /** | 75 | /** |
| 67 | * 发送邮件 | 76 | * 发送邮件 |
| @@ -69,4 +78,12 @@ public interface MailTemplateService { | @@ -69,4 +78,12 @@ public interface MailTemplateService { | ||
| 69 | * @param mailReqVO 邮件发送信息 | 78 | * @param mailReqVO 邮件发送信息 |
| 70 | */ | 79 | */ |
| 71 | void sendMail(MailReqVO mailReqVO); | 80 | void sendMail(MailReqVO mailReqVO); |
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * 邮件模版内容合成 | ||
| 84 | + * @param content 邮箱模版 | ||
| 85 | + * @param params 合成参数 | ||
| 86 | + * @return | ||
| 87 | + */ | ||
| 88 | + String formateMailTemplateContent(String content, Map<String, String> params); | ||
| 72 | } | 89 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/impl/MailAccountServiceImpl.java
| @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou | @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccou | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | 7 | import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; |
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; |
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; |
| 10 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; | 11 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; |
| 11 | import cn.iocoder.yudao.module.system.service.mail.MailAccountService; | 12 | import cn.iocoder.yudao.module.system.service.mail.MailAccountService; |
| @@ -16,8 +17,7 @@ import javax.annotation.Resource; | @@ -16,8 +17,7 @@ import javax.annotation.Resource; | ||
| 16 | import java.util.List; | 17 | import java.util.List; |
| 17 | 18 | ||
| 18 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 19 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_EXISTS; | ||
| 20 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_NOT_EXISTS; | 20 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | /** | 23 | /** |
| @@ -47,8 +47,8 @@ public class MailAccountServiceImpl implements MailAccountService { | @@ -47,8 +47,8 @@ public class MailAccountServiceImpl implements MailAccountService { | ||
| 47 | 47 | ||
| 48 | @Override | 48 | @Override |
| 49 | public void update(MailAccountUpdateReqVO updateReqVO) { | 49 | public void update(MailAccountUpdateReqVO updateReqVO) { |
| 50 | - // username 要校验唯一 // TODO @wangjingyi:更新的就是自己,username 这样写,会重复呀。 | ||
| 51 | - this.validateMailAccountOnlyByUserName(updateReqVO.getUsername()); | 50 | + // username 要校验唯一 |
| 51 | + this.validateMailAccountExists(updateReqVO.getId()); | ||
| 52 | MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(updateReqVO); | 52 | MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(updateReqVO); |
| 53 | // 校验是否存在 | 53 | // 校验是否存在 |
| 54 | this.validateMailAccountExists(mailAccountDO.getId()); | 54 | this.validateMailAccountExists(mailAccountDO.getId()); |
| @@ -57,9 +57,10 @@ public class MailAccountServiceImpl implements MailAccountService { | @@ -57,9 +57,10 @@ public class MailAccountServiceImpl implements MailAccountService { | ||
| 57 | 57 | ||
| 58 | @Override | 58 | @Override |
| 59 | public void delete(Long id) { | 59 | public void delete(Long id) { |
| 60 | - // TODO @wangjingyi:删除时,要判断是否有使用的模板 | ||
| 61 | - // 校验是否存在 | 60 | + // 校验是否存在账号 |
| 62 | this.validateMailAccountExists(id); | 61 | this.validateMailAccountExists(id); |
| 62 | + // 校验是否存在关联模版 | ||
| 63 | + this.validateMailTemplateByAccountId(id); | ||
| 63 | mailAccountMapper.deleteById(id); | 64 | mailAccountMapper.deleteById(id); |
| 64 | } | 65 | } |
| 65 | 66 | ||
| @@ -90,4 +91,11 @@ public class MailAccountServiceImpl implements MailAccountService { | @@ -90,4 +91,11 @@ public class MailAccountServiceImpl implements MailAccountService { | ||
| 90 | throw exception(MAIL_ACCOUNT_EXISTS); | 91 | throw exception(MAIL_ACCOUNT_EXISTS); |
| 91 | } | 92 | } |
| 92 | } | 93 | } |
| 94 | + | ||
| 95 | + private void validateMailTemplateByAccountId(Long accountId){ | ||
| 96 | + MailTemplateDO mailTemplateDO = mailTemplateMapper.selectOneByAccountId(accountId); | ||
| 97 | + if (mailTemplateDO != null) { | ||
| 98 | + throw exception(MAIL_RELATE_TEMPLATE_EXISTS); | ||
| 99 | + } | ||
| 100 | + } | ||
| 93 | } | 101 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/impl/MailLogServiceImpl.java
| @@ -4,14 +4,21 @@ package cn.iocoder.yudao.module.system.service.mail.impl; | @@ -4,14 +4,21 @@ package cn.iocoder.yudao.module.system.service.mail.impl; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogExportReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogExportReqVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO; |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO; |
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 8 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper; |
| 11 | +import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum; | ||
| 12 | +import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum; | ||
| 9 | import cn.iocoder.yudao.module.system.service.mail.MailLogService; | 13 | import cn.iocoder.yudao.module.system.service.mail.MailLogService; |
| 10 | import org.springframework.beans.factory.annotation.Autowired; | 14 | import org.springframework.beans.factory.annotation.Autowired; |
| 11 | import org.springframework.stereotype.Service; | 15 | import org.springframework.stereotype.Service; |
| 12 | import org.springframework.validation.annotation.Validated; | 16 | import org.springframework.validation.annotation.Validated; |
| 13 | 17 | ||
| 18 | +import java.sql.Timestamp; | ||
| 19 | +import java.util.Date; | ||
| 14 | import java.util.List; | 20 | import java.util.List; |
| 21 | +import java.util.Objects; | ||
| 15 | 22 | ||
| 16 | /** | 23 | /** |
| 17 | * 邮箱日志实现类 | 24 | * 邮箱日志实现类 |
| @@ -35,4 +42,39 @@ public class MailLogServiceImpl implements MailLogService { | @@ -35,4 +42,39 @@ public class MailLogServiceImpl implements MailLogService { | ||
| 35 | public List<MailLogDO> getMailLogList(MailLogExportReqVO exportReqVO) { | 42 | public List<MailLogDO> getMailLogList(MailLogExportReqVO exportReqVO) { |
| 36 | return mailLogMapper.selectList(exportReqVO); | 43 | return mailLogMapper.selectList(exportReqVO); |
| 37 | } | 44 | } |
| 45 | + | ||
| 46 | + @Override | ||
| 47 | + public Long createMailLog(MailAccountDO mailAccountDO , MailTemplateDO mailTemplateDO , String from, String content, List<String> tos, String title, Boolean isSend) { | ||
| 48 | + MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder(); | ||
| 49 | + logDOBuilder.from(mailAccountDO.getFrom()); | ||
| 50 | + logDOBuilder.accountId(mailAccountDO.getId()); | ||
| 51 | + logDOBuilder.content(content); | ||
| 52 | + logDOBuilder.title(title); | ||
| 53 | + logDOBuilder.templateCode(mailTemplateDO.getCode()); | ||
| 54 | + logDOBuilder.templateId(mailTemplateDO.getId()); | ||
| 55 | + logDOBuilder.to(tos.toString()); | ||
| 56 | + logDOBuilder.sendTime(new Date()); | ||
| 57 | + logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus() | ||
| 58 | + : MailSendStatusEnum.IGNORE.getStatus()); | ||
| 59 | + | ||
| 60 | + MailLogDO mailLogDO = logDOBuilder.build(); | ||
| 61 | + mailLogMapper.insert(mailLogDO); | ||
| 62 | + return mailLogDO.getId(); | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public Long updateSmsSendResult(Long logId, String result) { | ||
| 67 | + MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder(); | ||
| 68 | + logDOBuilder.id(logId); | ||
| 69 | + logDOBuilder.sendResult(result); | ||
| 70 | + MailLogDO mailLogDO = logDOBuilder.build(); | ||
| 71 | + mailLogMapper.updateById(mailLogDO); | ||
| 72 | + return logId; | ||
| 73 | + } | ||
| 74 | + | ||
| 75 | + public Long create(){ | ||
| 76 | + MailLogDO mailLogDO = new MailLogDO(); | ||
| 77 | + mailLogMapper.insert(mailLogDO); | ||
| 78 | + return mailLogDO.getId(); | ||
| 79 | + } | ||
| 38 | } | 80 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/impl/MailSendServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.mail.impl; | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +import cn.hutool.extra.mail.MailAccount; | ||
| 5 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 6 | +import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | ||
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | ||
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | ||
| 9 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | ||
| 10 | +import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; | ||
| 11 | +import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; | ||
| 12 | +import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; | ||
| 13 | +import cn.iocoder.yudao.module.system.service.mail.MailLogService; | ||
| 14 | +import cn.iocoder.yudao.module.system.service.mail.MailSendService; | ||
| 15 | +import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; | ||
| 16 | +import lombok.extern.slf4j.Slf4j; | ||
| 17 | +import cn.iocoder.yudao.framework.mail.core.client.MailClientFactory; | ||
| 18 | +import org.springframework.stereotype.Service; | ||
| 19 | +import org.springframework.validation.annotation.Validated; | ||
| 20 | +import cn.iocoder.yudao.framework.mail.core.client.MailClient; | ||
| 21 | + | ||
| 22 | +import javax.annotation.Resource; | ||
| 23 | +import java.util.List; | ||
| 24 | +import java.util.Map; | ||
| 25 | + | ||
| 26 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 27 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_EXISTS; | ||
| 28 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS; | ||
| 29 | + | ||
| 30 | +/** | ||
| 31 | + * 邮箱模版 服务实现类 | ||
| 32 | + * | ||
| 33 | + * @author wangjingyi | ||
| 34 | + * @since 2022-03-21 | ||
| 35 | + */ | ||
| 36 | +@Service | ||
| 37 | +@Validated | ||
| 38 | +@Slf4j | ||
| 39 | +public class MailSendServiceImpl implements MailSendService { | ||
| 40 | + | ||
| 41 | + @Resource | ||
| 42 | + private MailTemplateMapper mailTemplateMapper; | ||
| 43 | + @Resource | ||
| 44 | + private MailAccountMapper mailAccountMapper; | ||
| 45 | + @Resource | ||
| 46 | + private MailTemplateService mailTemplateService; | ||
| 47 | + @Resource | ||
| 48 | + private MailLogService mailLogService; | ||
| 49 | + @Resource | ||
| 50 | + private MailClientFactory mailClientFactory; | ||
| 51 | + @Resource | ||
| 52 | + private MailProducer mailProducer; | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + @Override | ||
| 56 | + public void sendMail(String templateCode, String from , String content , List<String> tos , String title) { | ||
| 57 | + // TODO @@wangjingyi:发送的时候,参考下短信; | ||
| 58 | + MailTemplateDO mailTemplateDO = this.checkMailTemplateValid(templateCode); | ||
| 59 | + // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志 | ||
| 60 | + Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(mailTemplateDO.getStatus()); | ||
| 61 | + //查询账号信息 | ||
| 62 | + MailAccountDO mailAccountDO = mailAccountMapper.selectOne( | ||
| 63 | + "from", from | ||
| 64 | + ); | ||
| 65 | + Map<String , String> params = MailAccountConvert.INSTANCE.convertToMap(mailAccountDO , content); | ||
| 66 | + content = mailTemplateService.formateMailTemplateContent(mailTemplateDO.getContent(), params); | ||
| 67 | + Long sendLogId = mailLogService.createMailLog(mailAccountDO , mailTemplateDO , from , content , tos , title , isSend); | ||
| 68 | + | ||
| 69 | + // 后续功能 TODO :附件查询 | ||
| 70 | + //List<String> fileIds = mailSendVO.getFileIds(); | ||
| 71 | + | ||
| 72 | + //装载账号信息 | ||
| 73 | + MailAccount account = MailAccountConvert.INSTANCE.convertAccount(mailAccountDO); | ||
| 74 | + | ||
| 75 | + // 发送 MQ 消息,异步执行发送短信 | ||
| 76 | + if (isSend) { | ||
| 77 | + mailProducer.sendMailSendMessage(mailAccountDO , mailTemplateDO ,content , tos , title , sendLogId); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + @Override | ||
| 82 | + public void doSendMail(MailSendMessage message) { | ||
| 83 | + MailClient mailClient = mailClientFactory.getMailClient(); | ||
| 84 | + String result = mailClient.sendMail(message.getFrom() , message.getContent() , message.getTitle() , message.getTos()); | ||
| 85 | + mailLogService.updateSmsSendResult(message.getLogId() , result); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + private MailTemplateDO checkMailTemplateValid(String templateCode) { | ||
| 89 | + MailTemplateDO mailTemplateDO = mailTemplateService.getMailTemplateByCodeFromCache(templateCode); | ||
| 90 | + if (mailTemplateDO == null){ | ||
| 91 | + throw exception(MAIL_TEMPLATE_NOT_EXISTS); | ||
| 92 | + } | ||
| 93 | + return mailTemplateDO; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + private void validateMailTemplateExists(Long id) { | ||
| 97 | + if (mailTemplateMapper.selectById(id) == null) { | ||
| 98 | + throw exception(MAIL_TEMPLATE_NOT_EXISTS); | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + private void validateMailTemplateOnlyByCode(String code){ | ||
| 103 | + if (mailTemplateMapper.selectOneByCode(code) != null) { | ||
| 104 | + throw exception(MAIL_TEMPLATE_EXISTS); | ||
| 105 | + } | ||
| 106 | + } | ||
| 107 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/mail/impl/MailTemplateServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.mail.impl; | 1 | package cn.iocoder.yudao.module.system.service.mail.impl; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.hutool.extra.mail.MailAccount; | 6 | import cn.hutool.extra.mail.MailAccount; |
| 6 | import cn.hutool.extra.mail.MailUtil; | 7 | import cn.hutool.extra.mail.MailUtil; |
| 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 8 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.send.MailReqVO; | 10 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.send.MailReqVO; |
| 9 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; | 11 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO; |
| 10 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; | 12 | import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO; |
| @@ -13,14 +15,18 @@ import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | @@ -13,14 +15,18 @@ import cn.iocoder.yudao.module.system.convert.mail.MailAccountConvert; | ||
| 13 | import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; | 15 | import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert; |
| 14 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; | 16 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO; |
| 15 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; | 17 | import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO; |
| 18 | +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; | ||
| 16 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; | 19 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailAccountMapper; |
| 17 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; | 20 | import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper; |
| 18 | import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; | 21 | import cn.iocoder.yudao.module.system.service.mail.MailTemplateService; |
| 22 | +import lombok.extern.slf4j.Slf4j; | ||
| 19 | import org.springframework.stereotype.Service; | 23 | import org.springframework.stereotype.Service; |
| 20 | import org.springframework.validation.annotation.Validated; | 24 | import org.springframework.validation.annotation.Validated; |
| 21 | 25 | ||
| 26 | +import javax.annotation.PostConstruct; | ||
| 22 | import javax.annotation.Resource; | 27 | import javax.annotation.Resource; |
| 23 | import javax.validation.Valid; | 28 | import javax.validation.Valid; |
| 29 | +import java.util.Date; | ||
| 24 | import java.util.List; | 30 | import java.util.List; |
| 25 | import java.util.Map; | 31 | import java.util.Map; |
| 26 | 32 | ||
| @@ -36,6 +42,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPL | @@ -36,6 +42,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPL | ||
| 36 | */ | 42 | */ |
| 37 | @Service | 43 | @Service |
| 38 | @Validated | 44 | @Validated |
| 45 | +@Slf4j | ||
| 39 | public class MailTemplateServiceImpl implements MailTemplateService { | 46 | public class MailTemplateServiceImpl implements MailTemplateService { |
| 40 | 47 | ||
| 41 | @Resource | 48 | @Resource |
| @@ -43,6 +50,38 @@ public class MailTemplateServiceImpl implements MailTemplateService { | @@ -43,6 +50,38 @@ public class MailTemplateServiceImpl implements MailTemplateService { | ||
| 43 | @Resource | 50 | @Resource |
| 44 | private MailAccountMapper mailAccountMapper; | 51 | private MailAccountMapper mailAccountMapper; |
| 45 | 52 | ||
| 53 | + private volatile List<MailTemplateDO> mailTemplateDOList; | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 邮件模板缓存 | ||
| 57 | + * key:邮箱模板编码 {@link MailTemplateDO#getCode()} | ||
| 58 | + * | ||
| 59 | + * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 | ||
| 60 | + */ | ||
| 61 | + private volatile Map<String, MailTemplateDO> mailTemplateCache; | ||
| 62 | + | ||
| 63 | + private volatile Date maxUpdateTime; | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + @PostConstruct | ||
| 67 | + public void initLocalCache() { | ||
| 68 | + if(maxUpdateTime == null){ | ||
| 69 | + mailTemplateDOList = mailTemplateMapper.selectList(); | ||
| 70 | + }else{ | ||
| 71 | + if(mailTemplateMapper.selectByMaxUpdateTime(maxUpdateTime)<=0){ | ||
| 72 | + return; | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + if (CollUtil.isEmpty(mailTemplateDOList)) { | ||
| 76 | + return; | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + // 写入缓存 | ||
| 80 | + mailTemplateCache = CollectionUtils.convertMap(mailTemplateDOList, MailTemplateDO::getCode); | ||
| 81 | + maxUpdateTime = CollectionUtils.getMaxValue(mailTemplateDOList, MailTemplateDO::getUpdateTime); | ||
| 82 | + log.info("[initLocalCache][初始化 mailTemplate 数量为 {}]", mailTemplateDOList.size()); | ||
| 83 | + } | ||
| 84 | + | ||
| 46 | @Override | 85 | @Override |
| 47 | public Long create(MailTemplateCreateReqVO createReqVO) { | 86 | public Long create(MailTemplateCreateReqVO createReqVO) { |
| 48 | // code 要校验唯一 | 87 | // code 要校验唯一 |
| @@ -54,11 +93,9 @@ public class MailTemplateServiceImpl implements MailTemplateService { | @@ -54,11 +93,9 @@ public class MailTemplateServiceImpl implements MailTemplateService { | ||
| 54 | 93 | ||
| 55 | @Override | 94 | @Override |
| 56 | public void update(@Valid MailTemplateUpdateReqVO updateReqVO) { | 95 | public void update(@Valid MailTemplateUpdateReqVO updateReqVO) { |
| 57 | - // code 要校验唯一 | ||
| 58 | - this.validateMailTemplateOnlyByCode(updateReqVO.getCode()); // TODO @wangjingyi:code 这样写,修改自己会有问题 | ||
| 59 | - MailTemplateDO mailTemplateDO = MailTemplateConvert.INSTANCE.convert(updateReqVO); | ||
| 60 | // 校验是否存在 | 96 | // 校验是否存在 |
| 61 | - this.validateMailTemplateExists(mailTemplateDO.getId()); | 97 | + this.validateMailTemplateExists(updateReqVO.getId()); |
| 98 | + MailTemplateDO mailTemplateDO = MailTemplateConvert.INSTANCE.convert(updateReqVO); | ||
| 62 | mailTemplateMapper.updateById(mailTemplateDO); | 99 | mailTemplateMapper.updateById(mailTemplateDO); |
| 63 | } | 100 | } |
| 64 | 101 | ||
| @@ -81,6 +118,11 @@ public class MailTemplateServiceImpl implements MailTemplateService { | @@ -81,6 +118,11 @@ public class MailTemplateServiceImpl implements MailTemplateService { | ||
| 81 | public List<MailTemplateDO> getMailTemplateList() {return mailTemplateMapper.selectList();} | 118 | public List<MailTemplateDO> getMailTemplateList() {return mailTemplateMapper.selectList();} |
| 82 | 119 | ||
| 83 | @Override | 120 | @Override |
| 121 | + public MailTemplateDO getMailTemplateByCodeFromCache(String code) { | ||
| 122 | + return mailTemplateCache.get(code); | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + @Override | ||
| 84 | public void sendMail(MailReqVO mailReqVO) { | 126 | public void sendMail(MailReqVO mailReqVO) { |
| 85 | // TODO @@wangjingyi:发送的时候,参考下短信; | 127 | // TODO @@wangjingyi:发送的时候,参考下短信; |
| 86 | MailTemplateDO mailTemplateDO = mailTemplateMapper.selectById(mailReqVO.getTemplateId()); | 128 | MailTemplateDO mailTemplateDO = mailTemplateMapper.selectById(mailReqVO.getTemplateId()); |
| @@ -102,6 +144,11 @@ public class MailTemplateServiceImpl implements MailTemplateService { | @@ -102,6 +144,11 @@ public class MailTemplateServiceImpl implements MailTemplateService { | ||
| 102 | MailUtil.send(account , mailReqVO.getTos() , mailReqVO.getTitle() , content , false); | 144 | MailUtil.send(account , mailReqVO.getTos() , mailReqVO.getTitle() , content , false); |
| 103 | } | 145 | } |
| 104 | 146 | ||
| 147 | + @Override | ||
| 148 | + public String formateMailTemplateContent(String content, Map<String, String> params) { | ||
| 149 | + return StrUtil.format(content, params); | ||
| 150 | + } | ||
| 151 | + | ||
| 105 | private void validateMailTemplateExists(Long id) { | 152 | private void validateMailTemplateExists(Long id) { |
| 106 | if (mailTemplateMapper.selectById(id) == null) { | 153 | if (mailTemplateMapper.selectById(id) == null) { |
| 107 | throw exception(MAIL_TEMPLATE_NOT_EXISTS); | 154 | throw exception(MAIL_TEMPLATE_NOT_EXISTS); |