mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-24 16:05:08 +08:00
邮箱模块:完善 account 账号的增删改查功能
This commit is contained in:
@ -1,4 +1,34 @@
|
||||
package cn.iocoder.yudao.module.system.api.mail;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 邮箱发送 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface MailSendApi {
|
||||
|
||||
/**
|
||||
* 发送单条邮箱给 Admin 用户
|
||||
*
|
||||
* 在 mail 为空时,使用 userId 加载对应 Admin 的邮箱
|
||||
*
|
||||
* @param reqDTO 发送请求
|
||||
* @return 发送日志编号
|
||||
*/
|
||||
Long sendSingleSmsToAdmin(@Valid MailSendSingleToUserReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 发送单条邮箱给 Member 用户
|
||||
*
|
||||
* 在 mail 为空时,使用 userId 加载对应 Member 的邮箱
|
||||
*
|
||||
* @param reqDTO 发送请求
|
||||
* @return 发送日志编号
|
||||
*/
|
||||
Long sendSingleSmsToMember(@Valid MailSendSingleToUserReqDTO reqDTO);
|
||||
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.api.mail.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiModel("管理后台 - 邮件发送 Req VO")
|
||||
@Data
|
||||
public class MailSendReqDTO { // TODO @wangjingqi:1), 不用空格;2)应该只要传递 templateCode、参数就好,title、from、content、附件应该都是参数里的
|
||||
|
||||
@ApiModelProperty(value = "用户编码",required = true)
|
||||
@NotNull(message = "用户编码不能为空")
|
||||
private String userId;
|
||||
|
||||
@ApiModelProperty(value = "用户类型",required = true)
|
||||
@NotNull(message = "用户类型不能为空")
|
||||
private String userType;
|
||||
|
||||
@ApiModelProperty(value = "邮箱模版id",example = "1024")
|
||||
@NotNull(message = "邮箱模版编码不能为空")
|
||||
private Integer templateCode;
|
||||
|
||||
@ApiModelProperty(value = "邮箱参数")
|
||||
@NotNull(message = "模版参数不能为空")
|
||||
private Map<String,Object> templateParams;
|
||||
|
||||
@ApiModelProperty(value = "收件人",required = true,example = "yudaoyuanma@123.com")
|
||||
@NotNull(message = "收件人不能为空")
|
||||
private List<String> tos;
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package cn.iocoder.yudao.module.system.api.mail.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 邮件发送 Request DTO
|
||||
*
|
||||
* @author wangjingqi
|
||||
*/
|
||||
@Data
|
||||
public class MailSendSingleToUserReqDTO {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private String userId;
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@Email
|
||||
private String mail;
|
||||
|
||||
/**
|
||||
* 邮件模板编号
|
||||
*/
|
||||
@NotNull(message = "邮件模板编号不能为空")
|
||||
private String templateCode;
|
||||
/**
|
||||
* 邮件模板参数
|
||||
*/
|
||||
@NotNull(message = "邮件模板参数不能为空")
|
||||
private Map<String, Object> templateParams;
|
||||
|
||||
}
|
@ -141,16 +141,13 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode OAUTH2_CODE_NOT_EXISTS = new ErrorCode(1002022000, "code 不存在");
|
||||
ErrorCode OAUTH2_CODE_EXPIRE = new ErrorCode(1002022001, "code 已过期");
|
||||
|
||||
// TODO @芋艿:需要重新搞下 mail 错误码
|
||||
|
||||
// ========== 邮箱账号 1002020000 ==========
|
||||
ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1002020000, "邮箱账号不存在");
|
||||
ErrorCode MAIL_ACCOUNT_EXISTS = new ErrorCode(1002020001, "邮箱账号存在");
|
||||
// ========== 邮箱账号 1002023000 ==========
|
||||
ErrorCode MAIL_ACCOUNT_NOT_EXISTS = new ErrorCode(1002023000, "邮箱账号不存在");
|
||||
ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1002023001, "无法删除,该邮箱账号还有邮件模板");
|
||||
|
||||
// ========== 邮箱模版 1002021000 ==========
|
||||
ErrorCode MAIL_TEMPLATE_NOT_EXISTS = new ErrorCode(1002021000, "邮箱模版不存在");
|
||||
ErrorCode MAIL_TEMPLATE_EXISTS = new ErrorCode(1002021001, "邮箱模版存在");
|
||||
ErrorCode MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS = new ErrorCode(1002021002, "存在关联邮箱模版");
|
||||
ErrorCode MAIL_SEND_TEMPLATE_PARAM_MISS = new ErrorCode(1002021003, "模板参数({})缺失");
|
||||
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
package cn.iocoder.yudao.module.system.enums.mail;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 邮件日志用户类型
|
||||
*
|
||||
* @author wangjingyi
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum MailLogUserTypeEnum {
|
||||
|
||||
COMMON (10),
|
||||
VIP (20);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final int userType;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.mail;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@ -10,5 +11,16 @@ import org.springframework.validation.annotation.Validated;
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class MailSendApiImpl implements MailSendApi{
|
||||
public class MailSendApiImpl implements MailSendApi {
|
||||
|
||||
@Override
|
||||
public Long sendSingleSmsToAdmin(MailSendSingleToUserReqDTO reqDTO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sendSingleSmsToMember(MailSendSingleToUserReqDTO reqDTO) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,11 +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.account.MailAccountBaseVO;
|
||||
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.controller.admin.mail.vo.send.MailReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.*;
|
||||
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.service.mail.MailAccountService;
|
||||
@ -36,14 +32,14 @@ public class MailAccountController {
|
||||
@ApiOperation("创建邮箱账号")
|
||||
@PreAuthorize("@ss.hasPermission('system:mail-account:create')")
|
||||
public CommonResult<Long> createMailAccount(@Valid @RequestBody MailAccountCreateReqVO createReqVO) {
|
||||
return success(mailAccountService.create(createReqVO));
|
||||
return success(mailAccountService.createMailAccount(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@ApiOperation("修改邮箱账号")
|
||||
@PreAuthorize("@ss.hasPermission('system:mail-account:update')")
|
||||
public CommonResult<Boolean> updateMailAccount(@Valid @RequestBody MailAccountUpdateReqVO updateReqVO) {
|
||||
mailAccountService.update(updateReqVO);
|
||||
mailAccountService.updateMailAccount(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@ -52,18 +48,15 @@ public class MailAccountController {
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:mail-account:delete')")
|
||||
public CommonResult<Boolean> deleteMailAccount(@RequestParam Long id) {
|
||||
mailAccountService.delete(id);
|
||||
mailAccountService.deleteMailAccount(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// TODO @wangjingyi:getMailAccount 和 getMailAccountPage 这两个接口,定义一个对应的 Resp 类哈,参考别的模块。主要不要返回 password 字段。
|
||||
// 一个可以的做法,是 MailAccountBaseVO 不返回 password,然后 MailAccountCreateReqVO、MailAccountUpdateReqVO 添加这个字段 DONE
|
||||
|
||||
@GetMapping("/get")
|
||||
@ApiOperation("获得邮箱账号")
|
||||
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
|
||||
@PreAuthorize("@ss.hasPermission('system:mail-account:get')")
|
||||
public CommonResult<MailAccountBaseVO> getMailAccount(@RequestParam("id") Long id) {
|
||||
public CommonResult<MailAccountRespVO> getMailAccount(@RequestParam("id") Long id) {
|
||||
MailAccountDO mailAccountDO = mailAccountService.getMailAccount(id);
|
||||
return success(MailAccountConvert.INSTANCE.convert(mailAccountDO));
|
||||
}
|
||||
@ -76,14 +69,10 @@ public class MailAccountController {
|
||||
return success(MailAccountConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
// TODO @wangjingyi:getSimpleMailAccountList 单独定义一个类,只返回精简的信息,id,from 即可。像密码之类都是敏感信息,不应该返回 DONE
|
||||
|
||||
@GetMapping("/list-all-simple")
|
||||
@ApiOperation(value = "获得邮箱账号精简列表")
|
||||
public CommonResult<List<MailAccountBaseVO>> getSimpleMailAccountList() {
|
||||
public CommonResult<List<MailAccountSimpleRespVO>> getSimpleMailAccountList() {
|
||||
List<MailAccountDO> list = mailAccountService.getMailAccountList();
|
||||
// 排序后,返回给前端
|
||||
list.sort(Comparator.comparing(MailAccountDO::getId));
|
||||
return success(MailAccountConvert.INSTANCE.convertList02(list));
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,41 @@
|
||||
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 javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel("管理后台 - 邮箱账号基类 Base VO")
|
||||
/**
|
||||
* 邮箱账号 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class MailAccountBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "邮箱",required = true,example = "yudaoyuanma@123.com")
|
||||
@NotNull(message = "邮箱必填")
|
||||
@Email(message = "必须是Email格式")
|
||||
private String fromAddress;
|
||||
@ApiModelProperty(value = "邮箱", required = true, example = "yudaoyuanma@123.com")
|
||||
@NotNull(message = "邮箱不能为空")
|
||||
@Email(message = "必须是 Email 格式")
|
||||
private String mail;
|
||||
|
||||
@ApiModelProperty(value = "用户名",required = true,example = "yudao")
|
||||
@NotNull(message = "用户名必填")
|
||||
@ApiModelProperty(value = "用户名", required = true, example = "yudao")
|
||||
@NotNull(message = "用户名不能为空")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "网站",required = true,example = "www.iocoder.cn")
|
||||
@NotNull(message = "网站必填")
|
||||
@ApiModelProperty(value = "密码", required = true, example = "123456")
|
||||
@NotNull(message = "密码必填")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty(value = "网站", required = true, example = "www.iocoder.cn")
|
||||
@NotNull(message = "网站不能为空")
|
||||
private String host;
|
||||
|
||||
@ApiModelProperty(value = "端口",required = true,example = "80")
|
||||
@ApiModelProperty(value = "端口", required = true, example = "80")
|
||||
@NotNull(message = "端口不能为空")
|
||||
private Integer port;
|
||||
|
||||
@ApiModelProperty(value = "是否开启ssl",required = true,example = "2")
|
||||
@NotNull(message = "是否开启ssl必填")
|
||||
@ApiModelProperty(value = "是否开启 ssl", required = true, example = "true")
|
||||
@NotNull(message = "是否开启 ssl 必填")
|
||||
private Boolean sslEnable;
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,4 @@ import javax.validation.constraints.NotNull;
|
||||
@ToString(callSuper = true)
|
||||
public class MailAccountCreateReqVO extends MailAccountBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "密码",required = true,example = "123456")
|
||||
@NotNull(message = "密码必填")
|
||||
private String password;
|
||||
}
|
||||
|
@ -13,21 +13,10 @@ import lombok.ToString;
|
||||
@ToString(callSuper = true)
|
||||
public class MailAccountPageReqVO extends PageParam {
|
||||
|
||||
@ApiModelProperty(value = "邮箱" , required = true , example = "yudaoyuanma@123.com")
|
||||
private String fromAddress;
|
||||
@ApiModelProperty(value = "邮箱", required = true, example = "yudaoyuanma@123.com")
|
||||
private String mail;
|
||||
|
||||
@ApiModelProperty(value = "用户名" , required = true , example = "yudao")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty(value = "密码" , required = true , example = "123456")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty(value = "网站" , required = true , example = "www.iocoder.cn")
|
||||
private String host;
|
||||
|
||||
@ApiModelProperty(value = "端口" , required = true , example = "80")
|
||||
private String port;
|
||||
|
||||
@ApiModelProperty(value = "是否开启ssl" , required = true , example = "2")
|
||||
private Boolean sslEnable;
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
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;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@ApiModel("管理后台 - 邮箱账号 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class MailAccountRespVO extends MailAccountBaseVO {
|
||||
|
||||
@ApiModelProperty(value = "编号", required = true, example = "1024")
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "创建时间", required = true)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.mail.vo.account;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("管理后台 - 邮箱账号的精简 Response VO")
|
||||
@Data
|
||||
public class MailAccountSimpleRespVO {
|
||||
|
||||
@ApiModelProperty(value = "邮箱比那好", required = true, example = "1024")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "邮箱", required = true, example = "768541388@qq.com")
|
||||
private String mail;
|
||||
|
||||
}
|
@ -18,7 +18,4 @@ public class MailAccountUpdateReqVO extends MailAccountBaseVO {
|
||||
@NotNull(message = "编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "密码",required = true,example = "123456")
|
||||
@NotNull(message = "密码必填")
|
||||
private String password;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.system.convert.mail;
|
||||
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.controller.admin.mail.vo.account.MailAccountRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountSimpleRespVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
|
||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
|
||||
import org.mapstruct.Mapper;
|
||||
@ -14,30 +16,33 @@ import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface MailAccountConvert {
|
||||
|
||||
MailAccountConvert INSTANCE = Mappers.getMapper(MailAccountConvert.class);
|
||||
|
||||
MailAccountDO convert (MailAccountBaseVO mailAccountBaseVO);
|
||||
MailAccountDO convert(MailAccountBaseVO bean);
|
||||
|
||||
MailAccountBaseVO convert (MailAccountDO mailAccountDO);
|
||||
MailAccountRespVO convert(MailAccountDO bean);
|
||||
|
||||
PageResult<MailAccountBaseVO> convertPage(PageResult<MailAccountDO> pageResult);
|
||||
PageResult<MailAccountBaseVO> convertPage(PageResult<MailAccountDO> pageResult);
|
||||
|
||||
List<MailAccountBaseVO> convertList02(List<MailAccountDO> list);
|
||||
List<MailAccountSimpleRespVO> convertList02(List<MailAccountDO> list);
|
||||
|
||||
default MailAccount convertAccount(MailSendMessage mailAccountDO){
|
||||
// TODO 芋艿:改下
|
||||
default MailAccount convertAccount(MailSendMessage bean) {
|
||||
return new MailAccount()
|
||||
.setHost(mailAccountDO.getHost())
|
||||
.setPort(mailAccountDO.getPort())
|
||||
.setHost(bean.getHost())
|
||||
.setPort(bean.getPort())
|
||||
.setAuth(true)
|
||||
.setFrom(mailAccountDO.getFromAddress())
|
||||
.setUser(mailAccountDO.getUsername())
|
||||
.setPass(mailAccountDO.getPassword())
|
||||
.setSslEnable(mailAccountDO.getSslEnable());
|
||||
.setFrom(bean.getFromAddress())
|
||||
.setUser(bean.getUsername())
|
||||
.setPass(bean.getPassword())
|
||||
.setSslEnable(bean.getSslEnable());
|
||||
}
|
||||
|
||||
// TODO 芋艿:改下
|
||||
default Map<String, String> convertToMap(MailAccountDO mailAccountDO , String content) {
|
||||
Map<String , String> map = new HashMap<>();
|
||||
map.put("from_address" , mailAccountDO.getFromAddress());
|
||||
map.put("from_address" , mailAccountDO.getMail());
|
||||
map.put("username" , mailAccountDO.getUsername());
|
||||
map.put("content" , content);
|
||||
return map;
|
||||
|
@ -1,14 +1,14 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.mail;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 邮箱账号
|
||||
* 配置发送邮箱的账号
|
||||
* 邮箱账号 DO
|
||||
*
|
||||
* 用途:配置发送邮箱的账号
|
||||
*
|
||||
* @author wangjingyi
|
||||
* @since 2022-03-21
|
||||
@ -25,7 +25,8 @@ public class MailAccountDO extends BaseDO {
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
private String fromAddress;
|
||||
private String mail;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.dal.dataobject.mail;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import cn.iocoder.yudao.module.system.enums.mail.MailLogUserTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@ -13,7 +13,7 @@ import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 邮箱日志
|
||||
* 邮箱日志 DO
|
||||
* 记录每一次邮件的发送
|
||||
*
|
||||
* @author wangjingyi
|
||||
@ -29,7 +29,7 @@ import java.util.Map;
|
||||
public class MailLogDO extends BaseDO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
* 日志编号,自增
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
@ -37,62 +37,74 @@ public class MailLogDO extends BaseDO implements Serializable {
|
||||
* 用户编码
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户类型
|
||||
*
|
||||
* 冗余 {@link MailLogUserTypeEnum#getUserType}
|
||||
* 枚举 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
/**
|
||||
* 接收邮箱地址
|
||||
*/
|
||||
private String toMail;
|
||||
|
||||
// TODO @wangjingyi:accountId
|
||||
/**
|
||||
* 邮箱账号编号
|
||||
*
|
||||
* 关联 {@link MailAccountDO#getId()}
|
||||
*/
|
||||
private Long accountId;
|
||||
|
||||
// TODO @wangjingyi:如果是冗余字段,记得 @ 下;DONE
|
||||
/**
|
||||
* 邮箱账号
|
||||
* 发送邮箱地址
|
||||
*
|
||||
* 冗余 {@link MailAccountDO}
|
||||
* 冗余 {@link MailAccountDO#getMail()}
|
||||
*/
|
||||
private String fromAddress;
|
||||
private String fromMail;
|
||||
|
||||
// ========= 模板相关字段 =========
|
||||
/**
|
||||
* 模版主键
|
||||
* 模版编号
|
||||
*
|
||||
* 关联 {@link MailTemplateDO#getId()}
|
||||
*/
|
||||
private Long templateId;
|
||||
|
||||
/**
|
||||
* 末班编码
|
||||
*
|
||||
* 冗余 {@link MailTemplateDO#getCode()}
|
||||
*/
|
||||
private String templateCode;
|
||||
/**
|
||||
* 模版内容
|
||||
*
|
||||
* 基于 {@link MailTemplateDO#getContent()} 格式化后的内容
|
||||
*/
|
||||
private String templateContent;
|
||||
|
||||
/**
|
||||
* 模版参数
|
||||
*
|
||||
* 基于 {@link MailTemplateDO#getParams()} 输入后的参数
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private Map<String,Object> templateParams;
|
||||
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
private Date sendTime;
|
||||
|
||||
//=========接收相关字段=========
|
||||
// ========= 发送相关字段 =========
|
||||
/**
|
||||
* 发送状态
|
||||
*
|
||||
* 枚举 {@link MailSendStatusEnum}
|
||||
*/
|
||||
private Integer sendStatus;
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
private Date sendTime;
|
||||
|
||||
// ========= 接收相关字段 =========
|
||||
/**
|
||||
* 发送结果
|
||||
*/
|
||||
private String sendResult;
|
||||
|
||||
/**
|
||||
* 消息ID
|
||||
*/
|
||||
|
@ -11,7 +11,7 @@ import lombok.EqualsAndHashCode;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 邮箱模版
|
||||
* 邮箱模版 DO
|
||||
*
|
||||
* @author wangjingyi
|
||||
* @since 2022-03-21
|
||||
@ -34,9 +34,12 @@ public class MailTemplateDO extends BaseDO {
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 邮箱账号主键
|
||||
* 发送的邮箱账号编号
|
||||
*
|
||||
* 关联 {@link MailAccountDO#getId()}
|
||||
*/
|
||||
private Long accountId;
|
||||
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
|
@ -2,37 +2,19 @@ package cn.iocoder.yudao.module.system.dal.mysql.mail;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
|
||||
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> {
|
||||
|
||||
default PageResult<MailAccountDO> selectPage(MailAccountPageReqVO pageReqVO) {
|
||||
return selectPage(pageReqVO, new QueryWrapperX<MailAccountDO>()
|
||||
.likeIfPresent("from_address" , pageReqVO.getFromAddress())
|
||||
.likeIfPresent("host" , pageReqVO.getHost())
|
||||
.likeIfPresent("username" , pageReqVO.getUsername())
|
||||
.eqIfPresent("password" , pageReqVO.getPassword())
|
||||
.eqIfPresent("port" , pageReqVO.getPort())
|
||||
);
|
||||
}
|
||||
|
||||
default MailAccountDO selectByUserName(String userName){
|
||||
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));
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<MailAccountDO>()
|
||||
.likeIfPresent(MailAccountDO::getMail, pageReqVO.getMail())
|
||||
.likeIfPresent(MailAccountDO::getUsername , pageReqVO.getUsername()));
|
||||
}
|
||||
|
||||
default MailAccountDO selectOneByFrom(String from){
|
||||
@ -40,6 +22,4 @@ public interface MailAccountMapper extends BaseMapperX<MailAccountDO> {
|
||||
.eqIfPresent("from_address" , from));
|
||||
}
|
||||
|
||||
@Select("SELECT COUNT(*) FROM system_mail_account WHERE update_time > #{maxUpdateTime}")
|
||||
Long selectCountByUpdateTimeGt(Date maxUpdateTime);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
@ -36,5 +37,10 @@ public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> {
|
||||
default MailTemplateDO selectOneByAccountId(Long accountId){
|
||||
return selectOne(new QueryWrapperX<MailTemplateDO>()
|
||||
.eqIfPresent("account_id" , accountId));
|
||||
};
|
||||
}
|
||||
|
||||
default Long selectCountByAccountId(Long accountId) {
|
||||
return selectCount(MailTemplateDO::getAccountId, accountId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class MailProducer {
|
||||
public void sendMailSendMessage(Long sendLogId,MailAccountDO mailAccountDO, MailTemplateDO mailTemplateDO, String content,List<KeyValue<String, Object>> templateParams,String to) {
|
||||
MailSendMessage message = new MailSendMessage();
|
||||
message.setContent(content)
|
||||
.setFromAddress(mailAccountDO.getFromAddress())
|
||||
.setFromAddress(mailAccountDO.getMail())
|
||||
.setHost(mailAccountDO.getHost())
|
||||
.setPort(mailAccountDO.getPort())
|
||||
.setPassword(mailAccountDO.getPassword())
|
||||
|
@ -28,21 +28,21 @@ public interface MailAccountService {
|
||||
* @param createReqVO 邮箱账号信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long create(@Valid MailAccountCreateReqVO createReqVO);
|
||||
Long createMailAccount(@Valid MailAccountCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 修改邮箱账号
|
||||
*
|
||||
* @param updateReqVO 邮箱账号信息
|
||||
*/
|
||||
void update(@Valid MailAccountUpdateReqVO updateReqVO);
|
||||
void updateMailAccount(@Valid MailAccountUpdateReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除邮箱账号
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void delete(Long id);
|
||||
void deleteMailAccount(Long id);
|
||||
|
||||
/**
|
||||
* 获取邮箱账号信息
|
||||
|
@ -85,4 +85,12 @@ public interface MailTemplateService {
|
||||
*/
|
||||
String formatMailTemplateContent(String content, Map<String, String> params);
|
||||
|
||||
/**
|
||||
* 获得指定邮箱账号下的邮件模板数量
|
||||
*
|
||||
* @param accountId 账号编号
|
||||
* @return 数量
|
||||
*/
|
||||
long countByAccountId(Long accountId);
|
||||
|
||||
}
|
||||
|
@ -1,32 +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 cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
|
||||
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.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS;
|
||||
|
||||
/**
|
||||
* 邮箱账号 Service 实现类
|
||||
@ -43,7 +39,7 @@ public class MailAccountServiceImpl implements MailAccountService {
|
||||
private MailAccountMapper mailAccountMapper;
|
||||
|
||||
@Resource
|
||||
private MailTemplateMapper mailTemplateMapper;
|
||||
private MailTemplateService mailTemplateService;
|
||||
|
||||
@Resource
|
||||
private MailProducer mailProducer;
|
||||
@ -56,75 +52,61 @@ public class MailAccountServiceImpl implements MailAccountService {
|
||||
*/
|
||||
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;
|
||||
}
|
||||
// 第一步:查询数据
|
||||
List<MailAccountDO> accounts = mailAccountMapper.selectList();
|
||||
log.info("[initLocalCache][缓存邮箱账号,数量:{}]", accounts.size());
|
||||
|
||||
// 写入缓存
|
||||
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();
|
||||
// 第二步:构建缓存
|
||||
mailAccountCache = convertMap(accounts, MailAccountDO::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long create(MailAccountCreateReqVO createReqVO) {
|
||||
// username 要校验唯一
|
||||
this.validateMailAccountOnlyByUserName(createReqVO.getUsername());
|
||||
MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(createReqVO);
|
||||
mailAccountMapper.insert(mailAccountDO);
|
||||
public Long createMailAccount(MailAccountCreateReqVO createReqVO) {
|
||||
// 插入
|
||||
MailAccountDO account = MailAccountConvert.INSTANCE.convert(createReqVO);
|
||||
mailAccountMapper.insert(account);
|
||||
|
||||
// 更新
|
||||
// 发送刷新消息
|
||||
mailProducer.sendMailAccountRefreshMessage();
|
||||
return mailAccountDO.getId();
|
||||
return account.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(MailAccountUpdateReqVO updateReqVO) {
|
||||
// username 要校验唯一 TODO @wangjingyi:校验唯一的时候,需要排除掉自己 DONE
|
||||
this.validateMailAccountOnlyByUserNameAndId(updateReqVO.getUsername(),updateReqVO.getId());
|
||||
MailAccountDO mailAccountDO = MailAccountConvert.INSTANCE.convert(updateReqVO);
|
||||
public void updateMailAccount(MailAccountUpdateReqVO updateReqVO) {
|
||||
// 校验是否存在
|
||||
validateMailAccountExists(mailAccountDO.getId());
|
||||
validateMailAccountExists(updateReqVO.getId());
|
||||
|
||||
// 更新
|
||||
MailAccountDO updateObj = MailAccountConvert.INSTANCE.convert(updateReqVO);
|
||||
mailAccountMapper.updateById(updateObj);
|
||||
// 发送刷新消息
|
||||
mailProducer.sendMailAccountRefreshMessage();
|
||||
mailAccountMapper.updateById(mailAccountDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
public void deleteMailAccount(Long id) {
|
||||
// 校验是否存在账号
|
||||
validateMailAccountExists(id);
|
||||
// 校验是否存在关联模版
|
||||
validateMailTemplateByAccountId(id);
|
||||
if (mailTemplateService.countByAccountId(id) > 0) {
|
||||
throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS);
|
||||
}
|
||||
|
||||
// 删除
|
||||
mailAccountMapper.deleteById(id);
|
||||
// 更新
|
||||
// 发送刷新消息
|
||||
mailProducer.sendMailAccountRefreshMessage();
|
||||
}
|
||||
|
||||
private void validateMailAccountExists(Long id) {
|
||||
if (mailAccountMapper.selectById(id) == null) {
|
||||
throw exception(MAIL_ACCOUNT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MailAccountDO getMailAccount(Long id) {
|
||||
return mailAccountMapper.selectById(id);
|
||||
@ -140,33 +122,4 @@ public class MailAccountServiceImpl implements MailAccountService {
|
||||
return mailAccountMapper.selectList();
|
||||
}
|
||||
|
||||
private void validateMailAccountExists(Long id) {
|
||||
if (mailAccountMapper.selectById(id) == null) {
|
||||
throw exception(MAIL_ACCOUNT_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateMailAccountOnlyByUserName(String userName){
|
||||
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 DONE
|
||||
throw exception(MAIL_ACCOUNT_RELATE_TEMPLATE_EXISTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ 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.service.mail.MailLogService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@ -51,7 +50,7 @@ public class MailLogServiceImpl implements MailLogService {
|
||||
logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus()
|
||||
: MailSendStatusEnum.IGNORE.getStatus())
|
||||
// 设置邮箱相关字段
|
||||
.fromAddress(mailAccountDO.getFromAddress())
|
||||
.fromMail(mailAccountDO.getMail())
|
||||
.accountId(mailAccountDO.getId())
|
||||
// TODO @wangjingyi:userId、userType
|
||||
//用户信息
|
||||
@ -60,7 +59,7 @@ public class MailLogServiceImpl implements MailLogService {
|
||||
.templateId(template.getId()).templateParams(templateParams).templateContent(templateContent);
|
||||
|
||||
|
||||
logDOBuilder.fromAddress(mailAccountDO.getFromAddress());
|
||||
logDOBuilder.fromMail(mailAccountDO.getMail());
|
||||
logDOBuilder.accountId(mailAccountDO.getId());
|
||||
// TODO @wangjingyi:每个接收人一条日志。发送多个人,就调用多次,业务方。因为某个邮箱有问题,会导致所有都发送失败。 DONE
|
||||
// 设置模板相关字段
|
||||
|
@ -53,19 +53,19 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
||||
*/
|
||||
private volatile Map<Long, MailTemplateDO> mailTemplateCache;
|
||||
|
||||
private volatile Date maxUpdateTime;
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void initLocalCache() {
|
||||
List<MailTemplateDO> mailTemplateDOList = this.loadMailTemplateIfUpdate(maxUpdateTime);
|
||||
if (true) {
|
||||
return;
|
||||
}
|
||||
List<MailTemplateDO> mailTemplateDOList = this.loadMailTemplateIfUpdate(null);
|
||||
if (CollUtil.isEmpty(mailTemplateDOList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 写入缓存
|
||||
mailTemplateCache = CollectionUtils.convertMap(mailTemplateDOList, MailTemplateDO::getId);
|
||||
maxUpdateTime = CollectionUtils.getMaxValue(mailTemplateDOList, MailTemplateDO::getUpdateTime);
|
||||
log.info("[initLocalCache][初始化 mailTemplate 数量为 {}]", mailTemplateDOList.size());
|
||||
}
|
||||
|
||||
@ -156,4 +156,10 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
||||
// 第二步,如果有更新,则从数据库加载所有邮件模板
|
||||
return mailTemplateMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByAccountId(Long accountId) {
|
||||
return mailTemplateMapper.selectCountByAccountId(accountId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class SmsChannelServiceImpl implements SmsChannelService {
|
||||
public void deleteSmsChannel(Long id) {
|
||||
// 校验存在
|
||||
this.validateSmsChannelExists(id);
|
||||
// 校验是否有字典数据
|
||||
// 校验是否有在使用该账号的模版
|
||||
if (smsTemplateService.countByChannelId(id) > 0) {
|
||||
throw exception(SMS_CHANNEL_HAS_CHILDREN);
|
||||
}
|
||||
|
Reference in New Issue
Block a user