邮件发送

This commit is contained in:
lvleigang 2025-08-01 16:31:42 +08:00
parent 30704ab9bb
commit a3233f3a10
7 changed files with 217 additions and 1234 deletions

View File

@ -131,22 +131,22 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
return BaseResult.getFailureMessageEntity("获取OA token失败");
}
for (int i = 0; i < files.size(); i++) {
String encodedFileName = URLEncoder.encode(files.get(i).getFilename(), StandardCharsets.UTF_8.name());
String pdfUrl = "http://oa.sptzj.cn/seeyon/rest/attachment/file/"+files.get(i).getId()+"?fileName="+encodedFileName+"&token="+token;
logger.error("附件的url"+pdfUrl);
File file = getFile(pdfUrl,files.get(i).getFilename());
if(file != null){
try {
for (SendEmailEntity sendEmailEntity : files) {
String encodedFileName = URLEncoder.encode(sendEmailEntity.getFilename(), StandardCharsets.UTF_8.name());
String pdfUrl = "http://oa.sptzj.cn/seeyon/rest/attachment/file/" + sendEmailEntity.getId() + "?fileName=" + encodedFileName + "&token=" + token;
logger.error("附件的url" + pdfUrl);
File file = getFile(pdfUrl, sendEmailEntity.getFilename());
if (file != null) {
try {
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile(
MultipartFile multipartFile = new MockMultipartFile(
file.getName(), // 对应表单中的文件字段名
file.getName(), // 原始文件名
files.get(i).getContentType(), // 或根据文件类型指定 MIME 类型
sendEmailEntity.getContentType(), // 或根据文件类型指定 MIME 类型
input
);
attachments.add(multipartFile);
}catch (Exception e){
} catch (Exception e) {
return BaseResult.getFailureMessageEntity("发送邮件失败");
}
}
@ -154,12 +154,16 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
}
if(attachments != null && attachments.size() > 0){
emailUtil.sendHtmlAndFileMessage(sendEmail,subject, htmls,attachments);
emailUtil.sendHtmlAndFileMessage("1",sendEmail,subject, htmls,attachments);
emailUtil.sendHtmlAndFileMessage("2",sendEmail,subject, htmls,attachments);
}else {
emailUtil.sendHtmlMessage(sendEmail,subject, htmls);
emailUtil.sendHtmlMessage("1",sendEmail,subject, htmls);
emailUtil.sendHtmlMessage("2",sendEmail,subject, htmls);
}
return BaseResult.getSuccessMessageEntity("发送邮件成功");
}catch (Exception e){
logger.error(e.getMessage());
e.printStackTrace();
return BaseResult.getFailureMessageEntity("发送邮件失败");
}
}
@ -228,7 +232,7 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
**/
private String getSendData(JSONObject mainData, JSONArray detailArray) throws ParseException {
StringBuffer sb = new StringBuffer();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 拼接主容器div
sb.append("<div style=\"max-width: 1100px; margin: 0 auto; background-color: #fff; padding: 35px; box-shadow: 0 2px 10px rgba(0,0,0,0.08); border-radius: 6px;\">");
@ -237,12 +241,16 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
sb.append(" <h2 style=\"font-size: 26px; color: #2c3e50; letter-spacing: 2px; margin: 0; font-family: 'Microsoft YaHei', 'SimSun', sans-serif;\">"+mainData.getOrDefault("field0016","")+"采购单</h2>");
sb.append(" </div>");
sb.append("");
String field0004str = "";
if(mainData.getString("field0004") != null){
Date field0004 = new Date(mainData.getLong("field0004"));
field0004str = sdf.format(field0004);
}
// 拼接基础信息区域
sb.append(" <div style=\"display: flex; margin-bottom: 18px; line-height: 1.6; font-family: 'Microsoft YaHei', 'SimSun', sans-serif;\">");
sb.append(" <div style=\"flex: 1; display: flex;\">");
sb.append(" <span style=\"font-weight: 600; color: #34495e; min-width: 110px;\">申请日期:</span>");
sb.append(" <span style=\"color: #2c3e50; padding-left: 8px; border-bottom: 1px dashed #d1d1d1; flex: 1;\">"+mainData.getOrDefault("field0004","")+"</span>");
sb.append(" <span style=\"color: #2c3e50; padding-left: 8px; border-bottom: 1px dashed #d1d1d1; flex: 1;\">"+field0004str+"</span>");
sb.append(" </div>");
sb.append(" <div style=\"flex: 1; display: flex;\">");
sb.append(" <span style=\"font-weight: 600; color: #34495e; min-width: 110px;\">单据编号:</span>");
@ -332,19 +340,24 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
if (detailArray != null && detailArray.size() > 0) {
for (int i = 0; i < detailArray.size(); i++) {
sb.append(" <tr style=\"background-color: #f9f9f9;\">");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0005","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0006","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0007","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0008","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0009","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0010","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0011","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0012","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0013","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0014","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0017","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0018","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+mainData.getOrDefault("field0019","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0005","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0006","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0007","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0008","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0009","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0010","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0011","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0012","")+"</td>");
String field0013str = "";
if(detailArray.getJSONObject(i).getString("field0013") != null){
Date field0013 = new Date(detailArray.getJSONObject(i).getLong("field0013"));
field0013str = sdf.format(field0013);
}
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+field0013str+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0014","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0017","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0018","")+"</td>");
sb.append(" <td style=\"padding: 12px 8px; text-align: center; border: 1px solid #ddd; font-size: 14px; color: #2c3e50;\">"+detailArray.getJSONObject(i).getOrDefault("field0019","")+"</td>");
sb.append(" </tr>");
}
}else {
@ -372,11 +385,6 @@ public class SendEmailServiceImpl extends BaseService<SendEmailEntity, String> i
// 闭合主容器div
sb.append("</div>");
if (detailArray != null && detailArray.size() > 0) {
for (int i = 0; i < detailArray.size(); i++) {
}
}
return sb.toString();
}

View File

@ -9,18 +9,28 @@ logging:
path: /Users/apple/Desktop/log/local
spring:
mail:
host: smtp.qq.com
port: 465
username: 957075182@qq.com
password: lcmgbgaxuhsbbbei
first:
host: smtp.sptchina.cn
port: 25
username: mro@sptchina.cn
password: VeaQDO9zjuYpGc1i
second:
host: smtp.qq.com
port: 587
username: 957075182@qq.com
password: lcmgbgaxuhsbbbei
default-encoding: UTF-8
properties:
mail:
mime:
charset: UTF-8
smtp:
socketFactory:
class: javax.net.ssl.SSLSocketFactory
auth: true
ssl:
enable: true
protocol: TLSv1.2
data:
mongodb:
# host: 192.168.2.237

View File

@ -8,6 +8,23 @@ logging:
# 日志保存路径
path: D:\yongansystem\log\zs
spring:
mail:
host: smtp.qq.com
port: 587
username: 957075182@qq.com
password: lcmgbgaxuhsbbbei
default-encoding: UTF-8
properties:
mail:
mime:
charset: UTF-8
smtp:
socketFactory:
class: javax.net.ssl.SSLSocketFactory
auth: true
ssl:
enable: true
protocol: TLSv1.2
data:
mongodb:
# host: 192.168.2.237

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
package com.hzya.frame.email;
import com.hzya.frame.web.exception.BaseSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
@ -24,21 +26,50 @@ import java.util.List;
*/
@Service
public class EmailUtil {
@Value("${spring.mail.username}")
private String sendEmail ;
@Resource
private JavaMailSender mailSender;
@Value("${spring.mail.first.username}")
private String firstSendEmail ;
@Value("${spring.mail.second.username}")
private String secondSendEmail ;
// 注入第一个邮箱发送器
@Autowired
@Qualifier("firstMailSender")
private JavaMailSender firstMailSender;
public void sendHtmlMessage(String to, String subject, String htmlContent) throws MessagingException {
// 注入第二个邮箱发送器
@Autowired
@Qualifier("secondMailSender")
private JavaMailSender secondMailSender;
public void sendHtmlMessage(String type,String to, String subject, String htmlContent) throws MessagingException {
if("1".equals(type)){
sendHtmlMessage( firstMailSender,firstSendEmail, to, subject, htmlContent);
}else if("2".equals(type)){
sendHtmlMessage( secondMailSender,secondSendEmail, to, subject, htmlContent);
}else {
throw new BaseSystemException("邮件类型错误");
}
}
public void sendHtmlAndFileMessage(String type,String to, String subject, String htmlContent, List<MultipartFile> attachments) throws MessagingException, UnsupportedEncodingException {
if("1".equals(type)){
sendHtmlAndFileMessage( firstMailSender,firstSendEmail, to, subject, htmlContent,attachments);
}else if("2".equals(type)){
sendHtmlAndFileMessage( secondMailSender,secondSendEmail, to, subject, htmlContent,attachments);
}else {
throw new BaseSystemException("邮件类型错误");
}
}
private void sendHtmlMessage(JavaMailSender mailSender,String sendEmail,String to, String subject, String htmlContent) throws MessagingException {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
MimeMessageHelper helper = new MimeMessageHelper(message, true,StandardCharsets.UTF_8.name());
helper.setFrom(sendEmail);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(htmlContent, true); // 第二个参数设为true表示启用HTML格式
mailSender.send(message);
}
public void sendHtmlAndFileMessage(String to, String subject, String htmlContent, List<MultipartFile> attachments) throws MessagingException, UnsupportedEncodingException {
private void sendHtmlAndFileMessage(JavaMailSender mailSender,String sendEmail,String to, String subject, String htmlContent, List<MultipartFile> attachments) throws MessagingException, UnsupportedEncodingException {
MimeMessage message = mailSender.createMimeMessage();
// 使用MimeMessageHelper的构造函数设置multipart模式为true并指定编码
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name());
@ -60,7 +91,7 @@ public class EmailUtil {
mailSender.send(message);
}
public void sendSimpleMessage(String to, String subject, String text) {
private void sendSimpleMessage(JavaMailSender mailSender,String sendEmail, String to, String subject, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(sendEmail);
message.setTo(to);

View File

@ -0,0 +1,96 @@
package com.hzya.frame.email;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import javax.net.ssl.*;
import java.security.cert.X509Certificate;
import java.util.Properties;
@Configuration
public class MultiMailSenderConfig {
// 第一个邮箱参数
@Value("${spring.mail.first.host}")
private String firstHost;
@Value("${spring.mail.first.port}")
private int firstPort;
@Value("${spring.mail.first.username}")
private String firstUsername;
@Value("${spring.mail.first.password}")
private String firstPassword;
// 第二个邮箱参数
@Value("${spring.mail.second.host}")
private String secondHost;
@Value("${spring.mail.second.port}")
private int secondPort;
@Value("${spring.mail.second.username}")
private String secondUsername;
@Value("${spring.mail.second.password}")
private String secondPassword;
// 第一个邮箱发送器跳过SSL认证
@Bean(name = "firstMailSender")
public JavaMailSender firstMailSender() throws Exception {
return createMailSender(firstHost, firstPort, firstUsername, firstPassword);
}
// 第二个邮箱发送器跳过SSL认证
@Bean(name = "secondMailSender")
public JavaMailSender secondMailSender() throws Exception {
return createMailSender(secondHost, secondPort, secondUsername, secondPassword);
}
// 通用创建方法配置邮箱信息并禁用SSL验证
private JavaMailSender createMailSender(String host, int port, String username, String password) throws Exception {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(host);
mailSender.setPort(port);
mailSender.setUsername(username);
mailSender.setPassword(password);
// 配置JavaMail属性
Properties props = mailSender.getJavaMailProperties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", "true");
props.put("mail.debug", "false"); // 关闭调试模式生产环境建议false
// 根据端口设置SSL/TLS465通常用SSL587用TLS
if (port == 465) {
props.put("mail.smtp.ssl.enable", "true");
} else if (port == 587) {
props.put("mail.smtp.starttls.enable", "true");
}
// 跳过SSL证书验证核心配置
disableSslVerification(props);
return mailSender;
}
// 禁用SSL证书验证的方法
private void disableSslVerification(Properties props) throws Exception {
// 创建信任所有证书的TrustManager
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
// 初始化SSL上下文
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
// 设置自定义SSLSocketFactory
props.put("mail.smtp.ssl.socketFactory", sc.getSocketFactory());
// 信任所有主机
props.put("mail.smtp.ssl.trust", "*");
}
}

View File

@ -230,39 +230,4 @@ public class EntranceController {
}
@Resource
private EmailUtil emailUtil;
@RequestMapping(value = "/sendemail")
@ResponseBody
public JsonResultEntity sendemail(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
//emailUtil.sendSimpleMessage(
// "number8912@qq.com",
// "测试邮件简单",
// "这是一封来自Spring Boot的测试邮件"
//);
String filePath = "/Users/apple/Desktop/【C4协同费控产品】(报表相关)字典说明zm@2025.pdf";
File file = new File(filePath);
List<MultipartFile> attachments = new ArrayList<>();
try (FileInputStream input = new FileInputStream(file)) {
MultipartFile multipartFile = new MockMultipartFile(
file.getName(), // 对应表单中的文件字段名
file.getName(), // 原始文件名
"application/pdf", // 或根据文件类型指定 MIME 类型
input
);
attachments.add(multipartFile);
}
String htmls = "<div style=\"font-family:'Arial',sans-serif;margin:20px;\"><style>table{width:100%;border-collapse:collapse;border:1px solid #ddd}th,td{padding:10px 15px;border:1px solid #ddd;text-align:left}th{background-color:#4CAF50;color:white;font-weight:bold}tr:nth-child(even){background-color:#f2f2f2}tr:hover{background-color:#e0e0e0}h2{text-align:center;font-size:24px;margin-bottom:15px;color:#333}.priority-high{background-color:#ffebee}.priority-medium{background-color:#fff3e0}.priority-low{background-color:#e8f5e9}</style><h2>任务列表</h2><table><thead><tr><th>问题标题</th><th>详细描述</th><th>预计完成时间</th></tr></thead><tbody><tr class=\"priority-medium\"><td>共享结算备注</td><td>结算单备注字段赋值</td><td>2025年7月2日</td></tr><tr class=\"priority-medium\"><td>流水状态展示调整</td><td>1、流水匹配界面明细行匹配状态 调整为已推送<br>2、查询条件 已推送明源 调整为已推送</td><td>2025年7月3日</td></tr><tr class=\"priority-high\"><td>共享单据挂起后,银行流水对账界面客商有误</td><td></td><td>2025年7月4日</td></tr><tr class=\"priority-high\"><td>单据在审核中心 详细信息默认不自动带出</td><td>审批界面表体明细数据未自动展开</td><td>2025年7月4日</td></tr><tr class=\"priority-medium\"><td>单据传输失败后ncc 有自由状态的单子</td><td>通过接口对接NC单据附件上传失败后单据未删除</td><td>2025年7月3日</td></tr><tr class=\"priority-low\"><td>对接审核状态更新优化</td><td>共享审批,取消审批,共享审核,共享复核,驳回状态回传简道云</td><td>2025年7月10日</td></tr></tbody></table></div>";
emailUtil.sendHtmlAndFileMessage("number8912@qq.com",
"测试邮件html",
htmls,attachments);
return BaseResult.getSuccessMessageEntity("成功");
}
}