【同步】BOOT 和 CLOUD 的功能
This commit is contained in:
@@ -1,27 +1,50 @@
|
||||
package cn.iocoder.yudao.module.system.api.mail.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "RPC 服务 - 邮件发送给 Admin 或者 Member 用户 Request DTO")
|
||||
/**
|
||||
* 邮件发送 Request DTO
|
||||
*
|
||||
* @author wangjingqi
|
||||
*/
|
||||
@Data
|
||||
public class MailSendSingleToUserReqDTO {
|
||||
|
||||
@Schema(description = "用户编号", example = "1024")
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 如果非空,则加载对应用户的邮箱,添加到 {@link #toMails} 中
|
||||
*/
|
||||
private Long userId;
|
||||
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300")
|
||||
@Email
|
||||
private String mail;
|
||||
|
||||
@Schema(description = "邮件模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "USER_SEND")
|
||||
/**
|
||||
* 收件邮箱
|
||||
*/
|
||||
private List<@Email String> toMails;
|
||||
/**
|
||||
* 抄送邮箱
|
||||
*/
|
||||
private List<@Email String> ccMails;
|
||||
/**
|
||||
* 密送邮箱
|
||||
*/
|
||||
private List<@Email String> bccMails;
|
||||
|
||||
|
||||
/**
|
||||
* 邮件模板编号
|
||||
*/
|
||||
@NotNull(message = "邮件模板编号不能为空")
|
||||
private String templateCode;
|
||||
|
||||
@Schema(description = "邮件模板参数")
|
||||
/**
|
||||
* 邮件模板参数
|
||||
*/
|
||||
private Map<String, Object> templateParams;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,13 +19,15 @@ public class MailSendApiImpl implements MailSendApi {
|
||||
|
||||
@Override
|
||||
public CommonResult<Long> sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) {
|
||||
return success(mailSendService.sendSingleMailToAdmin(reqDTO.getMail(), reqDTO.getUserId(),
|
||||
return success(mailSendService.sendSingleMailToAdmin(reqDTO.getUserId(),
|
||||
reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(),
|
||||
reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Long> sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) {
|
||||
return success(mailSendService.sendSingleMailToMember(reqDTO.getMail(), reqDTO.getUserId(),
|
||||
return success(mailSendService.sendSingleMailToMember(reqDTO.getUserId(),
|
||||
reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(),
|
||||
reqDTO.getTemplateCode(), reqDTO.getTemplateParams()));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,24 @@ tag: Yunai.local
|
||||
"code": "1024"
|
||||
}
|
||||
|
||||
### 请求 /login 接口【加密 AES】 => 成功
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
tag: Yunai.local
|
||||
X-API-ENCRYPT: true
|
||||
|
||||
WvSX9MOrenyGfBhEM0g1/hHgq8ocktMZ9OwAJ6MOG5FUrzYF/rG5JF1eMptQM1wT73VgDS05l/37WeRtad+JrqChAul/sR/SdOsUKqjBhvvQx1JVhzxr6s8uUP67aKTSZ6Psv7O32ELxXrzSaQvG5CInzz3w6sLtbNNLd1kXe6Q=
|
||||
|
||||
### 请求 /login 接口【加密 RSA】 => 成功
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: {{adminTenantId}}
|
||||
tag: Yunai.local
|
||||
X-API-ENCRYPT: true
|
||||
|
||||
e7QZTork9ZV5CmgZvSd+cHZk3xdUxKtowLM02kOha+gxHK2H/daU8nVBYS3+bwuDRy5abf+Pz1QJJGVAEd27wwrXBmupOOA/bhpuzzDwcRuJRD+z+YgiNoEXFDRHERxPYlPqAe9zAHtihD0ceub1AjybQsEsROew4C3Q602XYW0=
|
||||
|
||||
### 请求 /login 接口 => 成功(无验证码)
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
@@ -21,16 +39,6 @@ tenant-id: {{adminTenantId}}
|
||||
"password": "admin123"
|
||||
}
|
||||
|
||||
### 请求 /login 接口 => 失败(租户不存在)
|
||||
POST {{baseUrl}}/system/auth/login
|
||||
Content-Type: application/json
|
||||
tenant-id: 2
|
||||
|
||||
{
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
}
|
||||
|
||||
### 请求 /get-permission-info 接口 => 成功
|
||||
GET {{baseUrl}}/system/auth/get-permission-info
|
||||
Authorization: Bearer {{token}}
|
||||
|
||||
@@ -56,6 +56,15 @@ public class DeptController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete-list")
|
||||
@Operation(summary = "批量删除部门")
|
||||
@Parameter(name = "ids", description = "编号列表", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('system:dept:delete')")
|
||||
public CommonResult<Boolean> deleteDeptList(@RequestParam("ids") List<Long> ids) {
|
||||
deptService.deleteDeptList(ids);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获取部门列表")
|
||||
@PreAuthorize("@ss.hasPermission('system:dept:query')")
|
||||
|
||||
@@ -91,7 +91,8 @@ public class MailTemplateController {
|
||||
@Operation(summary = "发送短信")
|
||||
@PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')")
|
||||
public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) {
|
||||
return success(mailSendService.sendSingleMailToAdmin(sendReqVO.getMail(), getLoginUserId(),
|
||||
return success(mailSendService.sendSingleMailToAdmin(getLoginUserId(),
|
||||
sendReqVO.getToMails(), sendReqVO.getCcMails(), sendReqVO.getBccMails(),
|
||||
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - 邮件日志 Response VO")
|
||||
@@ -19,8 +20,14 @@ public class MailLogRespVO {
|
||||
@Schema(description = "用户类型,参见 UserTypeEnum 枚举", example = "2")
|
||||
private Byte userType;
|
||||
|
||||
@Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "76854@qq.com")
|
||||
private String toMail;
|
||||
@Schema(description = "接收邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user1@example.com, user2@example.com")
|
||||
private List<String> toMails;
|
||||
|
||||
@Schema(description = "抄送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user3@example.com, user4@example.com")
|
||||
private List<String> ccMails;
|
||||
|
||||
@Schema(description = "密送邮箱地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "user5@example.com, user6@example.com")
|
||||
private List<String> bccMails;
|
||||
|
||||
@Schema(description = "邮箱账号编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18107")
|
||||
private Long accountId;
|
||||
|
||||
@@ -5,15 +5,22 @@ import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Schema(description = "管理后台 - 邮件发送 Req VO")
|
||||
@Data
|
||||
public class MailTemplateSendReqVO {
|
||||
|
||||
@Schema(description = "接收邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "7685413@qq.com")
|
||||
@Schema(description = "接收邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user1@example.com, user2@example.com]")
|
||||
@NotEmpty(message = "接收邮箱不能为空")
|
||||
private String mail;
|
||||
private List<String> toMails;
|
||||
|
||||
@Schema(description = "抄送邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user3@example.com, user4@example.com]")
|
||||
private List<String> ccMails;
|
||||
|
||||
@Schema(description = "密送邮箱", requiredMode = Schema.RequiredMode.REQUIRED, example = "[user5@example.com, user6@example.com]")
|
||||
private List<String> bccMails;
|
||||
|
||||
@Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "test_01")
|
||||
@NotNull(message = "模板编码不能为空")
|
||||
|
||||
@@ -2,6 +2,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.framework.mybatis.core.type.StringListTypeHandler;
|
||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
@@ -12,6 +13,7 @@ import lombok.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -47,10 +49,22 @@ public class MailLogDO extends BaseDO implements Serializable {
|
||||
* 枚举 {@link UserTypeEnum}
|
||||
*/
|
||||
private Integer userType;
|
||||
|
||||
/**
|
||||
* 接收邮箱地址
|
||||
*/
|
||||
private String toMail;
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> toMails;
|
||||
/**
|
||||
* 接收邮箱地址
|
||||
*/
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> ccMails;
|
||||
/**
|
||||
* 密送邮箱地址
|
||||
*/
|
||||
@TableField(typeHandler = StringListTypeHandler.class)
|
||||
private List<String> bccMails;
|
||||
|
||||
/**
|
||||
* 邮箱账号编号
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package cn.iocoder.yudao.module.system.dal.mysql.mail;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
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.util.MyBatisUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@@ -14,11 +16,12 @@ public interface MailLogMapper extends BaseMapperX<MailLogDO> {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<MailLogDO>()
|
||||
.eqIfPresent(MailLogDO::getUserId, reqVO.getUserId())
|
||||
.eqIfPresent(MailLogDO::getUserType, reqVO.getUserType())
|
||||
.likeIfPresent(MailLogDO::getToMail, reqVO.getToMail())
|
||||
.eqIfPresent(MailLogDO::getAccountId, reqVO.getAccountId())
|
||||
.eqIfPresent(MailLogDO::getTemplateId, reqVO.getTemplateId())
|
||||
.eqIfPresent(MailLogDO::getSendStatus, reqVO.getSendStatus())
|
||||
.betweenIfPresent(MailLogDO::getSendTime, reqVO.getSendTime())
|
||||
.apply(StrUtil.isNotBlank(reqVO.getToMail()),
|
||||
MyBatisUtils.findInSet("to_mails", reqVO.getToMail()))
|
||||
.orderByDesc(MailLogDO::getId));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ import lombok.Data;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 邮箱发送消息
|
||||
*
|
||||
@@ -21,8 +24,16 @@ public class MailSendMessage {
|
||||
/**
|
||||
* 接收邮件地址
|
||||
*/
|
||||
@NotNull(message = "接收邮件地址不能为空")
|
||||
private String mail;
|
||||
@NotEmpty(message = "接收邮件地址不能为空")
|
||||
private Collection<String> toMails;
|
||||
/**
|
||||
* 抄送邮件地址
|
||||
*/
|
||||
private Collection<String> ccMails;
|
||||
/**
|
||||
* 密送邮件地址
|
||||
*/
|
||||
private Collection<String> bccMails;
|
||||
/**
|
||||
* 邮件账号编号
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,11 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Mail 邮件相关消息的 Producer
|
||||
*
|
||||
@@ -24,17 +29,22 @@ public class MailProducer {
|
||||
* 发送 {@link MailSendMessage} 消息
|
||||
*
|
||||
* @param sendLogId 发送日志编码
|
||||
* @param mail 接收邮件地址
|
||||
* @param toMails 接收邮件地址
|
||||
* @param ccMails 抄送邮件地址
|
||||
* @param bccMails 密送邮件地址
|
||||
* @param accountId 邮件账号编号
|
||||
* @param nickname 邮件发件人
|
||||
* @param title 邮件标题
|
||||
* @param content 邮件内容
|
||||
* @param nickname 邮件发件人
|
||||
* @param title 邮件标题
|
||||
* @param content 邮件内容
|
||||
*/
|
||||
public void sendMailSendMessage(Long sendLogId, String mail, Long accountId,
|
||||
String nickname, String title, String content) {
|
||||
public void sendMailSendMessage(Long sendLogId,
|
||||
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
Long accountId, String nickname, String title, String content) {
|
||||
MailSendMessage message = new MailSendMessage()
|
||||
.setLogId(sendLogId).setMail(mail).setAccountId(accountId)
|
||||
.setNickname(nickname).setTitle(title).setContent(content);
|
||||
.setLogId(sendLogId)
|
||||
.setToMails(toMails).setCcMails(ccMails).setBccMails(bccMails)
|
||||
.setAccountId(accountId).setNickname(nickname)
|
||||
.setTitle(title).setContent(content);
|
||||
applicationContext.publishEvent(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@ public interface DeptService {
|
||||
*/
|
||||
void deleteDept(Long id);
|
||||
|
||||
/**
|
||||
* 批量删除部门
|
||||
*
|
||||
* @param ids 部门编号数组
|
||||
*/
|
||||
void deleteDeptList(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 获得部门信息
|
||||
*
|
||||
|
||||
@@ -88,6 +88,21 @@ public class DeptServiceImpl implements DeptService {
|
||||
deptMapper.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(cacheNames = RedisKeyConstants.DEPT_CHILDREN_ID_LIST,
|
||||
allEntries = true) // allEntries 清空所有缓存,因为操作一个部门,涉及到多个缓存
|
||||
public void deleteDeptList(List<Long> ids) {
|
||||
// 校验是否有子部门
|
||||
for (Long id : ids) {
|
||||
if (deptMapper.selectCountByParentId(id) > 0) {
|
||||
throw exception(DEPT_EXITS_CHILDREN);
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除部门
|
||||
deptMapper.deleteByIds(ids);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateDeptExists(Long id) {
|
||||
if (id == null) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -35,18 +37,21 @@ public interface MailLogService {
|
||||
/**
|
||||
* 创建邮件日志
|
||||
*
|
||||
* @param userId 用户编码
|
||||
* @param userType 用户类型
|
||||
* @param toMail 收件人邮件
|
||||
* @param account 邮件账号信息
|
||||
* @param template 模版信息
|
||||
* @param userId 用户编码
|
||||
* @param userType 用户类型
|
||||
* @param toMails 收件人邮件
|
||||
* @param ccMails 收件人邮件
|
||||
* @param bccMails 收件人邮件
|
||||
* @param account 邮件账号信息
|
||||
* @param template 模版信息
|
||||
* @param templateContent 模版内容
|
||||
* @param templateParams 模版参数
|
||||
* @param isSend 是否发送成功
|
||||
* @param templateParams 模版参数
|
||||
* @param isSend 是否发送成功
|
||||
* @return 日志编号
|
||||
*/
|
||||
Long createMailLog(Long userId, Integer userType, String toMail,
|
||||
MailAccountDO account, MailTemplateDO template ,
|
||||
Long createMailLog(Long userId, Integer userType,
|
||||
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
MailAccountDO account, MailTemplateDO template,
|
||||
String templateContent, Map<String, Object> templateParams, Boolean isSend);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.service.mail;
|
||||
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.log.MailLogPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
|
||||
@@ -12,8 +13,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.hutool.core.exceptions.ExceptionUtil.getRootCauseMessage;
|
||||
|
||||
@@ -41,7 +41,8 @@ public class MailLogServiceImpl implements MailLogService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createMailLog(Long userId, Integer userType, String toMail,
|
||||
public Long createMailLog(Long userId, Integer userType,
|
||||
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
MailAccountDO account, MailTemplateDO template,
|
||||
String templateContent, Map<String, Object> templateParams, Boolean isSend) {
|
||||
MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder();
|
||||
@@ -49,7 +50,8 @@ public class MailLogServiceImpl implements MailLogService {
|
||||
logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus()
|
||||
: MailSendStatusEnum.IGNORE.getStatus())
|
||||
// 用户信息
|
||||
.userId(userId).userType(userType).toMail(toMail)
|
||||
.userId(userId).userType(userType)
|
||||
.toMails(ListUtil.toList(toMails)).ccMails(ListUtil.toList(ccMails)).bccMails(ListUtil.toList(bccMails))
|
||||
.accountId(account.getId()).fromMail(account.getMail())
|
||||
// 模板相关字段
|
||||
.templateId(template.getId()).templateCode(template.getCode()).templateNickname(template.getNickname())
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package cn.iocoder.yudao.module.system.service.mail;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -15,38 +17,53 @@ public interface MailSendService {
|
||||
/**
|
||||
* 发送单条邮件给管理后台的用户
|
||||
*
|
||||
* @param mail 邮箱
|
||||
* @param userId 用户编码
|
||||
* @param toMails 收件邮箱
|
||||
* @param ccMails 抄送邮箱
|
||||
* @param bccMails 密送邮箱
|
||||
* @param templateCode 邮件模版编码
|
||||
* @param templateParams 邮件模版参数
|
||||
* @return 发送日志编号
|
||||
*/
|
||||
Long sendSingleMailToAdmin(String mail, Long userId,
|
||||
String templateCode, Map<String, Object> templateParams);
|
||||
default Long sendSingleMailToAdmin(Long userId,
|
||||
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
String templateCode, Map<String, Object> templateParams) {
|
||||
return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.ADMIN.getValue(),
|
||||
templateCode, templateParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送单条邮件给用户 APP 的用户
|
||||
*
|
||||
* @param mail 邮箱
|
||||
* @param userId 用户编码
|
||||
* @param toMails 收件邮箱
|
||||
* @param ccMails 抄送邮箱
|
||||
* @param bccMails 密送邮箱
|
||||
* @param templateCode 邮件模版编码
|
||||
* @param templateParams 邮件模版参数
|
||||
* @return 发送日志编号
|
||||
*/
|
||||
Long sendSingleMailToMember(String mail, Long userId,
|
||||
String templateCode, Map<String, Object> templateParams);
|
||||
default Long sendSingleMailToMember(Long userId,
|
||||
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
String templateCode, Map<String, Object> templateParams) {
|
||||
return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.MEMBER.getValue(),
|
||||
templateCode, templateParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送单条邮件给用户
|
||||
* 发送单条邮件
|
||||
*
|
||||
* @param mail 邮箱
|
||||
* @param userId 用户编码
|
||||
* @param toMails 收件邮箱
|
||||
* @param ccMails 抄送邮箱
|
||||
* @param bccMails 密送邮箱
|
||||
* @param userId 用户编号
|
||||
* @param userType 用户类型
|
||||
* @param templateCode 邮件模版编码
|
||||
* @param templateParams 邮件模版参数
|
||||
* @return 发送日志编号
|
||||
*/
|
||||
Long sendSingleMail(String mail, Long userId, Integer userType,
|
||||
Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
Long userId, Integer userType,
|
||||
String templateCode, Map<String, Object> templateParams);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.service.mail;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
@@ -13,10 +15,13 @@ import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.hutool.extra.mail.*;
|
||||
import org.dromara.hutool.extra.mail.MailAccount;
|
||||
import org.dromara.hutool.extra.mail.MailUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@@ -49,56 +54,67 @@ public class MailSendServiceImpl implements MailSendService {
|
||||
private MailProducer mailProducer;
|
||||
|
||||
@Override
|
||||
public Long sendSingleMailToAdmin(String mail, Long userId,
|
||||
String templateCode, Map<String, Object> templateParams) {
|
||||
// 如果 mail 为空,则加载用户编号对应的邮箱
|
||||
if (StrUtil.isEmpty(mail)) {
|
||||
AdminUserDO user = adminUserService.getUser(userId);
|
||||
if (user != null) {
|
||||
mail = user.getEmail();
|
||||
}
|
||||
}
|
||||
// 执行发送
|
||||
return sendSingleMail(mail, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sendSingleMailToMember(String mail, Long userId,
|
||||
String templateCode, Map<String, Object> templateParams) {
|
||||
// 如果 mail 为空,则加载用户编号对应的邮箱
|
||||
if (StrUtil.isEmpty(mail)) {
|
||||
mail = memberService.getMemberUserEmail(userId);
|
||||
}
|
||||
// 执行发送
|
||||
return sendSingleMail(mail, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long sendSingleMail(String mail, Long userId, Integer userType,
|
||||
public Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
|
||||
Long userId, Integer userType,
|
||||
String templateCode, Map<String, Object> templateParams) {
|
||||
// 校验邮箱模版是否合法
|
||||
// 1.1 校验邮箱模版是否合法
|
||||
MailTemplateDO template = validateMailTemplate(templateCode);
|
||||
// 校验邮箱账号是否合法
|
||||
// 1.2 校验邮箱账号是否合法
|
||||
MailAccountDO account = validateMailAccount(template.getAccountId());
|
||||
|
||||
// 校验邮箱是否存在
|
||||
mail = validateMail(mail);
|
||||
// 1.3 校验邮件参数是否缺失
|
||||
validateTemplateParams(template, templateParams);
|
||||
|
||||
// 2. 组装邮箱
|
||||
String userMail = getUserMail(userId, userType);
|
||||
Collection<String> toMailSet = new LinkedHashSet<>();
|
||||
Collection<String> ccMailSet = new LinkedHashSet<>();
|
||||
Collection<String> bccMailSet = new LinkedHashSet<>();
|
||||
if (Validator.isEmail(userMail)) {
|
||||
toMailSet.add(userMail);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(toMails)) {
|
||||
toMails.stream().filter(Validator::isEmail).forEach(toMailSet::add);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(ccMails)) {
|
||||
ccMails.stream().filter(Validator::isEmail).forEach(ccMailSet::add);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(bccMails)) {
|
||||
bccMails.stream().filter(Validator::isEmail).forEach(bccMailSet::add);
|
||||
}
|
||||
if (CollUtil.isEmpty(toMailSet)) {
|
||||
throw exception(MAIL_SEND_MAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
// 创建发送日志。如果模板被禁用,则不发送短信,只记录日志
|
||||
Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus());
|
||||
String title = mailTemplateService.formatMailTemplateContent(template.getTitle(), templateParams);
|
||||
String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams);
|
||||
Long sendLogId = mailLogService.createMailLog(userId, userType, mail,
|
||||
Long sendLogId = mailLogService.createMailLog(userId, userType, toMailSet, ccMailSet, bccMailSet,
|
||||
account, template, content, templateParams, isSend);
|
||||
// 发送 MQ 消息,异步执行发送短信
|
||||
if (isSend) {
|
||||
mailProducer.sendMailSendMessage(sendLogId, mail, account.getId(),
|
||||
template.getNickname(), title, content);
|
||||
mailProducer.sendMailSendMessage(sendLogId, toMailSet, ccMailSet, bccMailSet,
|
||||
account.getId(), template.getNickname(), title, content);
|
||||
}
|
||||
return sendLogId;
|
||||
}
|
||||
|
||||
private String getUserMail(Long userId, Integer userType) {
|
||||
if (userId == null || userType == null) {
|
||||
return null;
|
||||
}
|
||||
if (UserTypeEnum.ADMIN.getValue().equals(userType)) {
|
||||
AdminUserDO user = adminUserService.getUser(userId);
|
||||
if (user != null) {
|
||||
return user.getEmail();
|
||||
}
|
||||
}
|
||||
if (UserTypeEnum.MEMBER.getValue().equals(userType)) {
|
||||
return memberService.getMemberUserEmail(userId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSendMail(MailSendMessage message) {
|
||||
// 1. 创建发送账号
|
||||
@@ -106,7 +122,7 @@ public class MailSendServiceImpl implements MailSendService {
|
||||
MailAccount mailAccount = buildMailAccount(account, message.getNickname());
|
||||
// 2. 发送邮件
|
||||
try {
|
||||
String messageId = MailUtil.send(mailAccount, message.getMail(),
|
||||
String messageId = MailUtil.send(mailAccount, message.getToMails(), message.getCcMails(), message.getBccMails(),
|
||||
message.getTitle(), message.getContent(), true);
|
||||
// 3. 更新结果(成功)
|
||||
mailLogService.updateMailSendResult(message.getLogId(), messageId, null);
|
||||
@@ -146,16 +162,8 @@ public class MailSendServiceImpl implements MailSendService {
|
||||
return account;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String validateMail(String mail) {
|
||||
if (StrUtil.isEmpty(mail)) {
|
||||
throw exception(MAIL_SEND_MAIL_NOT_EXISTS);
|
||||
}
|
||||
return mail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验邮件参数是否确实
|
||||
* 校验邮件参数是否缺失
|
||||
*
|
||||
* @param template 邮箱模板
|
||||
* @param templateParams 参数列表
|
||||
|
||||
@@ -255,9 +255,6 @@ public class MenuServiceImpl implements MenuService {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
|
||||
if (id == null) {
|
||||
throw exception(MENU_NAME_DUPLICATE);
|
||||
}
|
||||
if (!menu.getId().equals(id)) {
|
||||
throw exception(MENU_NAME_DUPLICATE);
|
||||
}
|
||||
|
||||
@@ -10,15 +10,17 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
@@ -43,7 +45,9 @@ public class MailLogServiceImplTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String toMail = randomEmail();
|
||||
Collection<String> toMails = Lists.newArrayList(randomEmail(), randomEmail());
|
||||
Collection<String> ccMails = Lists.newArrayList(randomEmail());
|
||||
Collection<String> bccMails = Lists.newArrayList(randomEmail());
|
||||
MailAccountDO account = randomPojo(MailAccountDO.class);
|
||||
MailTemplateDO template = randomPojo(MailTemplateDO.class);
|
||||
String templateContent = randomString();
|
||||
@@ -52,14 +56,20 @@ public class MailLogServiceImplTest extends BaseDbUnitTest {
|
||||
// mock 方法
|
||||
|
||||
// 调用
|
||||
Long logId = mailLogService.createMailLog(userId, userType, toMail, account, template, templateContent, templateParams, isSend);
|
||||
Long logId = mailLogService.createMailLog(userId, userType, toMails, ccMails, bccMails,
|
||||
account, template, templateContent, templateParams, isSend);
|
||||
// 断言
|
||||
MailLogDO log = mailLogMapper.selectById(logId);
|
||||
assertNotNull(log);
|
||||
assertEquals(MailSendStatusEnum.INIT.getStatus(), log.getSendStatus());
|
||||
assertEquals(userId, log.getUserId());
|
||||
assertEquals(userType, log.getUserType());
|
||||
assertEquals(toMail, log.getToMail());
|
||||
assertEquals(toMails.size(), log.getToMails().size());
|
||||
assertTrue(log.getToMails().containsAll(toMails));
|
||||
assertEquals(ccMails.size(), log.getCcMails().size());
|
||||
assertTrue(log.getCcMails().containsAll(ccMails));
|
||||
assertEquals(bccMails.size(), log.getBccMails().size());
|
||||
assertTrue(log.getBccMails().containsAll(bccMails));
|
||||
assertEquals(account.getId(), log.getAccountId());
|
||||
assertEquals(account.getMail(), log.getFromMail());
|
||||
assertEquals(template.getId(), log.getTemplateId());
|
||||
@@ -132,48 +142,50 @@ public class MailLogServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Test
|
||||
public void testGetMailLogPage() {
|
||||
// mock 数据
|
||||
MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到
|
||||
o.setUserId(1L);
|
||||
o.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
o.setToMail("768@qq.com");
|
||||
o.setAccountId(10L);
|
||||
o.setTemplateId(100L);
|
||||
o.setSendStatus(MailSendStatusEnum.INIT.getStatus());
|
||||
o.setSendTime(buildTime(2023, 2, 10));
|
||||
o.setTemplateParams(randomTemplateParams());
|
||||
});
|
||||
mailLogMapper.insert(dbMailLog);
|
||||
// 测试 userId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L)));
|
||||
// 测试 userType 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
|
||||
// 测试 toMail 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMail("788@.qq.com")));
|
||||
// 测试 accountId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L)));
|
||||
// 测试 templateId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setTemplateId(101L)));
|
||||
// 测试 sendStatus 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendStatus(MailSendStatusEnum.SUCCESS.getStatus())));
|
||||
// 测试 sendTime 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendTime(buildTime(2023, 3, 10))));
|
||||
// 准备参数
|
||||
MailLogPageReqVO reqVO = new MailLogPageReqVO();
|
||||
reqVO.setUserId(1L);
|
||||
reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
reqVO.setToMail("768");
|
||||
reqVO.setAccountId(10L);
|
||||
reqVO.setTemplateId(100L);
|
||||
reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus());
|
||||
reqVO.setSendTime((buildBetweenTime(2023, 2, 1, 2023, 2, 15)));
|
||||
// mock 数据
|
||||
MailLogDO dbMailLog = randomPojo(MailLogDO.class, o -> { // 等会查询到
|
||||
o.setUserId(1L);
|
||||
o.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
o.setToMails(Lists.newArrayList("768@qq.com"));
|
||||
o.setCcMails(Lists.newArrayList());
|
||||
o.setBccMails(Lists.newArrayList());
|
||||
o.setAccountId(10L);
|
||||
o.setTemplateId(100L);
|
||||
o.setSendStatus(MailSendStatusEnum.INIT.getStatus());
|
||||
o.setSendTime(buildTime(2023, 2, 10));
|
||||
o.setTemplateParams(randomTemplateParams());
|
||||
});
|
||||
mailLogMapper.insert(dbMailLog);
|
||||
// 测试 userId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserId(2L)));
|
||||
// 测试 userType 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setUserType(UserTypeEnum.MEMBER.getValue())));
|
||||
// 测试 toMails 不匹配(特殊:find_in_set 无法单测)
|
||||
// mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setToMails(Lists.newArrayList("788@qq.com"))));
|
||||
// 测试 accountId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setAccountId(11L)));
|
||||
// 测试 templateId 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setTemplateId(101L)));
|
||||
// 测试 sendStatus 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendStatus(MailSendStatusEnum.SUCCESS.getStatus())));
|
||||
// 测试 sendTime 不匹配
|
||||
mailLogMapper.insert(cloneIgnoreId(dbMailLog, o -> o.setSendTime(buildTime(2023, 3, 10))));
|
||||
// 准备参数
|
||||
MailLogPageReqVO reqVO = new MailLogPageReqVO();
|
||||
reqVO.setUserId(1L);
|
||||
reqVO.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
// reqVO.setToMail("768@qq.com");
|
||||
reqVO.setAccountId(10L);
|
||||
reqVO.setTemplateId(100L);
|
||||
reqVO.setSendStatus(MailSendStatusEnum.INIT.getStatus());
|
||||
reqVO.setSendTime((buildBetweenTime(2023, 2, 1, 2023, 2, 15)));
|
||||
|
||||
// 调用
|
||||
PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbMailLog, pageResult.getList().get(0));
|
||||
// 调用
|
||||
PageResult<MailLogDO> pageResult = mailLogService.getMailLogPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbMailLog, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
private static Map<String, Object> randomTemplateParams() {
|
||||
|
||||
@@ -13,14 +13,14 @@ import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
|
||||
import cn.iocoder.yudao.module.system.service.member.MemberService;
|
||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.dromara.hutool.extra.mail.MailAccount;
|
||||
import org.dromara.hutool.extra.mail.MailUtil;
|
||||
import org.dromara.hutool.extra.mail.*;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockedStatic;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -66,14 +66,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendSingleMailToAdmin() {
|
||||
public void testSendSingleMail_success() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
String templateCode = RandomUtils.randomString();
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
||||
.put("op", "login").build();
|
||||
Collection<String> toMails = Lists.newArrayList("admin@test.com");
|
||||
Collection<String> ccMails = Lists.newArrayList("cc@test.com");
|
||||
Collection<String> bccMails = Lists.newArrayList("bcc@test.com");
|
||||
|
||||
// mock adminUserService 的方法
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300"));
|
||||
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setEmail("admin@example.com"));
|
||||
when(adminUserService.getUser(eq(userId))).thenReturn(user);
|
||||
|
||||
// mock MailTemplateService 的方法
|
||||
@@ -94,61 +98,27 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
|
||||
// mock MailLogService 的方法
|
||||
Long mailLogId = randomLongId();
|
||||
when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(user.getEmail()),
|
||||
when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.ADMIN.getValue()),
|
||||
argThat(toMailSet -> toMailSet.contains(user.getEmail()) && toMailSet.contains("admin@test.com")),
|
||||
argThat(ccMailSet -> ccMailSet.contains("cc@test.com")),
|
||||
argThat(bccMailSet -> bccMailSet.contains("bcc@test.com")),
|
||||
eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
|
||||
|
||||
// 调用
|
||||
Long resultMailLogId = mailSendService.sendSingleMailToAdmin(null, userId, templateCode, templateParams);
|
||||
Long resultMailLogId = mailSendService.sendSingleMail(toMails, ccMails, bccMails, userId,
|
||||
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
|
||||
// 断言
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(user.getEmail()),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendSingleMailToMember() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
String templateCode = RandomUtils.randomString();
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
||||
.put("op", "login").build();
|
||||
// mock memberService 的方法
|
||||
String mail = randomEmail();
|
||||
when(memberService.getMemberUserEmail(eq(userId))).thenReturn(mail);
|
||||
|
||||
// mock MailTemplateService 的方法
|
||||
MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setContent("验证码为{code}, 操作为{op}");
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
String title = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getTitle()), eq(templateParams)))
|
||||
.thenReturn(title);
|
||||
String content = RandomUtils.randomString();
|
||||
when(mailTemplateService.formatMailTemplateContent(eq(template.getContent()), eq(templateParams)))
|
||||
.thenReturn(content);
|
||||
// mock MailAccountService 的方法
|
||||
MailAccountDO account = randomPojo(MailAccountDO.class);
|
||||
when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
|
||||
// mock MailLogService 的方法
|
||||
Long mailLogId = randomLongId();
|
||||
when(mailLogService.createMailLog(eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(mail),
|
||||
eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
|
||||
|
||||
// 调用
|
||||
Long resultMailLogId = mailSendService.sendSingleMailToMember(null, userId, templateCode, templateParams);
|
||||
// 断言
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId),
|
||||
argThat(toMailSet -> toMailSet.contains(user.getEmail()) && toMailSet.contains("admin@test.com")),
|
||||
argThat(ccMailSet -> ccMailSet.contains("cc@test.com")),
|
||||
argThat(bccMailSet -> bccMailSet.contains("bcc@test.com")),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送成功,当短信模板开启时
|
||||
* 发送成功,当邮件模板开启时
|
||||
*/
|
||||
@Test
|
||||
public void testSendSingleMail_successWhenMailTemplateEnable() {
|
||||
@@ -159,6 +129,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
String templateCode = RandomUtils.randomString();
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
||||
.put("op", "login").build();
|
||||
Collection<String> toMails = Lists.newArrayList(mail);
|
||||
|
||||
// mock MailTemplateService 的方法
|
||||
MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
@@ -177,23 +149,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
|
||||
// mock MailLogService 的方法
|
||||
Long mailLogId = randomLongId();
|
||||
when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail),
|
||||
when(mailLogService.createMailLog(eq(userId), eq(userType),
|
||||
argThat(toMailSet -> toMailSet.contains(mail)),
|
||||
argThat(Collection::isEmpty),
|
||||
argThat(Collection::isEmpty),
|
||||
eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
|
||||
|
||||
// 调用
|
||||
Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams);
|
||||
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams);
|
||||
// 断言
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId), eq(mail),
|
||||
verify(mailProducer).sendMailSendMessage(eq(mailLogId),
|
||||
argThat(toMailSet -> toMailSet.contains(mail)),
|
||||
argThat(Collection::isEmpty),
|
||||
argThat(Collection::isEmpty),
|
||||
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送成功,当短信模板关闭时
|
||||
* 发送成功,当邮件模板关闭时
|
||||
*/
|
||||
@Test
|
||||
public void testSendSingleMail_successWhenSmsTemplateDisable() {
|
||||
public void testSendSingleMail_successWhenMailTemplateDisable() {
|
||||
// 准备参数
|
||||
String mail = randomEmail();
|
||||
Long userId = randomLongId();
|
||||
@@ -201,6 +179,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
String templateCode = RandomUtils.randomString();
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
||||
.put("op", "login").build();
|
||||
Collection<String> toMails = Lists.newArrayList(mail);
|
||||
|
||||
// mock MailTemplateService 的方法
|
||||
MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
|
||||
o.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||
@@ -219,15 +199,18 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
|
||||
// mock MailLogService 的方法
|
||||
Long mailLogId = randomLongId();
|
||||
when(mailLogService.createMailLog(eq(userId), eq(userType), eq(mail),
|
||||
when(mailLogService.createMailLog(eq(userId), eq(userType),
|
||||
argThat(toMailSet -> toMailSet.contains(mail)),
|
||||
argThat(Collection::isEmpty),
|
||||
argThat(Collection::isEmpty),
|
||||
eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId);
|
||||
|
||||
// 调用
|
||||
Long resultMailLogId = mailSendService.sendSingleMail(mail, userId, userType, templateCode, templateParams);
|
||||
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams);
|
||||
// 断言
|
||||
assertEquals(mailLogId, resultMailLogId);
|
||||
// 断言调用
|
||||
verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), anyString(),
|
||||
verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), any(), any(), any(),
|
||||
anyLong(), anyString(), anyString(), anyString());
|
||||
}
|
||||
|
||||
@@ -256,12 +239,29 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateMail_notExists() {
|
||||
public void testSendSingleMail_noValidEmail() {
|
||||
// 准备参数
|
||||
// mock 方法
|
||||
Long userId = randomLongId();
|
||||
String templateCode = RandomUtils.randomString();
|
||||
Map<String, Object> templateParams = MapUtil.<String, Object>builder().put("code", "1234")
|
||||
.put("op", "login").build();
|
||||
Collection<String> toMails = Lists.newArrayList("invalid-email"); // 非法邮箱
|
||||
|
||||
// mock MailTemplateService 的方法
|
||||
MailTemplateDO template = randomPojo(MailTemplateDO.class, o -> {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setContent("验证码为{code}, 操作为{op}");
|
||||
o.setParams(Lists.newArrayList("code", "op"));
|
||||
});
|
||||
when(mailTemplateService.getMailTemplateByCodeFromCache(eq(templateCode))).thenReturn(template);
|
||||
|
||||
// mock MailAccountService 的方法
|
||||
MailAccountDO account = randomPojo(MailAccountDO.class);
|
||||
when(mailAccountService.getMailAccountFromCache(eq(template.getAccountId()))).thenReturn(account);
|
||||
|
||||
// 调用,并断言异常
|
||||
assertServiceException(() -> mailSendService.validateMail(null),
|
||||
assertServiceException(() -> mailSendService.sendSingleMail(toMails, null, null, userId,
|
||||
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams),
|
||||
MAIL_SEND_MAIL_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@@ -287,7 +287,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
assertEquals(account.getPort(), mailAccount.getPort());
|
||||
assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
|
||||
return true;
|
||||
}), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true)))
|
||||
}), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()),
|
||||
eq(message.getTitle()), eq(message.getContent()), eq(true)))
|
||||
.thenReturn(messageId);
|
||||
|
||||
// 调用
|
||||
@@ -310,15 +311,16 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
|
||||
// mock 方法(发送邮件)
|
||||
Exception e = new NullPointerException("啦啦啦");
|
||||
mailUtilMock.when(() -> MailUtil.send(argThat(mailAccount -> {
|
||||
assertEquals("芋艿 <7685@qq.com>", mailAccount.getFrom());
|
||||
assertTrue(mailAccount.isAuth());
|
||||
assertEquals(account.getUsername(), mailAccount.getUser());
|
||||
assertArrayEquals(account.getPassword().toCharArray(), mailAccount.getPass());
|
||||
assertEquals(account.getHost(), mailAccount.getHost());
|
||||
assertEquals(account.getPort(), mailAccount.getPort());
|
||||
assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
|
||||
return true;
|
||||
}), eq(message.getMail()), eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e);
|
||||
assertEquals("芋艿 <7685@qq.com>", mailAccount.getFrom());
|
||||
assertTrue(mailAccount.isAuth());
|
||||
assertEquals(account.getUsername(), mailAccount.getUser());
|
||||
assertArrayEquals(account.getPassword().toCharArray(), mailAccount.getPass());
|
||||
assertEquals(account.getHost(), mailAccount.getHost());
|
||||
assertEquals(account.getPort(), mailAccount.getPort());
|
||||
assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
|
||||
return true;
|
||||
}), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()),
|
||||
eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e);
|
||||
|
||||
// 调用
|
||||
mailSendService.doSendMail(message);
|
||||
|
||||
@@ -553,7 +553,9 @@ CREATE TABLE IF NOT EXISTS "system_mail_log" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"user_id" bigint,
|
||||
"user_type" varchar,
|
||||
"to_mail" varchar NOT NULL,
|
||||
"to_mails" varchar NOT NULL,
|
||||
"cc_mails" varchar,
|
||||
"bcc_mails" varchar,
|
||||
"account_id" bigint NOT NULL,
|
||||
"from_mail" varchar NOT NULL,
|
||||
"template_id" bigint NOT NULL,
|
||||
|
||||
Reference in New Issue
Block a user