|
@@ -1,285 +0,0 @@
|
|
|
-package com.storlead.mail.util;
|
|
|
|
|
-
|
|
|
|
|
-import lombok.extern.log4j.Log4j2;
|
|
|
|
|
-import org.jsoup.Jsoup;
|
|
|
|
|
-import org.jsoup.nodes.Document;
|
|
|
|
|
-import org.jsoup.nodes.Element;
|
|
|
|
|
-import org.springframework.core.io.FileSystemResource;
|
|
|
|
|
-import org.springframework.mail.javamail.MimeMessageHelper;
|
|
|
|
|
-
|
|
|
|
|
-import javax.activation.DataHandler;
|
|
|
|
|
-import javax.activation.DataSource;
|
|
|
|
|
-import javax.activation.FileDataSource;
|
|
|
|
|
-import javax.mail.Multipart;
|
|
|
|
|
-import javax.mail.Part;
|
|
|
|
|
-import javax.mail.internet.MimeBodyPart;
|
|
|
|
|
-import javax.mail.util.ByteArrayDataSource;
|
|
|
|
|
-import java.io.File;
|
|
|
|
|
-import java.io.FileOutputStream;
|
|
|
|
|
-import java.io.InputStream;
|
|
|
|
|
-import java.io.OutputStream;
|
|
|
|
|
-import java.net.HttpURLConnection;
|
|
|
|
|
-import java.net.URL;
|
|
|
|
|
-import java.nio.file.Files;
|
|
|
|
|
-import java.nio.file.Paths;
|
|
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
|
|
-import java.util.*;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * @program: sp-sales-platform
|
|
|
|
|
- * @description:
|
|
|
|
|
- * @author: chenkq
|
|
|
|
|
- * @create: 2024-12-13 10:20
|
|
|
|
|
- */
|
|
|
|
|
-@Log4j2
|
|
|
|
|
-public class EmailHelper {
|
|
|
|
|
- private static final Map<String, String> mimeToExtensionMap = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- static {
|
|
|
|
|
- mimeToExtensionMap.put("image/png", "png");
|
|
|
|
|
- mimeToExtensionMap.put("image/jpeg", "jpg");
|
|
|
|
|
- mimeToExtensionMap.put("image/gif", "gif");
|
|
|
|
|
- mimeToExtensionMap.put("application/pdf", "pdf");
|
|
|
|
|
- mimeToExtensionMap.put("text/plain", "txt");
|
|
|
|
|
- // 根据需要继续添加其他 MIME 类型映射
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * 将 HTML 内容中的 img 标签的 src URL 转换为 cid:imageX 格式。
|
|
|
|
|
- *
|
|
|
|
|
- * @param htmlContent 邮件的 HTML 内容
|
|
|
|
|
- * @param imagePathMap 图片路径的映射
|
|
|
|
|
- * @return 修改后的 HTML 内容
|
|
|
|
|
- * @throws
|
|
|
|
|
- */
|
|
|
|
|
- public static String convertImageUrlsToCid(String htmlContent, Map<String, File> imagePathMap,String filePath) {
|
|
|
|
|
- Document doc = Jsoup.parse(htmlContent); // 使用 Jsoup 解析 HTML 内容
|
|
|
|
|
-
|
|
|
|
|
- // 遍历所有 img 标签
|
|
|
|
|
- for (Element img : doc.select("img")) {
|
|
|
|
|
- String src = img.attr("src"); // 获取 src 属性(图片 URL)
|
|
|
|
|
-
|
|
|
|
|
- // 如果 src 是一个有效的 URL,且需要转换为 CID
|
|
|
|
|
- if (src != null && !src.isEmpty()) {
|
|
|
|
|
- // 根据图片的 URL 为每个图片生成唯一的 CID
|
|
|
|
|
- String cid = "image" + imagePathMap.size() + 1; // 简单的 CID 生成规则,可以改成更复杂的逻辑
|
|
|
|
|
- img.attr("src", "cid:" + cid); // 将 src 转换为 cid:imageX 格式
|
|
|
|
|
- // 将图片路径和生成的 CID 映射保存
|
|
|
|
|
- String downloadDir = filePath;
|
|
|
|
|
- String imageName = src.replace("/sales/mail/file/images/","/");
|
|
|
|
|
- String url = downloadDir + imageName;
|
|
|
|
|
- imagePathMap.put(cid, new File(url));
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return doc.html(); // 返回修改后的 HTML 内容
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static String getFileExtensionFromBase64(String base64Data) {
|
|
|
|
|
- // 1. 先检查是否包含 `data:` URL 格式
|
|
|
|
|
- if (base64Data.startsWith("data:")) {
|
|
|
|
|
- // 从 `data:[mediatype];base64,` 中提取 MIME 类型
|
|
|
|
|
- String mimeTypePart = base64Data.split(";")[0]; // 例如:data:image/png
|
|
|
|
|
- String mimeType = mimeTypePart.substring(5); // 去掉 "data:",例如 "image/png"
|
|
|
|
|
-
|
|
|
|
|
- // 2. 查找扩展名
|
|
|
|
|
- return mimeToExtensionMap.getOrDefault(mimeType, "unknown"); // 返回对应的扩展名
|
|
|
|
|
- } else {
|
|
|
|
|
- throw new IllegalArgumentException("Invalid Base64 format. Expected data URL format.");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static MimeBodyPart createBase64BodyPart(String base64Data, String contentType,String extension) {
|
|
|
|
|
- // 1. 解码 Base64 数据
|
|
|
|
|
- try {
|
|
|
|
|
-
|
|
|
|
|
- String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
|
|
|
|
|
- String uniqueId = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
|
|
|
|
|
-
|
|
|
|
|
- String newFileName = "image_" + timestamp + "_" + uniqueId + "." + extension;
|
|
|
|
|
- byte[] decodedData = Base64.getDecoder().decode(base64Data);
|
|
|
|
|
- // 2. 创建 ByteArrayDataSource,将解码后的数据作为输入流
|
|
|
|
|
- // 3. 创建 MimeBodyPart,并设置数据源
|
|
|
|
|
- MimeBodyPart mimeBodyPart = new MimeBodyPart();
|
|
|
|
|
- DataSource dataSource = new ByteArrayDataSource(decodedData, contentType);
|
|
|
|
|
- mimeBodyPart.setDataHandler(new DataHandler(dataSource));
|
|
|
|
|
- // 4. 设置文件名(可选)
|
|
|
|
|
- mimeBodyPart.setFileName(newFileName); // 根据需要设置文件名和扩展名
|
|
|
|
|
- return mimeBodyPart;
|
|
|
|
|
- }catch (Exception e) {
|
|
|
|
|
- log.error("convertImageUrlsToCidBodyPart -- error",e);
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static String convertImageUrlsToCidBodyPart(String htmlContent, List<MimeBodyPart> imageParts, String filePath, Multipart multipart) {
|
|
|
|
|
- Document doc = Jsoup.parse(htmlContent); // 使用 Jsoup 解析 HTML 内容
|
|
|
|
|
-
|
|
|
|
|
- Integer i = 0;
|
|
|
|
|
- // 遍历所有 img 标签
|
|
|
|
|
- for (Element img : doc.select("img")) {
|
|
|
|
|
- try {
|
|
|
|
|
- i ++ ;
|
|
|
|
|
-
|
|
|
|
|
- String src = img.attr("src");
|
|
|
|
|
- String cid = "image_sp_" + i;
|
|
|
|
|
- if (src.startsWith("data:image/")) {
|
|
|
|
|
- // 如果 src 是一个有效的 URL,且需要转换为 CID
|
|
|
|
|
- String mimeTypePart = src.split(";")[0]; // 例如:data:image/png
|
|
|
|
|
- String mimeType = mimeTypePart.substring(5); // 去掉 "data:",例如 "image/png"
|
|
|
|
|
- // 3. 根据 MIME 类型推断扩展名
|
|
|
|
|
- String extension = mimeToExtensionMap.getOrDefault(mimeType, "unknown");
|
|
|
|
|
- // 4. 提取 Base64 编码的内容(去掉前缀 "data:image/png;base64,")
|
|
|
|
|
- String base64Content = src.split(",")[1];
|
|
|
|
|
- MimeBodyPart imagePart = createBase64BodyPart(base64Content, mimeType,extension);
|
|
|
|
|
- imagePart.setHeader("Content-ID", cid);
|
|
|
|
|
- img.attr("src", "cid:" + cid);
|
|
|
|
|
- imagePart.setDisposition(Part.INLINE); // 设置为内嵌
|
|
|
|
|
- multipart.addBodyPart(imagePart);
|
|
|
|
|
- }else if (src.contains("https://sales.storlead.com/sales/mail")){
|
|
|
|
|
- if (src != null && !src.isEmpty()) {
|
|
|
|
|
- // 根据图片的 URL 为每个图片生成唯一的 CID
|
|
|
|
|
- img.attr("src", "cid:" + cid); // 将 src 转换为 cid:imageX 格式
|
|
|
|
|
- }
|
|
|
|
|
- MimeBodyPart imagePart = createImagePartFromURL(src,cid);
|
|
|
|
|
- multipart.addBodyPart(imagePart);
|
|
|
|
|
-
|
|
|
|
|
- } else if (src.contains("/sales/mail/file/images/")){
|
|
|
|
|
- if (src != null && !src.isEmpty()) {
|
|
|
|
|
- // 根据图片的 URL 为每个图片生成唯一的 CID
|
|
|
|
|
- img.attr("src", "cid:" + cid); // 将 src 转换为 cid:imageX 格式
|
|
|
|
|
- }
|
|
|
|
|
- String downloadDir = filePath;
|
|
|
|
|
- String imageName = src.replace("/sales/mail/file/images/", "");
|
|
|
|
|
- String imagePath = downloadDir + imageName;
|
|
|
|
|
- MimeBodyPart imagePart = new MimeBodyPart();
|
|
|
|
|
- DataSource source = new FileDataSource(imagePath);
|
|
|
|
|
- imagePart.setDataHandler(new DataHandler(source));
|
|
|
|
|
- imagePart.setHeader("Content-ID", cid);
|
|
|
|
|
- imagePart.setDisposition(Part.INLINE); // 设置为内嵌
|
|
|
|
|
- multipart.addBodyPart(imagePart);
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- // 获取 src 属性(图片 URL)
|
|
|
|
|
-
|
|
|
|
|
- }catch (Exception e ) {
|
|
|
|
|
- log.error("convertImageUrlsToCidBodyPart -- error",e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return doc.html(); // 返回修改后的 HTML 内容
|
|
|
|
|
- }
|
|
|
|
|
- public static MimeBodyPart createImagePartFromURL(String imageUrl,String cid) throws Exception {
|
|
|
|
|
- // 从URL加载图片
|
|
|
|
|
- URL url = new URL(imageUrl);
|
|
|
|
|
- try (InputStream inputStream = url.openStream()) {
|
|
|
|
|
- byte[] imageBytes = inputStream.readAllBytes();
|
|
|
|
|
- DataSource dataSource = new ByteArrayDataSource(imageBytes, "image/jpeg"); // 根据图片类型选择MIME类型
|
|
|
|
|
- MimeBodyPart imagePart = new MimeBodyPart();
|
|
|
|
|
- imagePart.setDataHandler(new javax.activation.DataHandler(dataSource));
|
|
|
|
|
- String fileNameWithExtension = Paths.get(url.getPath()).getFileName().toString();
|
|
|
|
|
- String fileNameWithoutExtension = fileNameWithExtension.substring(0, fileNameWithExtension.lastIndexOf('.'));
|
|
|
|
|
- imagePart.setFileName(fileNameWithoutExtension); // 设置附件名称去掉后缀
|
|
|
|
|
- imagePart.setHeader("Content-ID", cid);
|
|
|
|
|
- imagePart.setDisposition(Part.INLINE); // 设置为内嵌
|
|
|
|
|
- return imagePart;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public static String convertImageUrlsToBase(String htmlContent, String filePath) {
|
|
|
|
|
- Document doc = Jsoup.parse(htmlContent); // 使用 Jsoup 解析 HTML 内容
|
|
|
|
|
- String downloadDir = filePath;
|
|
|
|
|
-
|
|
|
|
|
- // 遍历所有 img 标签
|
|
|
|
|
- for (Element img : doc.select("img")) {
|
|
|
|
|
- String src = img.attr("src"); // 获取 src 属性(图片 URL)
|
|
|
|
|
- String imageName = src.replace("/sales/mail/file/images/", "");
|
|
|
|
|
- String imgSrc = downloadDir + imageName;
|
|
|
|
|
- String base64Image = convertImageToFileBase64(imgSrc);
|
|
|
|
|
- String imageExtension = imgSrc.substring(imgSrc.lastIndexOf('.') + 1);
|
|
|
|
|
- // 构造 base64 数据 URI
|
|
|
|
|
- String base64DataUri = "data:image/" + imageExtension + ";base64," + base64Image;
|
|
|
|
|
- // 将图片的 src 属性替换为 base64 数据 URI
|
|
|
|
|
- img.attr("src", base64DataUri);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return doc.html(); // 返回修改后的 HTML 内容
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static String convertImageToBase64(String imageUrl) {
|
|
|
|
|
- try {
|
|
|
|
|
- URL url = new URL(imageUrl);
|
|
|
|
|
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
|
- connection.setRequestMethod("GET");
|
|
|
|
|
- connection.setDoOutput(true);
|
|
|
|
|
- connection.connect();
|
|
|
|
|
-
|
|
|
|
|
- // 从连接中读取图片数据
|
|
|
|
|
- try (InputStream in = connection.getInputStream()) {
|
|
|
|
|
- byte[] imageBytes = in.readAllBytes(); // 读取所有图片字节
|
|
|
|
|
- return Base64.getEncoder().encodeToString(imageBytes); // 转换为 Base64 编码
|
|
|
|
|
- }
|
|
|
|
|
- }catch (Exception e) {
|
|
|
|
|
- log.error("convertImageToBase64 -- error",e);
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- public static String convertImageToFileBase64(String imagePath) {
|
|
|
|
|
- try {
|
|
|
|
|
- // 读取图片文件
|
|
|
|
|
- byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath));
|
|
|
|
|
-
|
|
|
|
|
- // 使用 Base64 编码将图片字节数组转换为字符串
|
|
|
|
|
- return Base64.getEncoder().encodeToString(imageBytes);
|
|
|
|
|
- }catch (Exception e) {
|
|
|
|
|
- log.error("convertImageToBase64 -- error",e);
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- /**
|
|
|
|
|
- * 将图片添加到邮件附件中,并返回一个 Map 映射,包含每个图片的 CID 和对应的 File。
|
|
|
|
|
- *
|
|
|
|
|
- * @param imagePathMap 图片路径的映射
|
|
|
|
|
- * @param helper MimeMessageHelper
|
|
|
|
|
- * @throws
|
|
|
|
|
- */
|
|
|
|
|
- public static void addImagesToMail(Map<String, File> imagePathMap, MimeMessageHelper helper) {
|
|
|
|
|
- // 遍历 Map,将每个图片作为附件添加到邮件中
|
|
|
|
|
- try {
|
|
|
|
|
- for (Map.Entry<String, File> entry : imagePathMap.entrySet()) {
|
|
|
|
|
- String cid = entry.getKey();
|
|
|
|
|
- File imageFile = entry.getValue();
|
|
|
|
|
-
|
|
|
|
|
- // 添加内嵌图片,Content-ID 用于在 HTML 中引用
|
|
|
|
|
- helper.addInline(cid, imageFile);
|
|
|
|
|
- }
|
|
|
|
|
- }catch (Exception e) {
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static File downloadImage(String imageUrl) {
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- URL url = new URL(imageUrl);
|
|
|
|
|
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
|
|
|
- connection.setRequestMethod("GET");
|
|
|
|
|
- connection.setDoOutput(true);
|
|
|
|
|
- connection.connect();
|
|
|
|
|
-
|
|
|
|
|
- String tempDir = System.getProperty("java.io.tmpdir");
|
|
|
|
|
- String imageName = UUID.randomUUID().toString() + ".jpg"; // 根据实际类型修改
|
|
|
|
|
- File tempImage = new File(tempDir, imageName);
|
|
|
|
|
-
|
|
|
|
|
- try (InputStream in = connection.getInputStream();
|
|
|
|
|
- OutputStream out = new FileOutputStream(tempImage)) {
|
|
|
|
|
- byte[] buffer = new byte[4096];
|
|
|
|
|
- int bytesRead;
|
|
|
|
|
- while ((bytesRead = in.read(buffer)) != -1) {
|
|
|
|
|
- out.write(buffer, 0, bytesRead);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return tempImage;
|
|
|
|
|
- }catch (Exception e ) {
|
|
|
|
|
- log.error("downloadImage -- error",e);
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|