feat:【system】发送邮件时,携带附件,对应 https://gitee.com/zhijiantianya/yudao-cloud/pulls/233

This commit is contained in:
YunaiV
2026-01-18 15:43:52 +08:00
parent 3db0c41bf3
commit f743ffd195
7 changed files with 60 additions and 50 deletions

View File

@@ -23,14 +23,14 @@ public class MailSendApiImpl implements MailSendApi {
public Long sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) {
return mailSendService.sendSingleMailToAdmin(reqDTO.getUserId(),
reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(),
reqDTO.getTemplateCode(), reqDTO.getTemplateParams());
reqDTO.getTemplateCode(), reqDTO.getTemplateParams(), reqDTO.getAttachments());
}
@Override
public Long sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) {
return mailSendService.sendSingleMailToMember(reqDTO.getUserId(),
reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(),
reqDTO.getTemplateCode(), reqDTO.getTemplateParams());
reqDTO.getTemplateCode(), reqDTO.getTemplateParams(), reqDTO.getAttachments());
}
}

View File

@@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.system.api.mail.dto;
import lombok.Data;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.File;
import java.util.List;
import java.util.Map;
@@ -47,4 +47,9 @@ public class MailSendSingleToUserReqDTO {
*/
private Map<String, Object> templateParams;
/**
* 附件
*/
private File[] attachments;
}

View File

@@ -1,12 +1,11 @@
package cn.iocoder.yudao.module.system.mq.message.mail;
import lombok.Data;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.File;
import java.util.Collection;
import java.util.List;
/**
* 邮箱发送消息
@@ -55,4 +54,9 @@ public class MailSendMessage {
@NotEmpty(message = "邮件内容不能为空")
private String content;
/**
* 附件
*/
private File[] attachments;
}

View File

@@ -1,16 +1,13 @@
package cn.iocoder.yudao.module.system.mq.producer.mail;
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.io.File;
import java.util.Collection;
import java.util.List;
import static java.util.Collections.singletonList;
/**
* Mail 邮件相关消息的 Producer
@@ -28,23 +25,25 @@ public class MailProducer {
/**
* 发送 {@link MailSendMessage} 消息
*
* @param sendLogId 发送日志编码
* @param toMails 接收邮件地址
* @param ccMails 抄送邮件地址
* @param bccMails 密送邮件地址
* @param accountId 邮件账号编号
* @param nickname 邮件发件人
* @param title 邮件标题
* @param content 邮件内容
* @param sendLogId 发送日志编码
* @param toMails 接收邮件地址
* @param ccMails 抄送邮件地址
* @param bccMails 密送邮件地址
* @param accountId 邮件账号编号
* @param nickname 邮件发件人
* @param title 邮件标题
* @param content 邮件内容
* @param attachments 附件
*/
public void sendMailSendMessage(Long sendLogId,
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
Long accountId, String nickname, String title, String content) {
Long accountId, String nickname, String title, String content,
File[] attachments) {
MailSendMessage message = new MailSendMessage()
.setLogId(sendLogId)
.setToMails(toMails).setCcMails(ccMails).setBccMails(bccMails)
.setAccountId(accountId).setNickname(nickname)
.setTitle(title).setContent(content);
.setTitle(title).setContent(content).setAttachments(attachments);
applicationContext.publishEvent(message);
}

View File

@@ -3,6 +3,7 @@ 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.io.File;
import java.util.Collection;
import java.util.Map;
@@ -23,13 +24,15 @@ public interface MailSendService {
* @param bccMails 密送邮箱
* @param templateCode 邮件模版编码
* @param templateParams 邮件模版参数
* @param attachments 附件
* @return 发送日志编号
*/
default Long sendSingleMailToAdmin(Long userId,
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
String templateCode, Map<String, Object> templateParams) {
String templateCode, Map<String, Object> templateParams,
File... attachments) {
return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.ADMIN.getValue(),
templateCode, templateParams);
templateCode, templateParams, attachments);
}
/**
@@ -41,13 +44,15 @@ public interface MailSendService {
* @param bccMails 密送邮箱
* @param templateCode 邮件模版编码
* @param templateParams 邮件模版参数
* @param attachments 附件
* @return 发送日志编号
*/
default Long sendSingleMailToMember(Long userId,
Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
String templateCode, Map<String, Object> templateParams) {
String templateCode, Map<String, Object> templateParams,
File... attachments) {
return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.MEMBER.getValue(),
templateCode, templateParams);
templateCode, templateParams, attachments);
}
/**
@@ -60,11 +65,13 @@ public interface MailSendService {
* @param userType 用户类型
* @param templateCode 邮件模版编码
* @param templateParams 邮件模版参数
* @param attachments 附件
* @return 发送日志编号
*/
Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
Long userId, Integer userType,
String templateCode, Map<String, Object> templateParams);
String templateCode, Map<String, Object> templateParams,
File... attachments);
/**
* 执行真正的邮件发送

View File

@@ -20,6 +20,7 @@ import org.dromara.hutool.extra.mail.MailUtil;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.io.File;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
@@ -56,7 +57,8 @@ public class MailSendServiceImpl implements MailSendService {
@Override
public Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails,
Long userId, Integer userType,
String templateCode, Map<String, Object> templateParams) {
String templateCode, Map<String, Object> templateParams,
File... attachments) {
// 1.1 校验邮箱模版是否合法
MailTemplateDO template = validateMailTemplate(templateCode);
// 1.2 校验邮箱账号是否合法
@@ -94,7 +96,7 @@ public class MailSendServiceImpl implements MailSendService {
// 发送 MQ 消息,异步执行发送短信
if (isSend) {
mailProducer.sendMailSendMessage(sendLogId, toMailSet, ccMailSet, bccMailSet,
account.getId(), template.getNickname(), title, content);
account.getId(), template.getNickname(), title, content, attachments);
}
return sendLogId;
}
@@ -123,7 +125,7 @@ public class MailSendServiceImpl implements MailSendService {
// 2. 发送邮件
try {
String messageId = MailUtil.send(mailAccount, message.getToMails(), message.getCcMails(), message.getBccMails(),
message.getTitle(), message.getContent(), true);
message.getTitle(), message.getContent(), true, message.getAttachments());
// 3. 更新结果(成功)
mailLogService.updateMailSendResult(message.getLogId(), messageId, null);
} catch (Exception e) {

View File

@@ -13,13 +13,15 @@ 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.*;
import org.dromara.hutool.extra.mail.MailAccount;
import org.dromara.hutool.extra.mail.MailUtil;
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.io.File;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -106,7 +108,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
// 调用
Long resultMailLogId = mailSendService.sendSingleMail(toMails, ccMails, bccMails, userId,
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams, (File[]) null);
// 断言
assertEquals(mailLogId, resultMailLogId);
// 断言调用
@@ -114,7 +116,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
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));
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content), isNull());
}
/**
@@ -156,7 +158,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId);
// 调用
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams);
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams, (java.io.File[]) null);
// 断言
assertEquals(mailLogId, resultMailLogId);
// 断言调用
@@ -164,7 +166,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
argThat(toMailSet -> toMailSet.contains(mail)),
argThat(Collection::isEmpty),
argThat(Collection::isEmpty),
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content));
eq(account.getId()), eq(template.getNickname()), eq(title), eq(content), isNull());
}
/**
@@ -206,12 +208,12 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId);
// 调用
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams);
Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams, (java.io.File[]) null);
// 断言
assertEquals(mailLogId, resultMailLogId);
// 断言调用
verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), any(), any(), any(),
anyLong(), anyString(), anyString(), anyString());
anyLong(), anyString(), anyString(), anyString(), any());
}
@Test
@@ -261,7 +263,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
// 调用,并断言异常
assertServiceException(() -> mailSendService.sendSingleMail(toMails, null, null, userId,
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams),
UserTypeEnum.ADMIN.getValue(), templateCode, templateParams, (java.io.File[]) null),
MAIL_SEND_MAIL_NOT_EXISTS);
}
@@ -288,7 +290,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest {
assertEquals(account.getSslEnable(), mailAccount.isSslEnable());
return true;
}), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()),
eq(message.getTitle()), eq(message.getContent()), eq(true)))
eq(message.getTitle()), eq(message.getContent()), eq(true), eq(message.getAttachments())))
.thenReturn(messageId);
// 调用
@@ -310,17 +312,8 @@ 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.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()),
eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e);
mailUtilMock.when(() -> MailUtil.send(any(MailAccount.class), any(), any(), any(),
any(), any(), eq(true), any(java.io.File[].class))).thenThrow(e);
// 调用
mailSendService.doSendMail(message);