houzhongjian
2024-09-14 818a0170d8f2950d52cc7300a302356bbc523236
提交 | 用户 | 时间
e7c126 1 package com.iailab.module.system.service.mail;
H 2
3 import cn.hutool.core.util.StrUtil;
4 import cn.hutool.extra.mail.MailAccount;
5 import cn.hutool.extra.mail.MailUtil;
6 import com.iailab.framework.common.enums.CommonStatusEnum;
7 import com.iailab.framework.common.enums.UserTypeEnum;
8 import com.iailab.module.system.dal.dataobject.mail.MailAccountDO;
9 import com.iailab.module.system.dal.dataobject.mail.MailTemplateDO;
10 import com.iailab.module.system.dal.dataobject.user.AdminUserDO;
11 import com.iailab.module.system.mq.message.mail.MailSendMessage;
12 import com.iailab.module.system.mq.producer.mail.MailProducer;
13 import com.iailab.module.system.service.member.MemberService;
14 import com.iailab.module.system.service.user.AdminUserService;
15 import com.google.common.annotations.VisibleForTesting;
16 import lombok.extern.slf4j.Slf4j;
17 import org.springframework.stereotype.Service;
18 import org.springframework.validation.annotation.Validated;
19
20 import javax.annotation.Resource;
21 import java.util.Map;
22
23 import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
24 import static com.iailab.module.system.enums.ErrorCodeConstants.*;
25
26 /**
27  * 邮箱发送 Service 实现类
28  *
29  * @author wangjingyi
30  * @since 2022-03-21
31  */
32 @Service
33 @Validated
34 @Slf4j
35 public class MailSendServiceImpl implements MailSendService {
36
37     @Resource
38     private AdminUserService adminUserService;
39     @Resource
40     private MemberService memberService;
41
42     @Resource
43     private MailAccountService mailAccountService;
44     @Resource
45     private MailTemplateService mailTemplateService;
46
47     @Resource
48     private MailLogService mailLogService;
49     @Resource
50     private MailProducer mailProducer;
51
52     @Override
53     public Long sendSingleMailToAdmin(String mail, Long userId,
54                                       String templateCode, Map<String, Object> templateParams) {
55         // 如果 mail 为空,则加载用户编号对应的邮箱
56         if (StrUtil.isEmpty(mail)) {
57             AdminUserDO user = adminUserService.getUser(userId);
58             if (user != null) {
59                 mail = user.getEmail();
60             }
61         }
62         // 执行发送
63         return sendSingleMail(mail, userId, UserTypeEnum.ADMIN.getValue(), templateCode, templateParams);
64     }
65
66     @Override
67     public Long sendSingleMailToMember(String mail, Long userId,
68                                        String templateCode, Map<String, Object> templateParams) {
69         // 如果 mail 为空,则加载用户编号对应的邮箱
70         if (StrUtil.isEmpty(mail)) {
71             mail = memberService.getMemberUserEmail(userId);
72         }
73         // 执行发送
74         return sendSingleMail(mail, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams);
75     }
76
77     @Override
78     public Long sendSingleMail(String mail, Long userId, Integer userType,
79                                String templateCode, Map<String, Object> templateParams) {
80         // 校验邮箱模版是否合法
81         MailTemplateDO template = validateMailTemplate(templateCode);
82         // 校验邮箱账号是否合法
83         MailAccountDO account = validateMailAccount(template.getAccountId());
84
85         // 校验邮箱是否存在
86         mail = validateMail(mail);
87         validateTemplateParams(template, templateParams);
88
89         // 创建发送日志。如果模板被禁用,则不发送短信,只记录日志
90         Boolean isSend = CommonStatusEnum.ENABLE.getStatus().equals(template.getStatus());
91         String title = mailTemplateService.formatMailTemplateContent(template.getTitle(), templateParams);
92         String content = mailTemplateService.formatMailTemplateContent(template.getContent(), templateParams);
93         Long sendLogId = mailLogService.createMailLog(userId, userType, mail,
94                 account, template, content, templateParams, isSend);
95         // 发送 MQ 消息,异步执行发送短信
96         if (isSend) {
97             mailProducer.sendMailSendMessage(sendLogId, mail, account.getId(),
98                     template.getNickname(), title, content);
99         }
100         return sendLogId;
101     }
102
103     @Override
104     public void doSendMail(MailSendMessage message) {
105         // 1. 创建发送账号
106         MailAccountDO account = validateMailAccount(message.getAccountId());
107         MailAccount mailAccount  = buildMailAccount(account, message.getNickname());
108         // 2. 发送邮件
109         try {
110             String messageId = MailUtil.send(mailAccount, message.getMail(),
111                     message.getTitle(), message.getContent(), true);
112             // 3. 更新结果(成功)
113             mailLogService.updateMailSendResult(message.getLogId(), messageId, null);
114         } catch (Exception e) {
115             // 3. 更新结果(异常)
116             mailLogService.updateMailSendResult(message.getLogId(), null, e);
117         }
118     }
119
120     private MailAccount buildMailAccount(MailAccountDO account, String nickname) {
121         String from = StrUtil.isNotEmpty(nickname) ? nickname + " <" + account.getMail() + ">" : account.getMail();
122         return new MailAccount().setFrom(from).setAuth(true)
123                 .setUser(account.getUsername()).setPass(account.getPassword())
124                 .setHost(account.getHost()).setPort(account.getPort())
125                 .setSslEnable(account.getSslEnable()).setStarttlsEnable(account.getStarttlsEnable());
126     }
127
128     @VisibleForTesting
129     MailTemplateDO validateMailTemplate(String templateCode) {
130         // 获得邮件模板。考虑到效率,从缓存中获取
131         MailTemplateDO template = mailTemplateService.getMailTemplateByCodeFromCache(templateCode);
132         // 邮件模板不存在
133         if (template == null) {
134             throw exception(MAIL_TEMPLATE_NOT_EXISTS);
135         }
136         return template;
137     }
138
139     @VisibleForTesting
140     MailAccountDO validateMailAccount(Long accountId) {
141         // 获得邮箱账号。考虑到效率,从缓存中获取
142         MailAccountDO account = mailAccountService.getMailAccountFromCache(accountId);
143         // 邮箱账号不存在
144         if (account == null) {
145             throw exception(MAIL_ACCOUNT_NOT_EXISTS);
146         }
147         return account;
148     }
149
150     @VisibleForTesting
151     String validateMail(String mail) {
152         if (StrUtil.isEmpty(mail)) {
153             throw exception(MAIL_SEND_MAIL_NOT_EXISTS);
154         }
155         return mail;
156     }
157
158     /**
159      * 校验邮件参数是否确实
160      *
161      * @param template 邮箱模板
162      * @param templateParams 参数列表
163      */
164     @VisibleForTesting
165     void validateTemplateParams(MailTemplateDO template, Map<String, Object> templateParams) {
166         template.getParams().forEach(key -> {
167             Object value = templateParams.get(key);
168             if (value == null) {
169                 throw exception(MAIL_SEND_TEMPLATE_PARAM_MISS, key);
170             }
171         });
172     }
173
174 }