Commit f743ffd195df4d38c19eb3a97c1feea159c7cb05
1 parent
3db0c41b
feat:【system】发送邮件时,携带附件,对应 https://gitee.com/zhijiantianya/yudao-cloud/pulls/233
Showing
7 changed files
with
60 additions
and
50 deletions
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/mail/MailSendApiImpl.java
| ... | ... | @@ -23,14 +23,14 @@ public class MailSendApiImpl implements MailSendApi { |
| 23 | 23 | public Long sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) { |
| 24 | 24 | return mailSendService.sendSingleMailToAdmin(reqDTO.getUserId(), |
| 25 | 25 | reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(), |
| 26 | - reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | |
| 26 | + reqDTO.getTemplateCode(), reqDTO.getTemplateParams(), reqDTO.getAttachments()); | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | @Override |
| 30 | 30 | public Long sendSingleMailToMember(MailSendSingleToUserReqDTO reqDTO) { |
| 31 | 31 | return mailSendService.sendSingleMailToMember(reqDTO.getUserId(), |
| 32 | 32 | reqDTO.getToMails(), reqDTO.getCcMails(), reqDTO.getBccMails(), |
| 33 | - reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | |
| 33 | + reqDTO.getTemplateCode(), reqDTO.getTemplateParams(), reqDTO.getAttachments()); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | } | ... | ... |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/mail/dto/MailSendSingleToUserReqDTO.java
| 1 | 1 | package cn.iocoder.yudao.module.system.api.mail.dto; |
| 2 | 2 | |
| 3 | -import lombok.Data; | |
| 4 | - | |
| 5 | 3 | import jakarta.validation.constraints.Email; |
| 6 | 4 | import jakarta.validation.constraints.NotNull; |
| 5 | +import lombok.Data; | |
| 7 | 6 | |
| 7 | +import java.io.File; | |
| 8 | 8 | import java.util.List; |
| 9 | 9 | import java.util.Map; |
| 10 | 10 | |
| ... | ... | @@ -47,4 +47,9 @@ public class MailSendSingleToUserReqDTO { |
| 47 | 47 | */ |
| 48 | 48 | private Map<String, Object> templateParams; |
| 49 | 49 | |
| 50 | + /** | |
| 51 | + * 附件 | |
| 52 | + */ | |
| 53 | + private File[] attachments; | |
| 54 | + | |
| 50 | 55 | } | ... | ... |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/mq/message/mail/MailSendMessage.java
| 1 | 1 | package cn.iocoder.yudao.module.system.mq.message.mail; |
| 2 | 2 | |
| 3 | -import lombok.Data; | |
| 4 | - | |
| 5 | 3 | import jakarta.validation.constraints.NotEmpty; |
| 6 | 4 | import jakarta.validation.constraints.NotNull; |
| 5 | +import lombok.Data; | |
| 7 | 6 | |
| 7 | +import java.io.File; | |
| 8 | 8 | import java.util.Collection; |
| 9 | -import java.util.List; | |
| 10 | 9 | |
| 11 | 10 | /** |
| 12 | 11 | * 邮箱发送消息 |
| ... | ... | @@ -55,4 +54,9 @@ public class MailSendMessage { |
| 55 | 54 | @NotEmpty(message = "邮件内容不能为空") |
| 56 | 55 | private String content; |
| 57 | 56 | |
| 57 | + /** | |
| 58 | + * 附件 | |
| 59 | + */ | |
| 60 | + private File[] attachments; | |
| 61 | + | |
| 58 | 62 | } | ... | ... |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/mq/producer/mail/MailProducer.java
| 1 | 1 | package cn.iocoder.yudao.module.system.mq.producer.mail; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; |
| 4 | +import jakarta.annotation.Resource; | |
| 4 | 5 | import lombok.extern.slf4j.Slf4j; |
| 5 | 6 | import org.springframework.context.ApplicationContext; |
| 6 | 7 | import org.springframework.stereotype.Component; |
| 7 | 8 | |
| 8 | -import jakarta.annotation.Resource; | |
| 9 | - | |
| 9 | +import java.io.File; | |
| 10 | 10 | import java.util.Collection; |
| 11 | -import java.util.List; | |
| 12 | - | |
| 13 | -import static java.util.Collections.singletonList; | |
| 14 | 11 | |
| 15 | 12 | /** |
| 16 | 13 | * Mail 邮件相关消息的 Producer |
| ... | ... | @@ -28,23 +25,25 @@ public class MailProducer { |
| 28 | 25 | /** |
| 29 | 26 | * 发送 {@link MailSendMessage} 消息 |
| 30 | 27 | * |
| 31 | - * @param sendLogId 发送日志编码 | |
| 32 | - * @param toMails 接收邮件地址 | |
| 33 | - * @param ccMails 抄送邮件地址 | |
| 34 | - * @param bccMails 密送邮件地址 | |
| 35 | - * @param accountId 邮件账号编号 | |
| 36 | - * @param nickname 邮件发件人 | |
| 37 | - * @param title 邮件标题 | |
| 38 | - * @param content 邮件内容 | |
| 28 | + * @param sendLogId 发送日志编码 | |
| 29 | + * @param toMails 接收邮件地址 | |
| 30 | + * @param ccMails 抄送邮件地址 | |
| 31 | + * @param bccMails 密送邮件地址 | |
| 32 | + * @param accountId 邮件账号编号 | |
| 33 | + * @param nickname 邮件发件人 | |
| 34 | + * @param title 邮件标题 | |
| 35 | + * @param content 邮件内容 | |
| 36 | + * @param attachments 附件 | |
| 39 | 37 | */ |
| 40 | 38 | public void sendMailSendMessage(Long sendLogId, |
| 41 | 39 | Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 42 | - Long accountId, String nickname, String title, String content) { | |
| 40 | + Long accountId, String nickname, String title, String content, | |
| 41 | + File[] attachments) { | |
| 43 | 42 | MailSendMessage message = new MailSendMessage() |
| 44 | 43 | .setLogId(sendLogId) |
| 45 | 44 | .setToMails(toMails).setCcMails(ccMails).setBccMails(bccMails) |
| 46 | 45 | .setAccountId(accountId).setNickname(nickname) |
| 47 | - .setTitle(title).setContent(content); | |
| 46 | + .setTitle(title).setContent(content).setAttachments(attachments); | |
| 48 | 47 | applicationContext.publishEvent(message); |
| 49 | 48 | } |
| 50 | 49 | ... | ... |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendService.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.mail; |
| 3 | 3 | import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; |
| 4 | 4 | import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage; |
| 5 | 5 | |
| 6 | +import java.io.File; | |
| 6 | 7 | import java.util.Collection; |
| 7 | 8 | import java.util.Map; |
| 8 | 9 | |
| ... | ... | @@ -23,13 +24,15 @@ public interface MailSendService { |
| 23 | 24 | * @param bccMails 密送邮箱 |
| 24 | 25 | * @param templateCode 邮件模版编码 |
| 25 | 26 | * @param templateParams 邮件模版参数 |
| 27 | + * @param attachments 附件 | |
| 26 | 28 | * @return 发送日志编号 |
| 27 | 29 | */ |
| 28 | 30 | default Long sendSingleMailToAdmin(Long userId, |
| 29 | 31 | Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 30 | - String templateCode, Map<String, Object> templateParams) { | |
| 32 | + String templateCode, Map<String, Object> templateParams, | |
| 33 | + File... attachments) { | |
| 31 | 34 | return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.ADMIN.getValue(), |
| 32 | - templateCode, templateParams); | |
| 35 | + templateCode, templateParams, attachments); | |
| 33 | 36 | } |
| 34 | 37 | |
| 35 | 38 | /** |
| ... | ... | @@ -41,13 +44,15 @@ public interface MailSendService { |
| 41 | 44 | * @param bccMails 密送邮箱 |
| 42 | 45 | * @param templateCode 邮件模版编码 |
| 43 | 46 | * @param templateParams 邮件模版参数 |
| 47 | + * @param attachments 附件 | |
| 44 | 48 | * @return 发送日志编号 |
| 45 | 49 | */ |
| 46 | 50 | default Long sendSingleMailToMember(Long userId, |
| 47 | 51 | Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 48 | - String templateCode, Map<String, Object> templateParams) { | |
| 52 | + String templateCode, Map<String, Object> templateParams, | |
| 53 | + File... attachments) { | |
| 49 | 54 | return sendSingleMail(toMails, ccMails, bccMails, userId, UserTypeEnum.MEMBER.getValue(), |
| 50 | - templateCode, templateParams); | |
| 55 | + templateCode, templateParams, attachments); | |
| 51 | 56 | } |
| 52 | 57 | |
| 53 | 58 | /** |
| ... | ... | @@ -60,11 +65,13 @@ public interface MailSendService { |
| 60 | 65 | * @param userType 用户类型 |
| 61 | 66 | * @param templateCode 邮件模版编码 |
| 62 | 67 | * @param templateParams 邮件模版参数 |
| 68 | + * @param attachments 附件 | |
| 63 | 69 | * @return 发送日志编号 |
| 64 | 70 | */ |
| 65 | 71 | Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 66 | 72 | Long userId, Integer userType, |
| 67 | - String templateCode, Map<String, Object> templateParams); | |
| 73 | + String templateCode, Map<String, Object> templateParams, | |
| 74 | + File... attachments); | |
| 68 | 75 | |
| 69 | 76 | /** |
| 70 | 77 | * 执行真正的邮件发送 | ... | ... |
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImpl.java
| ... | ... | @@ -20,6 +20,7 @@ import org.dromara.hutool.extra.mail.MailUtil; |
| 20 | 20 | import org.springframework.stereotype.Service; |
| 21 | 21 | import org.springframework.validation.annotation.Validated; |
| 22 | 22 | |
| 23 | +import java.io.File; | |
| 23 | 24 | import java.util.Collection; |
| 24 | 25 | import java.util.LinkedHashSet; |
| 25 | 26 | import java.util.Map; |
| ... | ... | @@ -56,7 +57,8 @@ public class MailSendServiceImpl implements MailSendService { |
| 56 | 57 | @Override |
| 57 | 58 | public Long sendSingleMail(Collection<String> toMails, Collection<String> ccMails, Collection<String> bccMails, |
| 58 | 59 | Long userId, Integer userType, |
| 59 | - String templateCode, Map<String, Object> templateParams) { | |
| 60 | + String templateCode, Map<String, Object> templateParams, | |
| 61 | + File... attachments) { | |
| 60 | 62 | // 1.1 校验邮箱模版是否合法 |
| 61 | 63 | MailTemplateDO template = validateMailTemplate(templateCode); |
| 62 | 64 | // 1.2 校验邮箱账号是否合法 |
| ... | ... | @@ -94,7 +96,7 @@ public class MailSendServiceImpl implements MailSendService { |
| 94 | 96 | // 发送 MQ 消息,异步执行发送短信 |
| 95 | 97 | if (isSend) { |
| 96 | 98 | mailProducer.sendMailSendMessage(sendLogId, toMailSet, ccMailSet, bccMailSet, |
| 97 | - account.getId(), template.getNickname(), title, content); | |
| 99 | + account.getId(), template.getNickname(), title, content, attachments); | |
| 98 | 100 | } |
| 99 | 101 | return sendLogId; |
| 100 | 102 | } |
| ... | ... | @@ -123,7 +125,7 @@ public class MailSendServiceImpl implements MailSendService { |
| 123 | 125 | // 2. 发送邮件 |
| 124 | 126 | try { |
| 125 | 127 | String messageId = MailUtil.send(mailAccount, message.getToMails(), message.getCcMails(), message.getBccMails(), |
| 126 | - message.getTitle(), message.getContent(), true); | |
| 128 | + message.getTitle(), message.getContent(), true, message.getAttachments()); | |
| 127 | 129 | // 3. 更新结果(成功) |
| 128 | 130 | mailLogService.updateMailSendResult(message.getLogId(), messageId, null); |
| 129 | 131 | } catch (Exception e) { | ... | ... |
yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailSendServiceImplTest.java
| ... | ... | @@ -13,13 +13,15 @@ import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer; |
| 13 | 13 | import cn.iocoder.yudao.module.system.service.member.MemberService; |
| 14 | 14 | import cn.iocoder.yudao.module.system.service.user.AdminUserService; |
| 15 | 15 | import org.assertj.core.util.Lists; |
| 16 | -import org.dromara.hutool.extra.mail.*; | |
| 16 | +import org.dromara.hutool.extra.mail.MailAccount; | |
| 17 | +import org.dromara.hutool.extra.mail.MailUtil; | |
| 17 | 18 | import org.junit.jupiter.api.Disabled; |
| 18 | 19 | import org.junit.jupiter.api.Test; |
| 19 | 20 | import org.mockito.InjectMocks; |
| 20 | 21 | import org.mockito.Mock; |
| 21 | 22 | import org.mockito.MockedStatic; |
| 22 | 23 | |
| 24 | +import java.io.File; | |
| 23 | 25 | import java.util.Collection; |
| 24 | 26 | import java.util.HashMap; |
| 25 | 27 | import java.util.Map; |
| ... | ... | @@ -106,7 +108,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 106 | 108 | |
| 107 | 109 | // 调用 |
| 108 | 110 | Long resultMailLogId = mailSendService.sendSingleMail(toMails, ccMails, bccMails, userId, |
| 109 | - UserTypeEnum.ADMIN.getValue(), templateCode, templateParams); | |
| 111 | + UserTypeEnum.ADMIN.getValue(), templateCode, templateParams, (File[]) null); | |
| 110 | 112 | // 断言 |
| 111 | 113 | assertEquals(mailLogId, resultMailLogId); |
| 112 | 114 | // 断言调用 |
| ... | ... | @@ -114,7 +116,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 114 | 116 | argThat(toMailSet -> toMailSet.contains(user.getEmail()) && toMailSet.contains("admin@test.com")), |
| 115 | 117 | argThat(ccMailSet -> ccMailSet.contains("cc@test.com")), |
| 116 | 118 | argThat(bccMailSet -> bccMailSet.contains("bcc@test.com")), |
| 117 | - eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); | |
| 119 | + eq(account.getId()), eq(template.getNickname()), eq(title), eq(content), isNull()); | |
| 118 | 120 | } |
| 119 | 121 | |
| 120 | 122 | /** |
| ... | ... | @@ -156,7 +158,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 156 | 158 | eq(account), eq(template), eq(content), eq(templateParams), eq(true))).thenReturn(mailLogId); |
| 157 | 159 | |
| 158 | 160 | // 调用 |
| 159 | - Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams); | |
| 161 | + Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams, (java.io.File[]) null); | |
| 160 | 162 | // 断言 |
| 161 | 163 | assertEquals(mailLogId, resultMailLogId); |
| 162 | 164 | // 断言调用 |
| ... | ... | @@ -164,7 +166,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 164 | 166 | argThat(toMailSet -> toMailSet.contains(mail)), |
| 165 | 167 | argThat(Collection::isEmpty), |
| 166 | 168 | argThat(Collection::isEmpty), |
| 167 | - eq(account.getId()), eq(template.getNickname()), eq(title), eq(content)); | |
| 169 | + eq(account.getId()), eq(template.getNickname()), eq(title), eq(content), isNull()); | |
| 168 | 170 | } |
| 169 | 171 | |
| 170 | 172 | /** |
| ... | ... | @@ -206,12 +208,12 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 206 | 208 | eq(account), eq(template), eq(content), eq(templateParams), eq(false))).thenReturn(mailLogId); |
| 207 | 209 | |
| 208 | 210 | // 调用 |
| 209 | - Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams); | |
| 211 | + Long resultMailLogId = mailSendService.sendSingleMail(toMails, null, null, userId, userType, templateCode, templateParams, (java.io.File[]) null); | |
| 210 | 212 | // 断言 |
| 211 | 213 | assertEquals(mailLogId, resultMailLogId); |
| 212 | 214 | // 断言调用 |
| 213 | 215 | verify(mailProducer, times(0)).sendMailSendMessage(anyLong(), any(), any(), any(), |
| 214 | - anyLong(), anyString(), anyString(), anyString()); | |
| 216 | + anyLong(), anyString(), anyString(), anyString(), any()); | |
| 215 | 217 | } |
| 216 | 218 | |
| 217 | 219 | @Test |
| ... | ... | @@ -261,7 +263,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 261 | 263 | |
| 262 | 264 | // 调用,并断言异常 |
| 263 | 265 | assertServiceException(() -> mailSendService.sendSingleMail(toMails, null, null, userId, |
| 264 | - UserTypeEnum.ADMIN.getValue(), templateCode, templateParams), | |
| 266 | + UserTypeEnum.ADMIN.getValue(), templateCode, templateParams, (java.io.File[]) null), | |
| 265 | 267 | MAIL_SEND_MAIL_NOT_EXISTS); |
| 266 | 268 | } |
| 267 | 269 | |
| ... | ... | @@ -288,7 +290,7 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 288 | 290 | assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); |
| 289 | 291 | return true; |
| 290 | 292 | }), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()), |
| 291 | - eq(message.getTitle()), eq(message.getContent()), eq(true))) | |
| 293 | + eq(message.getTitle()), eq(message.getContent()), eq(true), eq(message.getAttachments()))) | |
| 292 | 294 | .thenReturn(messageId); |
| 293 | 295 | |
| 294 | 296 | // 调用 |
| ... | ... | @@ -310,17 +312,8 @@ public class MailSendServiceImplTest extends BaseMockitoUnitTest { |
| 310 | 312 | |
| 311 | 313 | // mock 方法(发送邮件) |
| 312 | 314 | Exception e = new NullPointerException("啦啦啦"); |
| 313 | - mailUtilMock.when(() -> MailUtil.send(argThat(mailAccount -> { | |
| 314 | - assertEquals("芋艿 <7685@qq.com>", mailAccount.getFrom()); | |
| 315 | - assertTrue(mailAccount.isAuth()); | |
| 316 | - assertEquals(account.getUsername(), mailAccount.getUser()); | |
| 317 | - assertArrayEquals(account.getPassword().toCharArray(), mailAccount.getPass()); | |
| 318 | - assertEquals(account.getHost(), mailAccount.getHost()); | |
| 319 | - assertEquals(account.getPort(), mailAccount.getPort()); | |
| 320 | - assertEquals(account.getSslEnable(), mailAccount.isSslEnable()); | |
| 321 | - return true; | |
| 322 | - }), eq(message.getToMails()), eq(message.getCcMails()), eq(message.getBccMails()), | |
| 323 | - eq(message.getTitle()), eq(message.getContent()), eq(true))).thenThrow(e); | |
| 315 | + mailUtilMock.when(() -> MailUtil.send(any(MailAccount.class), any(), any(), any(), | |
| 316 | + any(), any(), eq(true), any(java.io.File[].class))).thenThrow(e); | |
| 324 | 317 | |
| 325 | 318 | // 调用 |
| 326 | 319 | mailSendService.doSendMail(message); | ... | ... |