|
|
@@ -8,37 +8,104 @@ import com.storlead.framework.common.constant.CommonConstant;
|
|
|
import com.storlead.framework.common.util.encryptor.AccessKeyEncryptor;
|
|
|
import com.storlead.framework.mybatis.service.impl.MyBaseServiceImpl;
|
|
|
import com.storlead.framework.web.exception.WebException;
|
|
|
+import com.storlead.sales.mail.common.entity.MailTempAttachmentEntity;
|
|
|
import com.storlead.sales.mail.common.entity.SmtpPopSettingsEntity;
|
|
|
import com.storlead.sales.mail.common.enums.MailSceneEnum;
|
|
|
+import com.storlead.sales.mail.common.properties.MailFileProperties;
|
|
|
import com.storlead.sales.mail.common.service.MailAccountBizService;
|
|
|
+import com.storlead.sales.mail.common.service.MailTempAttachmentService;
|
|
|
import com.storlead.sales.mail.common.transport.MailTransportSupport;
|
|
|
+import com.storlead.sales.mail.common.util.EmailHelper;
|
|
|
+import com.storlead.sales.mail.mkt.entity.MktMailAttachmentEntity;
|
|
|
import com.storlead.sales.mail.mkt.entity.MktMailMessageEntity;
|
|
|
import com.storlead.sales.mail.mkt.mapper.MktMailMessageMapper;
|
|
|
import com.storlead.sales.mail.mkt.pojo.MktMailQueryDTO;
|
|
|
import com.storlead.sales.mail.mkt.pojo.MktSendMailDTO;
|
|
|
+import com.storlead.sales.mail.mkt.service.MktMailAttachmentService;
|
|
|
import com.storlead.sales.mail.mkt.service.MktMailMessageService;
|
|
|
+import lombok.extern.log4j.Log4j2;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
+import javax.activation.DataHandler;
|
|
|
+import javax.activation.DataSource;
|
|
|
+import javax.activation.FileDataSource;
|
|
|
import javax.annotation.Resource;
|
|
|
+import javax.mail.BodyPart;
|
|
|
import javax.mail.Message;
|
|
|
+import javax.mail.Multipart;
|
|
|
import javax.mail.Session;
|
|
|
import javax.mail.internet.InternetAddress;
|
|
|
+import javax.mail.internet.MimeBodyPart;
|
|
|
import javax.mail.internet.MimeMessage;
|
|
|
+import javax.mail.internet.MimeMultipart;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
+import java.util.Objects;
|
|
|
import java.util.UUID;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+/**
|
|
|
+ * 营销邮件:对齐 CRM 草稿 / 附件 / 延时 / 发送,成功后写入 mkt_mail_attachment。
|
|
|
+ */
|
|
|
+@Log4j2
|
|
|
@Service
|
|
|
public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageMapper, MktMailMessageEntity>
|
|
|
implements MktMailMessageService {
|
|
|
|
|
|
+ /** 草稿 */
|
|
|
+ public static final int STATUS_DRAFT = -2;
|
|
|
+ /** 待定时发送 */
|
|
|
+ public static final int STATUS_DELAY = -1;
|
|
|
+ /** 发送中 */
|
|
|
+ public static final int STATUS_SENDING = 0;
|
|
|
+ /** 成功 */
|
|
|
+ public static final int STATUS_SUCCESS = 1;
|
|
|
+ /** 失败 */
|
|
|
+ public static final int STATUS_FAIL = 2;
|
|
|
+
|
|
|
@Resource
|
|
|
private MailAccountBizService mailAccountBizService;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private MailTempAttachmentService tempAttachmentService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MktMailAttachmentService mktMailAttachmentService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MailFileProperties mailFileProperties;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 打开追踪像素根地址,需可被收件方公网访问,例如 https://host/router/mail
|
|
|
+ */
|
|
|
+ @Value("${storlead.mail.track-base-url:${domainname:}}")
|
|
|
+ private String trackBaseUrl;
|
|
|
+
|
|
|
@Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public MktMailMessageEntity saveDraft(MktSendMailDTO dto, Long operatorId) {
|
|
|
+ if (dto == null || dto.getAccountId() == null) {
|
|
|
+ throw new WebException("发信账户不能为空");
|
|
|
+ }
|
|
|
+ SmtpPopSettingsEntity account = mailAccountBizService.requireAccount(dto.getAccountId(), MailSceneEnum.MKT);
|
|
|
+ MktMailMessageEntity entity = resolveWritableEntity(dto.getId(), operatorId);
|
|
|
+ fillMessageFields(entity, dto, account, operatorId);
|
|
|
+ entity.setStatus(STATUS_DRAFT);
|
|
|
+ entity.setDelaySendTime(dto.getDelaySendTime());
|
|
|
+ ensureTrackToken(entity, dto.getIsTrack());
|
|
|
+ this.saveOrUpdate(entity);
|
|
|
+ bindTempAttachments(entity.getId(), dto.getFileIds(), operatorId);
|
|
|
+ copyFormalToTemp(entity.getId(), dto.getOldFileIds(), operatorId);
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
public MktMailMessageEntity send(MktSendMailDTO dto, Long operatorId) {
|
|
|
if (dto == null || dto.getAccountId() == null) {
|
|
|
throw new WebException("发信账户不能为空");
|
|
|
@@ -51,39 +118,27 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
}
|
|
|
SmtpPopSettingsEntity account = mailAccountBizService.requireAccount(dto.getAccountId(), MailSceneEnum.MKT);
|
|
|
|
|
|
- MktMailMessageEntity entity = new MktMailMessageEntity();
|
|
|
- entity.setAccountId(account.getId());
|
|
|
- entity.setOrgId(account.getOrgId());
|
|
|
- entity.setBizRef(dto.getBizRef());
|
|
|
- entity.setBizBatchNo(dto.getBizBatchNo());
|
|
|
- entity.setSubject(dto.getSubject());
|
|
|
- entity.setFromAddr(account.getEmailAddress());
|
|
|
- entity.setFromName(account.getSenderNickName());
|
|
|
- entity.setRecipient(dto.getRecipient().trim());
|
|
|
- entity.setRecipientCc(joinEmails(dto.getRecipientCcList()));
|
|
|
- entity.setRecipientBcc(joinEmails(dto.getRecipientBccList()));
|
|
|
- entity.setContent(dto.getContent());
|
|
|
- entity.setIsTrack(dto.getIsTrack() == null ? 0 : dto.getIsTrack());
|
|
|
- entity.setOpened(0);
|
|
|
- entity.setOpenCount(0);
|
|
|
- entity.setDelaySendTime(dto.getDelaySendTime());
|
|
|
- entity.setOwnerBy(operatorId);
|
|
|
- entity.setCreateBy(operatorId);
|
|
|
- entity.setIsDelete(CommonConstant.DEL_FLAG_0);
|
|
|
- entity.setEnabled(Boolean.TRUE);
|
|
|
- if (Integer.valueOf(1).equals(entity.getIsTrack())) {
|
|
|
- entity.setTrackToken(UUID.randomUUID().toString().replace("-", ""));
|
|
|
- }
|
|
|
+ MktMailMessageEntity entity = resolveWritableEntity(dto.getId(), operatorId);
|
|
|
+ fillMessageFields(entity, dto, account, operatorId);
|
|
|
+ ensureTrackToken(entity, dto.getIsTrack());
|
|
|
|
|
|
boolean delayed = dto.getDelaySendTime() != null && dto.getDelaySendTime().after(new Date());
|
|
|
if (delayed) {
|
|
|
- entity.setStatus(-1);
|
|
|
- this.save(entity);
|
|
|
+ entity.setStatus(STATUS_DELAY);
|
|
|
+ entity.setDelaySendTime(dto.getDelaySendTime());
|
|
|
+ this.saveOrUpdate(entity);
|
|
|
+ bindTempAttachments(entity.getId(), dto.getFileIds(), operatorId);
|
|
|
+ copyFormalToTemp(entity.getId(), dto.getOldFileIds(), operatorId);
|
|
|
return entity;
|
|
|
}
|
|
|
|
|
|
- entity.setStatus(0);
|
|
|
- this.save(entity);
|
|
|
+ entity.setStatus(STATUS_SENDING);
|
|
|
+ entity.setDelaySendTime(null);
|
|
|
+ this.saveOrUpdate(entity);
|
|
|
+ bindTempAttachments(entity.getId(), dto.getFileIds(), operatorId);
|
|
|
+ // 正式附件拷入临时表,MIME 与成功后转正式统一按 mailId 处理,避免重复挂载
|
|
|
+ copyFormalToTemp(entity.getId(), dto.getOldFileIds(), operatorId);
|
|
|
+
|
|
|
doSmtpSend(entity, decryptAccount(account));
|
|
|
return entity;
|
|
|
}
|
|
|
@@ -94,7 +149,7 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
List<MktMailMessageEntity> dueList = this.list(new LambdaQueryWrapper<MktMailMessageEntity>()
|
|
|
.select(MktMailMessageEntity::getId, MktMailMessageEntity::getAccountId)
|
|
|
.eq(MktMailMessageEntity::getIsDelete, CommonConstant.DEL_FLAG_0)
|
|
|
- .eq(MktMailMessageEntity::getStatus, -1)
|
|
|
+ .eq(MktMailMessageEntity::getStatus, STATUS_DELAY)
|
|
|
.isNotNull(MktMailMessageEntity::getDelaySendTime)
|
|
|
.le(MktMailMessageEntity::getDelaySendTime, now));
|
|
|
if (CollectionUtils.isEmpty(dueList)) {
|
|
|
@@ -102,15 +157,15 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
}
|
|
|
List<Long> ids = dueList.stream().map(MktMailMessageEntity::getId).collect(Collectors.toList());
|
|
|
LambdaUpdateWrapper<MktMailMessageEntity> claiming = new LambdaUpdateWrapper<>();
|
|
|
- claiming.set(MktMailMessageEntity::getStatus, 0);
|
|
|
+ claiming.set(MktMailMessageEntity::getStatus, STATUS_SENDING);
|
|
|
claiming.in(MktMailMessageEntity::getId, ids);
|
|
|
- claiming.eq(MktMailMessageEntity::getStatus, -1);
|
|
|
+ claiming.eq(MktMailMessageEntity::getStatus, STATUS_DELAY);
|
|
|
this.update(claiming);
|
|
|
|
|
|
int success = 0;
|
|
|
for (MktMailMessageEntity item : dueList) {
|
|
|
MktMailMessageEntity entity = this.getById(item.getId());
|
|
|
- if (entity == null || !Integer.valueOf(0).equals(entity.getStatus())) {
|
|
|
+ if (entity == null || !Integer.valueOf(STATUS_SENDING).equals(entity.getStatus())) {
|
|
|
continue;
|
|
|
}
|
|
|
try {
|
|
|
@@ -118,7 +173,8 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
doSmtpSend(entity, decryptAccount(account));
|
|
|
success++;
|
|
|
} catch (Exception ex) {
|
|
|
- entity.setStatus(2);
|
|
|
+ log.error("mkt delay send fail, id={}", item.getId(), ex);
|
|
|
+ entity.setStatus(STATUS_FAIL);
|
|
|
entity.setFailReason(ex.getMessage());
|
|
|
this.updateById(entity);
|
|
|
}
|
|
|
@@ -147,6 +203,32 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
return this.page(page, wrapper);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public MktMailMessageEntity getDetail(Long id, Long operatorId) {
|
|
|
+ if (id == null) {
|
|
|
+ throw new WebException("参数错误");
|
|
|
+ }
|
|
|
+ MktMailMessageEntity entity = this.getById(id);
|
|
|
+ if (entity == null || !Objects.equals(entity.getIsDelete(), CommonConstant.DEL_FLAG_0)) {
|
|
|
+ throw new WebException("邮件不存在");
|
|
|
+ }
|
|
|
+ if (operatorId != null && entity.getOwnerBy() != null && !Objects.equals(entity.getOwnerBy(), operatorId)) {
|
|
|
+ throw new WebException("无权访问该邮件");
|
|
|
+ }
|
|
|
+ // 发送成功:正式附件;其余状态(草稿/延时/发送中/失败):临时附件
|
|
|
+ if (Integer.valueOf(STATUS_SUCCESS).equals(entity.getStatus())) {
|
|
|
+ entity.setAttachments(mktMailAttachmentService.listByMailId(id));
|
|
|
+ } else {
|
|
|
+ List<MailTempAttachmentEntity> temps = resolveTempAttachments(id);
|
|
|
+ if (!CollectionUtils.isEmpty(temps)) {
|
|
|
+ temps.forEach(e -> e.setFileSizeName(
|
|
|
+ MktMailAttachmentServiceImpl.formatFileSize(e.getFileSize())));
|
|
|
+ }
|
|
|
+ entity.setAttachments(temps);
|
|
|
+ }
|
|
|
+ return entity;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public boolean markOpened(String trackToken) {
|
|
|
if (!StringUtils.hasText(trackToken)) {
|
|
|
@@ -171,36 +253,230 @@ public class MktMailMessageServiceImpl extends MyBaseServiceImpl<MktMailMessageM
|
|
|
private void doSmtpSend(MktMailMessageEntity entity, SmtpPopSettingsEntity account) {
|
|
|
try {
|
|
|
Session session = MailTransportSupport.createSmtpSession(account);
|
|
|
- MimeMessage message = new MimeMessage(session);
|
|
|
- String fromName = StringUtils.hasText(account.getSenderNickName())
|
|
|
- ? account.getSenderNickName() : account.getEmailAddress();
|
|
|
- message.setFrom(new InternetAddress(account.getEmailAddress(), fromName, "UTF-8"));
|
|
|
- message.setRecipient(Message.RecipientType.TO, new InternetAddress(entity.getRecipient()));
|
|
|
- if (StringUtils.hasText(entity.getRecipientCc())) {
|
|
|
- message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(entity.getRecipientCc()));
|
|
|
- }
|
|
|
- if (StringUtils.hasText(entity.getRecipientBcc())) {
|
|
|
- message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(entity.getRecipientBcc()));
|
|
|
- }
|
|
|
- message.setSubject(entity.getSubject(), "UTF-8");
|
|
|
- String html = entity.getContent() == null ? "" : entity.getContent();
|
|
|
- message.setContent(html, "text/html;charset=UTF-8");
|
|
|
- message.saveChanges();
|
|
|
+ MimeMessage message = buildMimeMessage(session, entity, account);
|
|
|
MailTransportSupport.send(message);
|
|
|
|
|
|
entity.setMessageId(message.getMessageID());
|
|
|
- entity.setStatus(1);
|
|
|
+ entity.setStatus(STATUS_SUCCESS);
|
|
|
entity.setSentTime(new Date());
|
|
|
entity.setFailReason(null);
|
|
|
this.updateById(entity);
|
|
|
+ promoteTempAttachments(entity);
|
|
|
} catch (Exception ex) {
|
|
|
- entity.setStatus(2);
|
|
|
+ entity.setStatus(STATUS_FAIL);
|
|
|
entity.setFailReason(ex.getMessage());
|
|
|
this.updateById(entity);
|
|
|
throw new WebException("营销邮件发送失败: " + ex.getMessage(), ex);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private MimeMessage buildMimeMessage(Session session,
|
|
|
+ MktMailMessageEntity entity,
|
|
|
+ SmtpPopSettingsEntity account) throws Exception {
|
|
|
+ MimeMessage message = new MimeMessage(session);
|
|
|
+ String fromName = StringUtils.hasText(account.getSenderNickName())
|
|
|
+ ? account.getSenderNickName() : account.getEmailAddress();
|
|
|
+ message.setFrom(new InternetAddress(account.getEmailAddress(), fromName, "UTF-8"));
|
|
|
+ message.setRecipient(Message.RecipientType.TO, new InternetAddress(entity.getRecipient()));
|
|
|
+ if (StringUtils.hasText(entity.getRecipientCc())) {
|
|
|
+ message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(entity.getRecipientCc()));
|
|
|
+ }
|
|
|
+ if (StringUtils.hasText(entity.getRecipientBcc())) {
|
|
|
+ message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(entity.getRecipientBcc()));
|
|
|
+ }
|
|
|
+ message.setSubject(entity.getSubject(), "UTF-8");
|
|
|
+
|
|
|
+ Multipart multipart = new MimeMultipart();
|
|
|
+ BodyPart htmlPart = new MimeBodyPart();
|
|
|
+ List<MimeBodyPart> imageParts = new ArrayList<>();
|
|
|
+ String html = entity.getContent() == null ? "" : entity.getContent();
|
|
|
+ html = injectTrackPixel(html, entity);
|
|
|
+ String updatedHtml = EmailHelper.convertImageUrlsToCidBodyPart(
|
|
|
+ html, imageParts, mailFileProperties.getPath().getJpeg(), multipart);
|
|
|
+ if (updatedHtml == null) {
|
|
|
+ updatedHtml = html;
|
|
|
+ }
|
|
|
+ htmlPart.setContent(updatedHtml, "text/html; charset=UTF-8");
|
|
|
+ multipart.addBodyPart(htmlPart);
|
|
|
+
|
|
|
+ List<MailTempAttachmentEntity> temps = resolveTempAttachments(entity.getId());
|
|
|
+ for (MailTempAttachmentEntity attachment : temps) {
|
|
|
+ multipart.addBodyPart(toAttachmentBodyPart(attachment.getFilePath(),
|
|
|
+ attachment.getFileName(), attachment.getFileExt()));
|
|
|
+ }
|
|
|
+
|
|
|
+ message.setContent(multipart);
|
|
|
+ message.saveChanges();
|
|
|
+ return message;
|
|
|
+ }
|
|
|
+
|
|
|
+ private BodyPart toAttachmentBodyPart(String relativePath, String fileName, String fileExt) throws Exception {
|
|
|
+ BodyPart messageBodyPart = new MimeBodyPart();
|
|
|
+ String filePath = mailFileProperties.getPath().getPath() + relativePath;
|
|
|
+ String fullName = fileName + (StringUtils.hasText(fileExt) ? "." + fileExt : "");
|
|
|
+ DataSource fileSource = new FileDataSource(filePath);
|
|
|
+ messageBodyPart.setDataHandler(new DataHandler(fileSource));
|
|
|
+ messageBodyPart.setFileName(fullName);
|
|
|
+ return messageBodyPart;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<MailTempAttachmentEntity> resolveTempAttachments(Long mailId) {
|
|
|
+ if (mailId == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ return tempAttachmentService.list(new LambdaQueryWrapper<MailTempAttachmentEntity>()
|
|
|
+ .eq(MailTempAttachmentEntity::getEmailId, mailId)
|
|
|
+ .eq(MailTempAttachmentEntity::getScene, MailSceneEnum.MKT.getCode()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String injectTrackPixel(String html, MktMailMessageEntity entity) {
|
|
|
+ if (!Integer.valueOf(1).equals(entity.getIsTrack()) || !StringUtils.hasText(entity.getTrackToken())) {
|
|
|
+ return html;
|
|
|
+ }
|
|
|
+ if (!StringUtils.hasText(trackBaseUrl)) {
|
|
|
+ log.warn("storlead.mail.track-base-url 未配置,跳过打开追踪像素注入, mailId={}", entity.getId());
|
|
|
+ return html;
|
|
|
+ }
|
|
|
+ String base = trackBaseUrl.endsWith("/") ? trackBaseUrl.substring(0, trackBaseUrl.length() - 1) : trackBaseUrl;
|
|
|
+ String pixel = "<img src=\"" + base + "/mail/mkt/track/" + entity.getTrackToken()
|
|
|
+ + "\" width=\"1\" height=\"1\" style=\"display:none\" alt=\"\"/>";
|
|
|
+ return html + pixel;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void promoteTempAttachments(MktMailMessageEntity entity) {
|
|
|
+ List<MailTempAttachmentEntity> temps = tempAttachmentService.list(
|
|
|
+ new LambdaQueryWrapper<MailTempAttachmentEntity>()
|
|
|
+ .eq(MailTempAttachmentEntity::getEmailId, entity.getId())
|
|
|
+ .eq(MailTempAttachmentEntity::getScene, MailSceneEnum.MKT.getCode()));
|
|
|
+ if (CollectionUtils.isEmpty(temps)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<MktMailAttachmentEntity> formals = new ArrayList<>();
|
|
|
+ for (MailTempAttachmentEntity temp : temps) {
|
|
|
+ MktMailAttachmentEntity formal = new MktMailAttachmentEntity();
|
|
|
+ formal.setMailId(entity.getId());
|
|
|
+ formal.setAccountId(entity.getAccountId());
|
|
|
+ formal.setFileCode(temp.getFileCode());
|
|
|
+ formal.setFileName(temp.getFileName());
|
|
|
+ formal.setFilePath(temp.getFilePath());
|
|
|
+ formal.setFileSize(temp.getFileSize());
|
|
|
+ formal.setFileExt(temp.getFileExt());
|
|
|
+ formal.setOwnerBy(entity.getOwnerBy());
|
|
|
+ formal.setCreateBy(entity.getCreateBy());
|
|
|
+ formal.setIsDelete(CommonConstant.DEL_FLAG_0);
|
|
|
+ formal.setEnabled(Boolean.TRUE);
|
|
|
+ formals.add(formal);
|
|
|
+ }
|
|
|
+ mktMailAttachmentService.saveBatch(formals);
|
|
|
+ tempAttachmentService.removeByIds(temps.stream().map(MailTempAttachmentEntity::getId).collect(Collectors.toList()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void bindTempAttachments(Long mailId, List<Long> fileIds, Long operatorId) {
|
|
|
+ if (CollectionUtils.isEmpty(fileIds) || mailId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ LambdaUpdateWrapper<MailTempAttachmentEntity> wrapper = new LambdaUpdateWrapper<>();
|
|
|
+ wrapper.set(MailTempAttachmentEntity::getEmailId, mailId);
|
|
|
+ wrapper.set(MailTempAttachmentEntity::getScene, MailSceneEnum.MKT.getCode());
|
|
|
+ if (operatorId != null) {
|
|
|
+ wrapper.set(MailTempAttachmentEntity::getOwnerBy, operatorId);
|
|
|
+ }
|
|
|
+ wrapper.in(MailTempAttachmentEntity::getId, fileIds);
|
|
|
+ tempAttachmentService.update(wrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void copyFormalToTemp(Long mailId, List<Long> oldFileIds, Long operatorId) {
|
|
|
+ if (CollectionUtils.isEmpty(oldFileIds) || mailId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<MktMailAttachmentEntity> formals = mktMailAttachmentService.list(
|
|
|
+ new LambdaQueryWrapper<MktMailAttachmentEntity>().in(MktMailAttachmentEntity::getId, oldFileIds));
|
|
|
+ if (CollectionUtils.isEmpty(formals)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<MailTempAttachmentEntity> temps = new ArrayList<>();
|
|
|
+ for (MktMailAttachmentEntity formal : formals) {
|
|
|
+ MailTempAttachmentEntity temp = new MailTempAttachmentEntity();
|
|
|
+ temp.setEmailId(mailId);
|
|
|
+ temp.setFileCode(formal.getFileCode());
|
|
|
+ temp.setFileName(formal.getFileName());
|
|
|
+ temp.setFilePath(formal.getFilePath());
|
|
|
+ temp.setFileSize(formal.getFileSize());
|
|
|
+ temp.setFileExt(formal.getFileExt());
|
|
|
+ temp.setScene(MailSceneEnum.MKT.getCode());
|
|
|
+ temp.setOwnerBy(operatorId);
|
|
|
+ temp.setCreateBy(operatorId);
|
|
|
+ temp.setIsDelete(CommonConstant.DEL_FLAG_0);
|
|
|
+ temp.setEnabled(Boolean.TRUE);
|
|
|
+ temps.add(temp);
|
|
|
+ }
|
|
|
+ tempAttachmentService.saveBatch(temps);
|
|
|
+ }
|
|
|
+
|
|
|
+ private MktMailMessageEntity resolveWritableEntity(Long id, Long operatorId) {
|
|
|
+ if (id == null) {
|
|
|
+ return new MktMailMessageEntity();
|
|
|
+ }
|
|
|
+ MktMailMessageEntity existing = this.getById(id);
|
|
|
+ if (existing == null || !Objects.equals(existing.getIsDelete(), CommonConstant.DEL_FLAG_0)) {
|
|
|
+ throw new WebException("邮件不存在");
|
|
|
+ }
|
|
|
+ if (operatorId != null && existing.getOwnerBy() != null && !Objects.equals(existing.getOwnerBy(), operatorId)) {
|
|
|
+ throw new WebException("无权操作该邮件");
|
|
|
+ }
|
|
|
+ Integer status = existing.getStatus();
|
|
|
+ if (status != null && status != STATUS_DRAFT && status != STATUS_DELAY && status != STATUS_FAIL) {
|
|
|
+ throw new WebException("当前状态不可编辑");
|
|
|
+ }
|
|
|
+ return existing;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void fillMessageFields(MktMailMessageEntity entity,
|
|
|
+ MktSendMailDTO dto,
|
|
|
+ SmtpPopSettingsEntity account,
|
|
|
+ Long operatorId) {
|
|
|
+ entity.setAccountId(account.getId());
|
|
|
+ entity.setOrgId(account.getOrgId());
|
|
|
+ entity.setBizRef(dto.getBizRef());
|
|
|
+ entity.setBizBatchNo(dto.getBizBatchNo());
|
|
|
+ entity.setSubject(dto.getSubject());
|
|
|
+ entity.setFromAddr(account.getEmailAddress());
|
|
|
+ entity.setFromName(account.getSenderNickName());
|
|
|
+ if (StringUtils.hasText(dto.getRecipient())) {
|
|
|
+ entity.setRecipient(dto.getRecipient().trim());
|
|
|
+ } else if (!StringUtils.hasText(entity.getRecipient())) {
|
|
|
+ // mkt_mail_message.recipient 非空;草稿允许先空串
|
|
|
+ entity.setRecipient("");
|
|
|
+ }
|
|
|
+ entity.setRecipientCc(joinEmails(dto.getRecipientCcList()));
|
|
|
+ entity.setRecipientBcc(joinEmails(dto.getRecipientBccList()));
|
|
|
+ entity.setContent(dto.getContent());
|
|
|
+ entity.setIsTrack(dto.getIsTrack() == null ? 0 : dto.getIsTrack());
|
|
|
+ if (entity.getOpened() == null) {
|
|
|
+ entity.setOpened(0);
|
|
|
+ }
|
|
|
+ if (entity.getOpenCount() == null) {
|
|
|
+ entity.setOpenCount(0);
|
|
|
+ }
|
|
|
+ entity.setOwnerBy(operatorId);
|
|
|
+ if (entity.getId() == null) {
|
|
|
+ entity.setCreateBy(operatorId);
|
|
|
+ }
|
|
|
+ entity.setIsDelete(CommonConstant.DEL_FLAG_0);
|
|
|
+ entity.setEnabled(Boolean.TRUE);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ensureTrackToken(MktMailMessageEntity entity, Integer isTrack) {
|
|
|
+ int track = isTrack == null ? (entity.getIsTrack() == null ? 0 : entity.getIsTrack()) : isTrack;
|
|
|
+ entity.setIsTrack(track);
|
|
|
+ if (track == 1 && !StringUtils.hasText(entity.getTrackToken())) {
|
|
|
+ entity.setTrackToken(UUID.randomUUID().toString().replace("-", ""));
|
|
|
+ }
|
|
|
+ if (track != 1) {
|
|
|
+ entity.setTrackToken(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private SmtpPopSettingsEntity decryptAccount(SmtpPopSettingsEntity account) {
|
|
|
AccessKeyEncryptor encryptor = AccessKeyEncryptor.getAccessKeyEncryptor("");
|
|
|
account.setEmailPassword(encryptor.decrypt(account.getEmailPassword()));
|