邮箱模块:完善 log 相关表结构

pull/2/head
YunaiV 2023-01-26 01:57:57 +08:00
parent afced9d420
commit f9ab45df18
13 changed files with 141 additions and 148 deletions

View File

@ -106,6 +106,10 @@
<artifactId>yudao-spring-boot-starter-captcha</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,14 @@
### 请求 /system/mail-template/send-mail 接口 => 成功
POST {{baseUrl}}/system/mail-template/send-mail
Authorization: Bearer {{token}}
Content-Type: application/json
tenant-id: {{adminTenentId}}
{
"templateCode": "test_01",
"mail": "7685413@qq.com",
"templateParams": {
"key01": "value01",
"key02": "value02"
}
}

View File

@ -3,8 +3,10 @@ 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.template.*;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSendReqVO;
import cn.iocoder.yudao.module.system.convert.mail.MailTemplateConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.service.mail.MailSendService;
import cn.iocoder.yudao.module.system.service.mail.MailTemplateService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
@ -25,6 +27,8 @@ public class MailTemplateController {
@Resource
private MailTemplateService mailTempleService;
@Resource
private MailSendService mailSendService;
@PostMapping("/create")
@ApiOperation("创建邮件模版")
@ -73,4 +77,13 @@ public class MailTemplateController {
List<MailTemplateDO> list = mailTempleService.getMailTemplateList();
return success(MailTemplateConvert.INSTANCE.convertList02(list));
}
@PostMapping("/send-mail")
@ApiOperation("发送短信")
@PreAuthorize("@ss.hasPermission('system:mail-template:send-mail')")
public CommonResult<Long> sendMail(@Valid @RequestBody MailTemplateSendReqVO sendReqVO) {
return success(mailSendService.sendSingleMailToAdmin(sendReqVO.getMail(), null,
sendReqVO.getTemplateCode(), sendReqVO.getTemplateParams()));
}
}

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.system.controller.admin.mail.vo.send;
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;
@ApiModel("管理后台 - 邮件发送 Req VO")
@Data
public class MailReqVO { // TODO @wangjingqi1, 不用空格2应该只要传递 templateCode、参数就好title、from、content、附件应该都是参数里的
@ApiModelProperty(value = "邮箱",required = true,example = "yudaoyuanma@123.com")
@NotNull(message = "邮箱账号不能为空")
@Email(message = "邮箱账号格式错误")
private String from;
@ApiModelProperty(value = "标题",example = "标题")
private String title;
@ApiModelProperty(value = "内容",example = "内容")
private String content;
@ApiModelProperty(value = "邮箱模版id",example = "1024")
@NotNull(message = "邮箱模版id不能为空")
private Integer templateId;
@ApiModelProperty(value = "收件人",required = true,example = "yudaoyuanma@123.com")
@NotNull(message = "收件人不能为空")
private List<String> tos;
@ApiModelProperty(value = "附件",example = "附件编码")
private List<String> fileIds;
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.system.controller.admin.mail.vo.template;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Map;
@ApiModel("管理后台 - 邮件发送 Req VO")
@Data
public class MailTemplateSendReqVO {
@ApiModelProperty(value = "接收邮箱", required = true, example = "7685413@qq.com")
@NotEmpty(message = "接收邮箱不能为空")
private String mail;
@ApiModelProperty(value = "模板编码", required = true, example = "test_01")
@NotNull(message = "模板编码不能为空")
private String templateCode;
@ApiModelProperty(value = "模板参数")
private Map<String, Object> templateParams;
}

View File

@ -33,7 +33,7 @@ public interface MailAccountConvert {
.setHost(bean.getHost())
.setPort(bean.getPort())
.setAuth(true)
.setFrom(bean.getFromAddress())
.setFrom(bean.getMail())
.setUser(bean.getUsername())
.setPass(bean.getPassword())
.setSslEnable(bean.getSslEnable());

View File

@ -96,7 +96,7 @@ public class MailLogDO extends BaseDO implements Serializable {
* {@link MailTemplateDO#getParams()}
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String,Object> templateParams;
private Map<String, Object> templateParams;
// ========= 发送相关字段 =========
/**
@ -109,16 +109,13 @@ public class MailLogDO extends BaseDO implements Serializable {
*
*/
private Date sendTime;
// ========= 接收相关字段 =========
/**
* ID
*/
private String sendMessageId;
/**
*
*/
private String sendResult;
/**
* ID
*/
private String messageId;
}

View File

@ -1,13 +1,11 @@
package cn.iocoder.yudao.module.system.mq.message.mail;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
/**
*
@ -19,61 +17,35 @@ import java.util.Map;
public class MailSendMessage extends AbstractStreamMessage {
/**
* id
*
*/
@NotNull(message = "邮箱日志id不能为空")
@NotNull(message = "邮件日志编号不能为空")
private Long logId;
/**
*
*
*/
@NotNull(message = "邮箱地址不能为空")
private String fromAddress;
@NotNull(message = "接收邮件地址不能为空")
private String mail;
/**
*
*
*/
@NotNull(message = "用户名不能为空")
private String username;
@NotNull(message = "邮件账号编号不能为空")
private Long accountId;
/**
*
*
*/
@NotNull(message = "密码不能为空")
private String password;
private String nickname;
/**
*
*/
@NotNull(message = "邮箱模板编号不能为空")
private String templateCode;
/**
*
*/
@NotNull(message = "收件人不能为空")
private String to;
/**
*
*
*/
@NotEmpty(message = "邮件标题不能为空")
private String title;
/**
*
*
*/
@NotEmpty(message = "邮件内容不能为空")
private String content;
/**
*
*/
@NotNull(message = "host不能为空")
private String host;
/**
*
*/
@NotNull(message = "端口号不能为空")
private Integer port;
/**
* SSL
*/
private Boolean sslEnable;
/**
*
*/
private List<KeyValue<String, Object>> templateParams;
@Override
public String getStreamKey() {

View File

@ -1,9 +1,6 @@
package cn.iocoder.yudao.module.system.mq.producer.mail;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.mq.message.mail.MailAccountRefreshMessage;
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
import cn.iocoder.yudao.module.system.mq.message.mail.MailTemplateRefreshMessage;
@ -11,13 +8,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
* Mail Producer
*
* @author wangjingyi
* @date 2021/4/19 13:33
* @since 2021/4/19 13:33
*/
@Slf4j
@Component
@ -46,26 +42,18 @@ public class MailProducer {
* {@link MailSendMessage}
*
* @param sendLogId
* @param mailAccountDO
* @param mailTemplateDO
* @param content
* @param templateParams
* @param to
* @param mail
* @param accountId
* @param nickname
* @param title
* @param content
*/
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.getMail())
.setHost(mailAccountDO.getHost())
.setPort(mailAccountDO.getPort())
.setPassword(mailAccountDO.getPassword())
.setUsername(mailAccountDO.getUsername())
.setSslEnable(mailAccountDO.getSslEnable())
.setTemplateCode(mailTemplateDO.getCode())
.setTitle(mailTemplateDO.getTitle())
.setTo(to)
.setLogId(sendLogId)
.setTemplateParams(templateParams);
public void sendMailSendMessage(Long sendLogId, String mail, Long accountId,
String nickname, String title, String content) {
MailSendMessage message = new MailSendMessage()
.setLogId(sendLogId).setMail(mail).setAccountId(accountId)
.setNickname(nickname).setTitle(title).setContent(content);
redisMQTemplate.send(message);
}
}

View File

@ -11,7 +11,7 @@ import java.util.List;
import java.util.Map;
/**
*
* Service
*
* @author wangjingyi
* @since 2022-03-21
@ -19,7 +19,7 @@ import java.util.Map;
public interface MailLogService {
/**
*
*
*
* @param pageVO
* @return
@ -27,7 +27,7 @@ public interface MailLogService {
PageResult<MailLogDO> getMailLogPage(MailLogPageReqVO pageVO);
/**
*
*
*
* @param exportReqVO
* @return
@ -35,12 +35,12 @@ public interface MailLogService {
List<MailLogDO> getMailLogList(MailLogExportReqVO exportReqVO);
/**
*
*
*
* @param userId
* @param userType
* @param to
* @param mailAccountDO
* @param mailAccountDO
* @param template
* @param templateContent
* @param templateParams

View File

@ -8,7 +8,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailLogMapper;
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
import cn.iocoder.yudao.module.system.service.mail.MailLogService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -19,7 +18,7 @@ import java.util.Map;
import java.util.Objects;
/**
*
* Service
*
* @author wangjingyi
* @since 2022-03-21
@ -42,29 +41,19 @@ public class MailLogServiceImpl implements MailLogService {
}
@Override
public Long createMailLog(Long userId,Integer userType,String to,MailAccountDO mailAccountDO, MailTemplateDO template , String templateContent, Map<String, Object> templateParams, Boolean isSend) {
public Long createMailLog(Long userId, Integer userType, String toMail,
MailAccountDO account, MailTemplateDO template,
String templateContent, Map<String, Object> templateParams, Boolean isSend) {
MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder();
// TODO @wangjingyi使用 builder 的时候,不用每个 set 是一行。DONE
// 根据是否要发送,设置状态
logDOBuilder.sendStatus(Objects.equals(isSend, true) ? MailSendStatusEnum.INIT.getStatus()
: MailSendStatusEnum.IGNORE.getStatus())
// 设置邮箱相关字段
.fromMail(mailAccountDO.getMail())
.accountId(mailAccountDO.getId())
// TODO @wangjingyiuserId、userType
//用户信息
.userId(userId).userType(userType)
//模版信息
.templateId(template.getId()).templateParams(templateParams).templateContent(templateContent);
logDOBuilder.fromMail(mailAccountDO.getMail());
logDOBuilder.accountId(mailAccountDO.getId());
// TODO @wangjingyi每个接收人一条日志。发送多个人就调用多次业务方。因为某个邮箱有问题会导致所有都发送失败。 DONE
// 设置模板相关字段
// TODO @wangjingyi可以参考下 sms 短信的逻辑templateContent、templateParams
// TODO @wangjingyi有结果的时候才是 sendTime 哈 DONE
//logDOBuilder.sendTime(new Date());
// 用户信息
.userId(userId).userType(userType).toMail(toMail)
.accountId(account.getId()).fromMail(account.getMail())
// 模板相关字段
.templateId(template.getId()).templateCode(template.getCode()).templateNickname(template.getNickname())
.templateTitle(template.getTitle()).templateContent(templateContent).templateParams(templateParams);
// 插入数据库
MailLogDO logDO = logDOBuilder.build();
@ -76,7 +65,7 @@ public class MailLogServiceImpl implements MailLogService {
@Override
public void updateMailSendResult(Long logId, String result) {
MailLogDO.MailLogDOBuilder logDOBuilder = MailLogDO.builder();
logDOBuilder.id(logId).sendTime(new Date()).sendResult(result).messageId(result).sendStatus(MailSendStatusEnum.SUCCESS.getStatus());
logDOBuilder.id(logId).sendTime(new Date()).sendResult(result).sendMessageId(result).sendStatus(MailSendStatusEnum.SUCCESS.getStatus());
MailLogDO mailLogDO = logDOBuilder.build();
mailLogMapper.updateById(mailLogDO);
}

View File

@ -100,22 +100,23 @@ public class MailSendServiceImpl implements MailSendService {
Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus());
String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams);
Long sendLogId = mailLogService.createMailLog(userId, userType, mail,
account, template, content, templateParams, isSend); // TODO 芋艿:待测试
account, template, content, templateParams, isSend);
// 发送 MQ 消息,异步执行发送短信
if (isSend) {
mailProducer.sendMailSendMessage(sendLogId, account, template, content, newTemplateParams, mail); // TODO 芋艿:待测试
mailProducer.sendMailSendMessage(sendLogId, mail, account.getId(),
template.getNickname(), template.getTitle(), content);
}
return sendLogId;
}
@Override
public void doSendMail(MailSendMessage message) {
// TODO @wangjingyi直接使用 hutool 发送,不要封装 mail client 哈,因为短信的客户端都是比较统一的 DONE
//装载账号信息
MailAccount account = MailAccountConvert.INSTANCE.convertAccount(message);
//发送邮件
// 装载账号信息
MailAccount mailAccount = MailAccountConvert.INSTANCE.convertAccount(message);
// 发送邮件
try {
String messageId = MailUtil.send(account,message.getTo(),message.getTitle(),message.getContent(),false,null);
String messageId = MailUtil.send(mailAccount, message.getMail(),
message.getTitle(), message.getContent(),true);
mailLogService.updateMailSendResult(message.getLogId() , messageId);
} catch (Exception e){
mailLogService.updateFailMailSendResult(message.getLogId() , e.getMessage());

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.system.service.mail;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MailSendServiceImplTest {
/**
*
*/
@Test
@Disabled
public void testDemo() {
MailAccount mailAccount = new MailAccount()
.setFrom("奥特曼 <ydym_test@163.com>")
.setHost("smtp.163.com").setPort(465).setSslEnable(true)
.setAuth(true).setUser("ydym_test@163.com").setPass("WBZTEINMIFVRYSOE");
String messageId = MailUtil.send(mailAccount, "7685413@qq.com", "主题", "内容", false);
System.out.println("发送结果:" + messageId);
}
}