TASK: 发送邮件功能及发送失败后的重试机制

This commit is contained in:
2025-07-31 15:57:47 +08:00
parent 7edc959432
commit 739e637267
12 changed files with 5131 additions and 4826 deletions

View File

@@ -0,0 +1,96 @@
package com.ai.da.common.RabbitMQ;
import com.ai.da.common.utils.MailUtil;
import com.ai.da.model.dto.BasicEmailParamDTO;
import com.ai.da.service.EmailService;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.core.exception.RetryableException;
import org.springframework.amqp.core.Message;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
public class EmailRetryConsumer {
@Resource
private MailUtil mailUtil;
@Resource
private MQPublisher mqPublisher;
@Resource
private EmailService emailService;
// @RabbitListener(queues = "#{rabbitMQProperties.deadLetter.queue}")
public void handleRetry(Map<String, String> mailParams, Message message, Channel channel) throws IOException {
long tag = message.getMessageProperties().getDeliveryTag();
try {
log.info("死信队列收到消息:{}", message);
// 处理邮件发送参数
BasicEmailParamDTO basicEmailParamDTO = JSONObject.parseObject(mailParams.get("dto"), BasicEmailParamDTO.class);
String fileName = mailParams.get("filename");
InputStreamSource inputStreamSource = Objects.isNull(mailParams.get("source")) ?
null : JSONObject.parseObject(mailParams.get("source"), InputStreamSource.class);
JSONObject templateParams = JSONObject.parseObject(mailParams.get("templateParams"), JSONObject.class);
String templateName = mailParams.get("templatePath");
long logId = Long.parseLong(mailParams.get("logId"));
basicEmailParamDTO.setContent(mailUtil.setContent(templateParams, templateName));
// 发邮件
int lastReturnCode = mailUtil.sendMail(basicEmailParamDTO, fileName, inputStreamSource);
if (lastReturnCode == 250) {
log.info("邮件发送成功Subject : {}", basicEmailParamDTO.getSubject());
emailService.updateStatus(logId, EmailService.DELIVERED);
} else if (lastReturnCode == 450) {
log.info("目标邮箱 {} 暂时不可用,请稍后重试", (Object) basicEmailParamDTO.getMailTo());
// 重试
retry(mailParams, message, channel, tag, logId);
} else if (lastReturnCode == 550) {
log.info("目标邮箱 {} 不可用,邮件发送失败", (Object) basicEmailParamDTO.getMailTo());
emailService.updateStatus(logId, EmailService.FAILED);
} else {
log.info("邮件发送失败Subject : {}, 状态码: {}", basicEmailParamDTO.getSubject(), lastReturnCode);
retry(mailParams, message, channel, tag, logId);
emailService.updateStatus(logId, EmailService.FAILED);
}
channel.basicAck(tag, false);
} catch (RetryableException e) {
log.info("邮件重试发生异常:RetryableException -> {}", e.getMessage());
channel.basicAck(tag, false); // 确认原消息
} catch (Exception e) {
log.info("邮件重试发生异常:Exception -> {}", e.getMessage());
channel.basicAck(tag, false); // 确认原消息
}
}
private int getRetryAttempt(Message message) {
Integer attempt = message.getMessageProperties()
.getHeader("x-retry-attempt");
return attempt != null ? attempt : 1;
}
private void retry(Map<String, String> mailParams, Message message, Channel channel, long tag, long logId) throws IOException{
int attempt = getRetryAttempt(message);
if (attempt >= 3) { // 最大重试次数
channel.basicReject(tag, false);
emailService.updateStatus(logId, EmailService.FAILED);
log.error("重试结束,邮件最终发送失败: {}", mailParams);
} else {
log.info("重新将邮件信息发送到重试队列");
mqPublisher.sendEmailMsg(mailParams, attempt);
channel.basicAck(tag, false); // 确认原消息
// 更新数据库
emailService.updateRetryCount(logId, attempt + 1);
}
}
}

View File

@@ -1,43 +1,82 @@
package com.ai.da.common.RabbitMQ;
import org.springframework.amqp.core.Queue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MQConfig {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Bean
public Queue generateQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerate());
}
@Bean
public Queue SRQueue() {
return new Queue(rabbitMQProperties.getQueues().getSr());
}
@Bean
public Queue SRResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getSrResult());
}
@Bean
public Queue generateResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerateResult());
}
@Bean
public Queue toProductImageResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getToProductImageResult());
}
@Bean
public Queue relightResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getRelightResult());
}
}
package com.ai.da.common.RabbitMQ;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MQConfig {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Bean
public Queue generateQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerate());
}
@Bean
public Queue SRQueue() {
return new Queue(rabbitMQProperties.getQueues().getSr());
}
@Bean
public Queue SRResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getSrResult());
}
@Bean
public Queue generateResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getGenerateResult());
}
@Bean
public Queue toProductImageResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getToProductImageResult());
}
@Bean
public Queue relightResultQueue() {
return new Queue(rabbitMQProperties.getQueues().getRelightResult());
}
@Bean
public Queue poseTransformQueue() {
return new Queue(rabbitMQProperties.getQueues().getPoseTransform());
}
@Bean
public Queue mailRetryQueue() {
// 普通队列不绑定DLX首次失败后才进入MQ
// durable 持久化队列
return QueueBuilder.durable(rabbitMQProperties.getQueues().getEmailRetry())
// 关键参数:绑定死信交换机
.withArgument("x-dead-letter-exchange", rabbitMQProperties.getDeadLetter().getExchange())
// 可选:指定死信路由键(默认使用原消息的路由键)
.withArgument("x-dead-letter-routing-key", rabbitMQProperties.getDeadLetter().getRoutingKey())
.build();
}
// 新增死信交换机
@Bean
public DirectExchange deadLetterExchange() {
return new DirectExchange(rabbitMQProperties.getDeadLetter().getExchange());
}
// 新增死信队列
@Bean
public Queue deadLetterQueue() {
return QueueBuilder.durable(rabbitMQProperties.getDeadLetter().getQueue()).build();
}
// 绑定死信队列
@Bean
public Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue())
.to(deadLetterExchange())
.with(rabbitMQProperties.getDeadLetter().getRoutingKey());
}
}

View File

@@ -1,29 +1,56 @@
package com.ai.da.common.RabbitMQ;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Component
public class MQPublisher {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Autowired
private AmqpTemplate amqpTemplate;
public void sendGenerateMessage(String mm) {
log.info("send message: " + mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getGenerate(), mm);
}
public void sendSRMessage(String mm) {
log.info("send message: " + mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm);
}
}
package com.ai.da.common.RabbitMQ;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Map;
@Slf4j
@Component
public class MQPublisher {
@Autowired
private RabbitMQProperties rabbitMQProperties;
@Autowired
private AmqpTemplate amqpTemplate;
public void sendGenerateMessage(String mm) {
log.info("send generate message: {}", mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getGenerate(), mm);
}
public void sendSRMessage(String mm) {
log.info("send message: {}", mm);
amqpTemplate.convertAndSend(rabbitMQProperties.getQueues().getSr(), mm);
}
/**
*
* @param mailParams 含有的字段
* {"dto": basicEmailParamDTO, "filename": fileName, "source": inputStreamSource,
* "templateParams": jsonObject, "templatePath": path}
* 邮件发送参数,附件文件名,附件数据
* @param retryTimes 重试次数初始为0
*/
public void sendEmailMsg(Map<String, String> mailParams, int retryTimes){
log.info("send email MQ message: {} ", mailParams);
// // 重新入队(指数退避) 时间单位:毫秒
long newDelay = (long) (5000 * Math.pow(2, retryTimes + 1));
log.info("send email MQ delay: {} ms, retry attempt: {}", newDelay, retryTimes + 1);
amqpTemplate.convertAndSend(
rabbitMQProperties.getQueues().getEmailRetry(),
mailParams,
m -> {
m.getMessageProperties().setExpiration(String.valueOf(newDelay));
m.getMessageProperties().setHeader("x-retry-attempt", retryTimes + 1);
return m;
}
);
}
}

View File

@@ -1,35 +1,45 @@
package com.ai.da.common.RabbitMQ;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "rabbitmq")
@Data
public class RabbitMQProperties {
private Queues queues;
private Exchange exchange;
@Data
public static class Queues {
private String generate;
private String sr;
private String srResult;
private String generateResult;
private String toProductImageResult;
private String relightResult;
private String poseTransform;
private String designBatch;
private String relightBatch;
private String toProductImageBatch;
private String poseTransformBatch;
}
@Data
public static class Exchange {
private String generate;
}
}
package com.ai.da.common.RabbitMQ;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "rabbitmq")
@Data
public class RabbitMQProperties {
private Queues queues;
private Exchange exchange;
private DeadLetter deadLetter; // 新增死信配置
@Data
public static class Queues {
private String generate;
private String sr;
private String srResult;
private String generateResult;
private String toProductImageResult;
private String relightResult;
private String poseTransform;
private String emailRetry;
private String designBatch;
private String relightBatch;
private String toProductImageBatch;
private String poseTransformBatch;
}
@Data
public static class Exchange {
private String generate;
}
// 新增死信配置内部类
@Data
public static class DeadLetter {
private String exchange;
private String queue;
private String routingKey;
}
}

View File

@@ -1,168 +1,176 @@
package com.ai.da.common.utils;
import com.ai.da.model.dto.BasicEmailParamDTO;
import com.alibaba.fastjson.JSONObject;
import com.sun.mail.smtp.SMTPTransport;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.*;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
public class MailUtil {
@Resource
private JavaMailSender javaMailSender;
@Resource
private TemplateEngine templateEngine;
/**
* 发送邮件 - 默认发件人
*
* @param basicEmailParamDTO 发送邮件所需参数
* @param inputStreamSource 附件(如果有)
*/
public int sendMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
MimeMessage mimeMessage = createSimpleMail(basicEmailParamDTO, fileName, inputStreamSource);
// 提取配置
String host;
String username;
String password;
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
host = ((JavaMailSenderImpl) javaMailSender).getHost();
} else {
host = basicEmailParamDTO.getServiceAddress();
}
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getSenderUser())) {
username = ((JavaMailSenderImpl) javaMailSender).getUsername();
} else {
username = basicEmailParamDTO.getSenderUser();
}
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
password = ((JavaMailSenderImpl) javaMailSender).getPassword();
} else {
password = basicEmailParamDTO.getPassword();
}
return sendMail(mimeMessage, host, username, password);
}
private int sendMail(MimeMessage mimeMessage, String host, String username, String password) throws MessagingException {
SMTPTransport transport = null;
try {
// 获取 SMTPTransport
transport = (SMTPTransport) mimeMessage.getSession().getTransport("smtp");
// 连接到 SMTP 服务器
transport.connect(host, username, password);
// 发送邮件
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
// 获取 SMTP 服务器的响应
String lastServerResponse = transport.getLastServerResponse();
int lastReturnCode = transport.getLastReturnCode();
log.info("SMTP 状态码: {}, SMTP 服务器响应: {}", lastReturnCode, lastServerResponse);
return lastReturnCode;
} catch (MailException | MessagingException e) {
// 记录日志或执行其他补偿逻辑
log.info("邮件发送失败:{}", e.getMessage());
} finally {
// 关闭连接
assert transport != null;
transport.close();
}
return 0;
}
/**
* 创建一封邮件
*
* @param basicEmailParamDTO 创建邮件需要的参数
* @param inputStreamSource 附件(如果有)
* @return 一封邮件
*/
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
// 创建邮件对象
MimeMessage message = javaMailSender.createMimeMessage();
// 使用 MimeMessageHelper 简化邮件内容和附件的设置
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
// 设置发件人
mimeMessageHelper.setFrom(new InternetAddress(basicEmailParamDTO.getSenderUserMail()));
// 设置收件人
mimeMessageHelper.setTo(basicEmailParamDTO.getMailTo());
// 设置抄送人
if (basicEmailParamDTO.getCc() != null && basicEmailParamDTO.getCc().length > 0) {
mimeMessageHelper.setCc(basicEmailParamDTO.getCc());
}
// 设置暗送人
if (basicEmailParamDTO.getBcc() != null && basicEmailParamDTO.getBcc().length > 0) {
mimeMessageHelper.setBcc(basicEmailParamDTO.getBcc());
}
// 设置邮件主题
mimeMessageHelper.setSubject(basicEmailParamDTO.getSubject());
// 设置邮件内容HTML 格式)
mimeMessageHelper.setText(basicEmailParamDTO.getContent(), true);
// 设置附件
if (inputStreamSource != null) {
mimeMessageHelper.addAttachment(fileName, inputStreamSource);
}
return message;
}
/**
* 设置实体参数
*
* @param mailTo 接收邮件的邮箱地址
* @param jsonObject 模板中变量的值
* @return 返回一个MailEntity
* @throws AddressException 邮箱地址值异常
*/
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, JSONObject jsonObject, String templatePath, String title) throws AddressException {
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
basicEmailParamDTO.setSubject(title);
// todo 邮件模板不存在的报错与重试机制
basicEmailParamDTO.setContent(setContent(jsonObject, templatePath));
return basicEmailParamDTO;
}
/**
* 将地址转换为InternetAddress类型
*
* @param addressList 普通的地址字符串列表
* @return InternetAddress类型的地址列表
* @throws AddressException 地址异常
*/
public InternetAddress[] getInternetAddressList(List<String> addressList) throws AddressException {
InternetAddress[] toAddress = new InternetAddress[addressList.size()];
for (String address : addressList) {
toAddress[addressList.indexOf(address)] = new InternetAddress(address);
}
return toAddress;
}
public String setContent(JSONObject jsonObject, String templatePath) {
Context context = new Context();
if (Objects.nonNull(jsonObject)) {
for (String key : jsonObject.keySet()) {
context.setVariable(key, jsonObject.get(key));
}
}
return templateEngine.process(templatePath, context);
}
}
package com.ai.da.common.utils;
import com.ai.da.model.dto.BasicEmailParamDTO;
import com.alibaba.fastjson.JSONObject;
import com.sun.mail.smtp.SMTPTransport;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.*;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
public class MailUtil {
@Resource
private JavaMailSender javaMailSender;
@Resource
private TemplateEngine templateEngine;
/**
* 发送邮件 - 默认发件人
*
* @param basicEmailParamDTO 发送邮件所需参数
* @param inputStreamSource 附件(如果有)
*/
public int sendMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
MimeMessage mimeMessage = createSimpleMail(basicEmailParamDTO, fileName, inputStreamSource);
// 提取配置
String host;
String username;
String password;
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
host = ((JavaMailSenderImpl) javaMailSender).getHost();
} else {
host = basicEmailParamDTO.getServiceAddress();
}
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getSenderUser())) {
username = ((JavaMailSenderImpl) javaMailSender).getUsername();
} else {
username = basicEmailParamDTO.getSenderUser();
}
if (StringUtil.isNullOrEmpty(basicEmailParamDTO.getServiceAddress())) {
password = ((JavaMailSenderImpl) javaMailSender).getPassword();
} else {
password = basicEmailParamDTO.getPassword();
}
return sendMail(mimeMessage, host, username, password);
}
private int sendMail(MimeMessage mimeMessage, String host, String username, String password) throws MessagingException {
SMTPTransport transport = null;
try {
// 获取 SMTPTransport
transport = (SMTPTransport) mimeMessage.getSession().getTransport("smtp");
// 连接到 SMTP 服务器
transport.connect(host, username, password);
// 发送邮件
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
// 获取 SMTP 服务器的响应
String lastServerResponse = transport.getLastServerResponse();
int lastReturnCode = transport.getLastReturnCode();
log.info("SMTP 状态码: {}, SMTP 服务器响应: {}", lastReturnCode, lastServerResponse);
return lastReturnCode;
} catch (MailException | MessagingException e) {
// 记录日志或执行其他补偿逻辑
log.info("邮件发送失败:{}", e.getMessage());
} finally {
// 关闭连接
assert transport != null;
transport.close();
}
return 0;
}
/**
* 创建一封邮件
*
* @param basicEmailParamDTO 创建邮件需要的参数
* @param inputStreamSource 附件(如果有)
* @return 一封邮件
*/
private MimeMessage createSimpleMail(BasicEmailParamDTO basicEmailParamDTO, String fileName, InputStreamSource inputStreamSource) throws MessagingException {
// 创建邮件对象
MimeMessage message = javaMailSender.createMimeMessage();
// 使用 MimeMessageHelper 简化邮件内容和附件的设置
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
// 设置发件人
mimeMessageHelper.setFrom(new InternetAddress(basicEmailParamDTO.getSenderUserMail()));
// 设置收件人
mimeMessageHelper.setTo(basicEmailParamDTO.getMailTo());
// 设置抄送人
if (basicEmailParamDTO.getCc() != null && basicEmailParamDTO.getCc().length > 0) {
mimeMessageHelper.setCc(basicEmailParamDTO.getCc());
}
// 设置暗送人
if (basicEmailParamDTO.getBcc() != null && basicEmailParamDTO.getBcc().length > 0) {
mimeMessageHelper.setBcc(basicEmailParamDTO.getBcc());
}
// 设置邮件主题
mimeMessageHelper.setSubject(basicEmailParamDTO.getSubject());
// 设置邮件内容HTML 格式)
mimeMessageHelper.setText(basicEmailParamDTO.getContent(), true);
// 设置附件
if (inputStreamSource != null) {
mimeMessageHelper.addAttachment(fileName, inputStreamSource);
}
return message;
}
/**
* 设置实体参数
*
* @param mailTo 接收邮件的邮箱地址
* @param jsonObject 模板中变量的值
* @return 返回一个MailEntity
* @throws AddressException 邮箱地址值异常
*/
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, JSONObject jsonObject, String templatePath, String title) throws AddressException {
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
basicEmailParamDTO.setSubject(title);
// todo 邮件模板不存在的报错与重试机制
basicEmailParamDTO.setContent(setContent(jsonObject, templatePath));
return basicEmailParamDTO;
}
public BasicEmailParamDTO setBasicEmailParams(List<String> mailTo, String title) throws AddressException {
BasicEmailParamDTO basicEmailParamDTO = new BasicEmailParamDTO();
basicEmailParamDTO.setSenderUserMail("info@aida.com.hk");
basicEmailParamDTO.setMailTo(getInternetAddressList(mailTo));
basicEmailParamDTO.setSubject(title);
return basicEmailParamDTO;
}
/**
* 将地址转换为InternetAddress类型
*
* @param addressList 普通的地址字符串列表
* @return InternetAddress类型的地址列表
* @throws AddressException 地址异常
*/
public InternetAddress[] getInternetAddressList(List<String> addressList) throws AddressException {
InternetAddress[] toAddress = new InternetAddress[addressList.size()];
for (String address : addressList) {
toAddress[addressList.indexOf(address)] = new InternetAddress(address);
}
return toAddress;
}
public String setContent(JSONObject jsonObject, String templatePath) {
Context context = new Context();
if (Objects.nonNull(jsonObject)) {
for (String key : jsonObject.keySet()) {
context.setVariable(key, jsonObject.get(key));
}
}
return templateEngine.process(templatePath, context);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -426,45 +426,7 @@ public class SendEmailUtil {
}
}
private final static Long GENERATE_EXCEPTION_WARNING_ID = 122589L;
public static void sendGenerateExceptionWarning(String message) {
try {
// 实例化一个认证对象
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("ses.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
SendEmailRequest req = new SendEmailRequest();
req.setFromEmailAddress(CODE_CREATE_SEND_ADDRESS);
req.setDestination(new String[]{"xupei3360@163.com"});
// 根据邮件类型设置不同的主题和模板
String subject = "";
Template template = new Template();
subject = "Warning: AiDA 3.0 Generate Exception Warning";
template.setTemplateID(GENERATE_EXCEPTION_WARNING_ID);
JSONObject parameter = new JSONObject();
parameter.put("errorMessage", message);
parameter.put("time", DateUtil.dateToStr(new Date(), DateUtil.YYYY_MM_DD_HH_MM_SS));
template.setTemplateData(parameter.toJSONString());
req.setSubject(subject);
req.setTemplate(template);
// 发送邮件
SendEmailResponse resp = client.SendEmail(req);
log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
log.info("邮件发送失败###{}", e.toString());
throw new BusinessException("failed.to.send.mail");
}
}
// todo ?需要保留吗
private final static Long QUESTIONNAIRE_FEEDBACK_EN_ID = 124151L;
private final static Long QUESTIONNAIRE_FEEDBACK_CN_ID = 124156L;
@@ -606,6 +568,7 @@ public class SendEmailUtil {
}
}
// todo 目前该定时器已取消,是否需要保留该模板?
private final static Long NEW_USER_REGISTER_NOTIFICATION_EN = 126919L;
public static void notificationForRegisterUser(String receiverAddress) {
@@ -644,51 +607,6 @@ public class SendEmailUtil {
}
}
private final static Long CHANGE_MAILBOX_CONFIRM_CN = 128278L;
private final static Long CHANGE_MAILBOX_CONFIRM_EN = 128277L;
public static void changeMailboxConfirm(String receiverAddress, String language, String name, String link) {
try {
// 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey此处还需注意密钥对的保密
// 代码泄露可能会导致 SecretId 和 SecretKey 泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议采用更安全的方式来使用密钥请参见https://cloud.tencent.com/document/product/1278/85305
// 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
// 实例化一个http选项可选的没有特殊需求可以跳过
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("ses.tencentcloudapi.com");
// 实例化一个client选项可选的没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
SendEmailRequest req = new SendEmailRequest();
req.setFromEmailAddress(SEND_ADDRESS);
req.setDestination(new String[]{receiverAddress});
Template template = new Template();
if (language.equals("ENGLISH")) {
req.setSubject("Change the email address bound to the AiDA account");
template.setTemplateID(CHANGE_MAILBOX_CONFIRM_EN);
} else {
req.setSubject("更换AiDA账号绑定的邮箱地址");
template.setTemplateID(CHANGE_MAILBOX_CONFIRM_CN);
}
JSONObject param = new JSONObject();
param.put("userName", name);
param.put("link", link);
template.setTemplateData(param.toJSONString());
req.setTemplate(template);
// 返回的resp是一个SendEmailResponse的实例与请求对象对应
SendEmailResponse resp = client.SendEmail(req);
log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
log.info("邮件发送失败###{}", e.toString());
throw new BusinessException("failed.to.send.mail");
}
}
private final static Long UPLOAD_TIMEOUT_REMINDER = 128324L;
public static void uploadTimeoutReminder(String userName, String time) {
@@ -732,7 +650,7 @@ public class SendEmailUtil {
}
}
private final static Long HALFPRICEPROMOTION_CN_ID = 128582L;
/*private final static Long HALFPRICEPROMOTION_CN_ID = 128582L;
private final static Long HALFPRICEPROMOTION_EN_ID = 128583L;
public static void halfPricePromotion(Account account, String senderAddress, int type) {
@@ -821,7 +739,7 @@ public class SendEmailUtil {
log.info("邮件发送失败###{}", e.toString());
throw new BusinessException("failed.to.send.mail");
}
}
}*/
private final static Long CANCEL_MERCHANT_EN = 130720L;
// private final static Long NEW_MERCHANT_EN = 130721L;
@@ -1074,4 +992,52 @@ public class SendEmailUtil {
}
}
private final static Long CN_2025_618 = 141425L;
private final static Long EN_2025_618 = 141424L;
public static void send618PromotionEmailTemp(String receiver, String language){
try {
// 实例化一个认证对象
Credential cred = new Credential(SECRET_ID, SECRET_KEy);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("ses.tencentcloudapi.com");
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
SesClient client = new SesClient(cred, "ap-hongkong", clientProfile);
SendEmailRequest req = new SendEmailRequest();
req.setFromEmailAddress(CODE_CREATE_SEND_ADDRESS);
req.setDestination(new String[]{receiver});
// 根据邮件类型设置不同的主题和模板
String subject = "";
Template template = new Template();
// if (type == 1) {
// subject = "Upcoming System Upgrade for AiDA 3.0";
// template.setTemplateID(UPGRADE_NOTIFICATION_ID);
// }else {
// subject = "即将到来的AiDA 3.0系统升级";
// template.setTemplateID(UPGRADE_NOTIFICATION_ID_CHINESE);
// }
if (language.equals("ENGLISH")) {
subject = "Welcome back Subscribe AiDA with the discount code to enjoy 50% OFF!";
template.setTemplateID(EN_2025_618);
}else {
subject = "设计时速狂飙AiDA 618半价让灵感永不限流";
template.setTemplateID(CN_2025_618);
}
req.setSubject(subject);
req.setTemplate(template);
// 发送邮件
SendEmailResponse resp = client.SendEmail(req);
log.info("邮件发送成功,收件人地址:{}", receiver);
log.info("短信发送结果res###{}", SendEmailResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
log.info(receiver);
log.error("邮件发送失败###{},收件人地址:{}", e.toString(), receiver);
}
}
}