Commit 4be82047 by zhangxingmin

push

parent 237b5e3f
......@@ -95,6 +95,10 @@ public class EmailSendJobHandler {
// 遍历所有收件人,逐个发送邮件
for (EmailTaskRecipients recipient : recipients) {
try {
// 添加发送间隔,避免频率过高
if (successCount > 0) {
Thread.sleep(2000); // 2秒间隔
}
// 处理抄送人列表:将数据库中的逗号分隔字符串转换为List
List<String> ccEmailList = StringUtils.isNotBlank(recipient.getCcEmail()) ?
Arrays.asList(recipient.getCcEmail().split(";")) :
......
......@@ -123,6 +123,11 @@ public class ApiEmailSendServiceImpl implements ApiEmailSendService {
// 遍历所有收件人,逐个发送邮件
for (EmailTaskRecipients recipient : recipients) {
try {
// 添加发送间隔,避免频率过高
if (successCount > 0) {
Thread.sleep(2000); // 2秒间隔
}
// 处理抄送人列表:将数据库中的逗号分隔字符串转换为List
List<String> ccEmailList = StringUtils.isNotBlank(recipient.getCcEmail()) ?
Arrays.asList(recipient.getCcEmail().split(";")) :
......
......@@ -53,65 +53,88 @@ public class ApiEmailServiceImpl implements ApiEmailService {
+ JSON.toJSONString(dto.getCcEmailList())
+ ";" + dto.getSubject() + ";" + dto.getContent() );
// 创建邮件配置属性对象
// 添加邮件服务器配置
Properties props = new Properties();
// 设置SMTP需要身份验证
props.put("mail.smtp.auth", dto.getMailSmtpAuth());
// 启用TLS加密传输
props.put("mail.smtp.starttls.enable", dto.getStarttlsEnable());
// 设置邮件服务器主机名(发件人邮箱-SMTP服务器地址)
props.put("mail.smtp.host", dto.getSmtpHost());
log.info("mail.smtp.host:{}",dto.getSmtpHost());
//发件人邮箱(单个)
log.info("spring.mail.username:{}",dto.getSendEmail());
//发件人邮箱密码或授权码
log.info("spring.mail.password:{}",dto.getPassword());
// 设置邮件服务器端口号(587是TLS标准端口)
//发件人邮箱-SMTP服务器端口
props.put("mail.smtp.port", dto.getSmtpPort());
// 创建邮件会话对象,传入配置和认证器
// 添加连接超时和读写超时设置
props.put("mail.smtp.connectiontimeout", "10000"); // 10秒连接超时
props.put("mail.smtp.timeout", "30000"); // 30秒读写超时
props.put("mail.smtp.writetimeout", "30000"); // 30秒写超时
// 对于 TLS 连接,添加额外的安全配置
props.put("mail.smtp.ssl.trust", dto.getSmtpHost());
props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.3");
Session session = Session.getInstance(props, new Authenticator() {
// 重写获取密码认证的方法
protected PasswordAuthentication getPasswordAuthentication() {
// 返回用户名密码认证对象
return new PasswordAuthentication(dto.getSendEmail(), dto.getPassword());
}
});
// 使用try-catch块处理邮件发送异常
// 添加重试机制
int retryCount = 0;
int maxRetries = 2;
boolean sentSuccessfully = false;
while (retryCount <= maxRetries && !sentSuccessfully) {
try {
retryCount++;
log.info("尝试第 {} 次发送邮件", retryCount);
sendMailWithRetry(session, dto);
sentSuccessfully = true;
log.info("邮件发送成功: {} -> {}", dto.getSendEmail(), dto.getReceiveEmail());
} catch (AuthenticationFailedException e) {
log.error("第 {} 次认证失败: {}", retryCount, e.getMessage());
if (retryCount > maxRetries) {
throw new RuntimeException("邮件发送失败: 认证失败,请检查邮箱配置", e);
}
// 等待后重试
Thread.sleep(5000);
} catch (MessagingException e) {
log.error("第 {} 次发送失败: {}", retryCount, e.getMessage());
if (retryCount > maxRetries) {
throw new RuntimeException("邮件发送失败: " + e.getMessage(), e);
}
// 等待后重试
Thread.sleep(3000);
}
}
}
/**
* 发送邮件侏主要逻辑
* @param session
* @param dto
* @throws Exception
*/
private void sendMailWithRetry(Session session, ApiSendMailDto dto) throws Exception {
// 原有的邮件发送逻辑移到这里
try {
// 创建MIME类型邮件消息对象
Message message = new MimeMessage(session);
// 设置发件人地址
message.setFrom(new InternetAddress(dto.getSendEmail()));
// 设置收件人地址(支持多个收件人,用逗号分隔)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(dto.getReceiveEmail()));
// 判断是否有抄送人
if (!CollectionUtils.isEmpty(dto.getCcEmailList())) {
// 将抄送人列表转换为逗号分隔的字符串
String ccAddresses = String.join(",", dto.getCcEmailList());
// 设置抄送人地址
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccAddresses));
}
// 设置邮件主题
message.setSubject(dto.getSubject());
// 设置邮件发送时间(当前时间)
message.setSentDate(new Date());
// 创建邮件正文部分
MimeBodyPart messageBodyPart = new MimeBodyPart();
// 设置正文内容,指定HTML格式和UTF-8编码
messageBodyPart.setContent(dto.getContent(), "text/html;charset=utf-8");
// 创建多部分内容容器(用于组合正文和附件)
Multipart multipart = new MimeMultipart();
// 将正文部分添加到多部分容器中
multipart.addBodyPart(messageBodyPart);
// 修改附件处理部分:
// 多附件处理逻辑(您之前添加的)
if (StringUtils.isNotBlank(dto.getAttachmentPath())) {
String[] attachmentPaths = dto.getAttachmentPath().split(";");
for (String attachmentPath : attachmentPaths) {
......@@ -119,49 +142,149 @@ public class ApiEmailServiceImpl implements ApiEmailService {
if (StringUtils.isNotBlank(attachmentPath)) {
try {
MimeBodyPart attachmentPart = new MimeBodyPart();
DataSource source;
String fileName;
if (attachmentPath.startsWith("http://") || attachmentPath.startsWith("https://")) {
// 使用URLDataSource处理网络附件
URL url = new URL(attachmentPath);
source = new URLDataSource(url);
fileName = getFileNameFromUrl(attachmentPath);
} else {
// 处理本地文件附件
source = new FileDataSource(attachmentPath);
fileName = new File(attachmentPath).getName();
}
DataSource source = new FileDataSource(attachmentPath);
attachmentPart.setDataHandler(new DataHandler(source));
attachmentPart.setFileName(fileName);
attachmentPart.setFileName(new File(attachmentPath).getName());
multipart.addBodyPart(attachmentPart);
log.info("添加附件: {}", attachmentPath);
log.info("成功添加附件: {}", attachmentPath);
} catch (Exception e) {
log.error("添加附件失败: {}", attachmentPath, e);
throw new RuntimeException("添加附件失败: " + attachmentPath, e);
}
}
}
}
// 将多部分内容设置为邮件的完整内容
message.setContent(multipart);
// 发送邮件
Transport.send(message);
// 记录成功日志
log.info("邮件发送成功: {} -> {}", dto.getSendEmail(), dto.getReceiveEmail());
// log.info("发送邮件Transport.send(message) {}", JSON.toJSONString(message));
} catch (MessagingException e) {
// 记录失败日志,包含异常信息
log.error("邮件发送失败: {} -> {}", dto.getSendEmail(), dto.getReceiveEmail(), e);
// 抛出运行时异常
throw new RuntimeException("邮件发送失败: " + e.getMessage());
throw e;
}
}
// /**
// * 发送邮件
// * @param dto
// * @throws Exception
// */
// @Override
// public void sendMail(ApiSendMailDto dto) throws Exception {
// log.info("发送邮件的主要方法参数: {}: "
// + dto.getSendEmail() + ";"
// + dto.getReceiveEmail() + ";"
// + JSON.toJSONString(dto.getCcEmailList())
// + ";" + dto.getSubject() + ";" + dto.getContent() );
//
// // 创建邮件配置属性对象
// Properties props = new Properties();
// // 设置SMTP需要身份验证
// props.put("mail.smtp.auth", dto.getMailSmtpAuth());
// // 启用TLS加密传输
// props.put("mail.smtp.starttls.enable", dto.getStarttlsEnable());
// // 设置邮件服务器主机名(发件人邮箱-SMTP服务器地址)
// props.put("mail.smtp.host", dto.getSmtpHost());
// log.info("mail.smtp.host:{}",dto.getSmtpHost());
// //发件人邮箱(单个)
// log.info("spring.mail.username:{}",dto.getSendEmail());
// //发件人邮箱密码或授权码
// log.info("spring.mail.password:{}",dto.getPassword());
// // 设置邮件服务器端口号(587是TLS标准端口)
// //发件人邮箱-SMTP服务器端口
// props.put("mail.smtp.port", dto.getSmtpPort());
//
// // 创建邮件会话对象,传入配置和认证器
// Session session = Session.getInstance(props, new Authenticator() {
// // 重写获取密码认证的方法
// protected PasswordAuthentication getPasswordAuthentication() {
// // 返回用户名密码认证对象
// return new PasswordAuthentication(dto.getSendEmail(), dto.getPassword());
// }
// });
//
// // 使用try-catch块处理邮件发送异常
// try {
// // 创建MIME类型邮件消息对象
// Message message = new MimeMessage(session);
// // 设置发件人地址
// message.setFrom(new InternetAddress(dto.getSendEmail()));
// // 设置收件人地址(支持多个收件人,用逗号分隔)
// message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(dto.getReceiveEmail()));
//
// // 判断是否有抄送人
// if (!CollectionUtils.isEmpty(dto.getCcEmailList())) {
// // 将抄送人列表转换为逗号分隔的字符串
// String ccAddresses = String.join(",", dto.getCcEmailList());
// // 设置抄送人地址
// message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccAddresses));
// }
//
// // 设置邮件主题
// message.setSubject(dto.getSubject());
// // 设置邮件发送时间(当前时间)
// message.setSentDate(new Date());
//
// // 创建邮件正文部分
// MimeBodyPart messageBodyPart = new MimeBodyPart();
// // 设置正文内容,指定HTML格式和UTF-8编码
// messageBodyPart.setContent(dto.getContent(), "text/html;charset=utf-8");
//
// // 创建多部分内容容器(用于组合正文和附件)
// Multipart multipart = new MimeMultipart();
// // 将正文部分添加到多部分容器中
// multipart.addBodyPart(messageBodyPart);
//
// // 修改附件处理部分:
// if (StringUtils.isNotBlank(dto.getAttachmentPath())) {
// String[] attachmentPaths = dto.getAttachmentPath().split(";");
// for (String attachmentPath : attachmentPaths) {
// attachmentPath = attachmentPath.trim();
// if (StringUtils.isNotBlank(attachmentPath)) {
// try {
// MimeBodyPart attachmentPart = new MimeBodyPart();
// DataSource source;
// String fileName;
//
// if (attachmentPath.startsWith("http://") || attachmentPath.startsWith("https://")) {
// // 使用URLDataSource处理网络附件
// URL url = new URL(attachmentPath);
// source = new URLDataSource(url);
// fileName = getFileNameFromUrl(attachmentPath);
// } else {
// // 处理本地文件附件
// source = new FileDataSource(attachmentPath);
// fileName = new File(attachmentPath).getName();
// }
//
// attachmentPart.setDataHandler(new DataHandler(source));
// attachmentPart.setFileName(fileName);
// multipart.addBodyPart(attachmentPart);
// log.info("添加附件: {}", attachmentPath);
// } catch (Exception e) {
// log.error("添加附件失败: {}", attachmentPath, e);
// throw new RuntimeException("添加附件失败: " + attachmentPath, e);
// }
// }
// }
// }
//
// // 将多部分内容设置为邮件的完整内容
// message.setContent(multipart);
//
// // 发送邮件
// Transport.send(message);
// // 记录成功日志
// log.info("邮件发送成功: {} -> {}", dto.getSendEmail(), dto.getReceiveEmail());
//// log.info("发送邮件Transport.send(message) {}", JSON.toJSONString(message));
//
// } catch (MessagingException e) {
// // 记录失败日志,包含异常信息
// log.error("邮件发送失败: {} -> {}", dto.getSendEmail(), dto.getReceiveEmail(), e);
// // 抛出运行时异常
// throw new RuntimeException("邮件发送失败: " + e.getMessage());
// }
// }
// 辅助方法:从URL中提取文件名
private String getFileNameFromUrl(String url) {
try {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment