使用hutool阿里云企业邮箱发送邮件和附件,包含PDF转图片base64,PDF转HTML

news/2024/5/14 15:58:06

请务必开启阿里云服务器465 ssl邮件端口
废话不多,我们直接上代码。

注意:阿里云邮箱不支持邮件内容HTML带有URL链接,会被过滤和谐掉!,所以邮件内容有PDF要么:

  • PDF转图片base64,PDF转HTML;
  • 要么附件形式

maven添加依赖:

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.22</version>
</dependency><dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf.free</artifactId><version>4.4.1</version>
</dependency><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.24</version>
</dependency><repositories><repository><id>com.e-iceblue</id><url>https://repo.e-iceblue.cn/repository/maven-public/</url></repository>
</repositories>

完整代码:

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import com.sun.mail.util.MailSSLSocketFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.junit.jupiter.api.Test;import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;import com.spire.pdf.*;import javax.imageio.ImageIO;/*** @author hsj* @description:阿里云企业邮箱发送邮件和附件(请开启阿里云服务器465端口)* @date 2024-4-25 8:59*/
@Slf4j
public class Temail {/*** @Description:发邮件* @author HeShengjin 2356899074@qq.com* @date 2024-4-25 10:11*/@Testpublic void t() throws IOException {InputStream inputStream = null;try {//公司阿里云企业邮箱String from = "你的阿里云企业邮箱";// 加载PDF文档URLURL url = new URL("https://jixujiaoyu-test.oss-cn-shenzhen.aliyuncs.com/upload/20240425/1954fae396aa5aa1eb3dbad8edc19547.pdf");HttpURLConnection conn = (HttpURLConnection) url.openConnection();inputStream = conn.getInputStream();//			// 获取字节数组byte[] bytesPdf = readInputStream(inputStream);MailSSLSocketFactory sf = new MailSSLSocketFactory();sf.setTrustAllHosts(true);MailAccount account = new MailAccount();account.setHost("smtp.mxhichina.com");account.setPort(465);account.setAuth(true);account.setSslEnable(true);account.setFrom(from.trim());account.setUser(from.trim());account.setPass("你的阿里云企业邮箱密码");account.setCharset(CharsetUtil.CHARSET_UTF_8);account.setCustomProperty("mail.smtp.ssl.socketFactory", sf);MailUtil.send(account,CollUtil.newArrayList("你的要发送的目标邮箱"),//目标邮箱"主题名称",//邮件主题"<p>测试发送邮件,使用阿里云云邮箱(发送中文名字附件)。</p>",true,//支持HTML内容FileUtil.writeBytes(bytesPdf,String.format("%s%s",FileUtil.getTmpDirPath(),"中文名字附件.pdf")));} catch (Exception e){e.printStackTrace();log.error(String.format("发送邮件失败,%s",e.getMessage()));} finally {if (inputStream != null){inputStream.close();}}}/*** @Description:PDF转HTML* @author HeShengjin 2356899074@qq.com* @date 2024-4-25 10:11*/@Testpublic void t2() throws IOException{InputStream inputStream = null;try {// 加载PDF文档URLURL url = new URL("https://jixujiaoyu-test.oss-cn-shenzhen.aliyuncs.com/upload/20240425/1954fae396aa5aa1eb3dbad8edc19547.pdf");HttpURLConnection conn = (HttpURLConnection) url.openConnection();inputStream = conn.getInputStream();// 获取字节数组byte[] bytes = readInputStream(inputStream);//加载PDF文档PdfDocument pdf = new PdfDocument();pdf.loadFromBytes(bytes);//设置useEmbeddedSvg和 useEmbeddedImg布尔值为truepdf.getConvertOptions().setPdfToHtmlOptions(true,true);//保存到流File outFile = new File("PDFtoHTML.html");OutputStream outputStream = new FileOutputStream(outFile);pdf.saveToStream(outputStream, FileFormat.HTML);pdf.close();System.out.println("PDF转换成HTML完成!");} catch (Exception e) {e.printStackTrace();} finally {if (inputStream != null){inputStream.close();}}}/*** @Description:PDF转图片base64* @author HeShengjin 2356899074@qq.com* @date 2024-4-25 10:12*/@Testpublic void t3() throws IOException{InputStream inputStream = null;ByteArrayOutputStream byteArrayOutputStream = null;try {// 加载PDF文档URLURL url = new URL("https://jixujiaoyu-test.oss-cn-shenzhen.aliyuncs.com/upload/20240425/1954fae396aa5aa1eb3dbad8edc19547.pdf");HttpURLConnection conn = (HttpURLConnection) url.openConnection();inputStream = conn.getInputStream();//			// 获取字节数组byte[] bytesPdf = readInputStream(inputStream);List<BufferedImage> bufferedImages = pdfToImage(bytesPdf);byteArrayOutputStream = new  ByteArrayOutputStream();ImageIO.write(bufferedImages.get(0),"jpg",byteArrayOutputStream);//只要PDF第一页的一张图片// 清流byteArrayOutputStream.flush();// 转为byte[]byte[] byteImage = byteArrayOutputStream.toByteArray();// 将图片数据转换为Base64字符串String base64String = Base64.getEncoder().encodeToString(byteImage);String html = String.format("<img src=\"data:image/jpg;base64,%s\" />",base64String);
////保存到流File outFile = new File("PDFtoIMGBase64.html");FileUtils.writeByteArrayToFile(outFile,html.getBytes(StandardCharsets.UTF_8));System.out.println("PDF转换成HTML完成!");} catch (Exception e) {e.printStackTrace();} finally {if (inputStream != null){inputStream.close();}if (byteArrayOutputStream != null){// 关流byteArrayOutputStream.close();}}}/**** @Description: (InputStream转字节数组)* @author hsj* @date 2019年8月8日*/public byte[] readInputStream(InputStream inputStream) throws IOException {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();}/*** PDF转图片 (一个PDF很多页,所以很多图片)* @param bytes:文件输入流* @return*/public List<BufferedImage> pdfToImage(byte[] bytes){List<BufferedImage> images = new ArrayList<>();PDDocument document = null;try {// 加载PDF文档document = PDDocument.load(bytes);// 创建PDFRenderer对象PDFRenderer renderer = new PDFRenderer(document);for (int i = 0; i < document.getNumberOfPages(); i++) {/*** 《 72 》 此处设置得越大像素越高,生成得时候也会越久* DPI 的设置一般根据具体的需求和使用场景来决定。DPI 越高,生成的图片分辨率越大,图像质量也越高,* 但同时文件大小也会变得更大。通常情况下,如果需要对生成的图片进行放大、裁剪等操作,建议将 DPI 设置得较高,* 以保证图像质量和细节的清晰度;如果只是需要简单地浏览或共享图片,可以适当降低 DPI 以减小文件大小。在实际开发中,* 可以根据不同的应用场景进行调整。一般来说,72 DPI 是一个比较常见的默认值,可以作为参考。*/BufferedImage image = renderer.renderImageWithDPI(i, 72, ImageType.RGB);images.add(image);}return images;} catch (Exception e) {e.printStackTrace();return null;} finally {// 关闭文档try {if (document != null) {document.close();}} catch (IOException e) {e.printStackTrace();}}}}

http://www.mrgr.cn/p/14517121

相关文章

【学习记录】autoware标定相机与激光雷达外参

一、autoware选择 这里踩了好几个坑&#xff0c;首先autoware作为一个无人驾驶知名框架&#xff0c;其内部实际上是有两套标定的东西的&#xff0c;这一点绝大多数博客没有提到。其中最常用的是一个叫标定工具箱的东西&#xff0c;这个ros包已经在1.10往后的版本中被删掉了&am…

【1431】java学习网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 学习网站系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

双塔模型在召回和粗排的区别

答案参考&#xff1a;推荐系统中&#xff0c;双塔模型用于粗排和用于召回的区别有哪些? - 知乎 召回和粗排在不同阶段面临样本不一样&#xff0c;对双塔来说样本分布差异会使召回和粗排采取不一样的方式。召回打分空间是全部item空间&#xff0c;曝光只有很少一部分&#xff0…

eclipse 如何创建python文件

一、准备 1.平台要求&#xff1a; 电脑除了要安装eclipse软件和Python语言包之外&#xff0c;还需要将Python集成到eclipse软件中&#xff0c;网上有很多的方法&#xff0c;这里就不细细介绍如何集成了。 在下面界面中可以看到自己已经安装了继承插件。具体方法见步骤2&…

Linux网络编程---Socket编程

一、网络套接字 一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现。) 在通信过程中&#xff0c;套接字一定是成对出现的 套接字通讯原理示意图&#xff1a; 二、预备知识 1. 网络字节序 内存中的多字节数据相对于内存地址有大端和小端之分 小端法&…

【C语言】贪吃蛇详解(附源码)

一、贪吃蛇实现效果 【C语言】贪吃蛇&#xff08;控制台&#xff09; 二、源码 &#x1f388;&#x1f388;&#x1f388;Snake 残风也想永存/C语言项目 - 码云 - 开源中国 (gitee.com)&#x1f388;&#x1f388;&#x1f388; 三、如何使用C语言去实现一个贪吃蛇&#xff1f…

Python数据分析 DataFrame 笔记

08,DataFrame创建 DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。行索引:index 列索引:columns…

【介绍下分布式系统】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

同事上班这样摸鱼,我坐边上咋看他都在专心写代码啊

我边上有个同事&#xff0c;我坐他边上&#xff0c;但是每天看着他都眉头紧锁&#xff0c;忙的不亦乐乎&#xff0c;但终于有一天&#xff0c;我发现了他上班摸鱼的秘诀。 我劝你千万不要学会这4招&#xff0c;要不就该不好好上班了。 目录 1 上班看电影&#xff1f; 2 上班…

使用joinjs绘制流程图(五)-流程图绘制

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

洗地机哪个品牌好?四款性能王者巅峰对决推荐

洗地机的出现&#xff0c;让我们可以高效快速的完成地面清洁&#xff0c;家里干净卫生的同时还让我们有更多的时间去做其他事情。但是面多众多的机型&#xff0c;大家难免有些疑问&#xff0c;究竟哪个好用&#xff0c;怎么挑选到适合我的家用的洗地机&#xff1f;来&#xff0…

云原生Service Mesh服务网格简单介绍

serviceMesh是什么 Service Mesh是一个用于处理服务间通信的基础设施层&#xff0c;旨在实现云原生应用复杂服务拓扑中的可靠请求传递。其基本构成是一组与应用一起部署的轻量级网络代理&#xff0c;这些代理对应用来说是透明的。Service Mesh通过统一的方式来控制和处理服务间…

使用joinjs绘制流程图(二)-Paper对象的属性和方法

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

使用joinjs绘制流程图(三)-Rect对象属性

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

经典的目标检测算法有哪些?

一、经典的目标检测算法有哪些&#xff1f; 目标检测算法根据其处理流程可以分为两大类&#xff1a;One-Stage&#xff08;单阶段&#xff09;算法和Two-Stage&#xff08;两阶段&#xff09;算法。以下是一些经典的目标检测算法&#xff1a; 单阶段算法: YOLO (You Only Loo…

system -v 信号量的使用

本文介绍了,以图片的形式介绍了system -V IPC信号量的主要作用以及使用的例程,并且用买卖车为例子介绍了信号量的具体使用方法。信号量的作用 信号量是system -v IPC中的一种,通过P、V操作它体现了同步和互斥资源的分配机制。信号量的作用主要可以总结为如下:信号量是syste…

站立会议和燃尽图08

站立会议和燃尽图08 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月26日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月26日 7:00 至 2024年4月26日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…

业财一体化数字化

业财一体化有助于打破业务和财务之间的隔阂,助推企业做好业务洞察,而业财一体化数字化,则可以进一步助推财务业务一体化,提升业务财务的协同效率。这篇文章里,作者就对业财一体化的定义、挑战、以及业财一体化数字化等内容做了拆解,一起来看。 引子 销售人员老王签订了个…

站立会议和燃尽图06

站立会议和燃尽图06 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月24日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月24日 7:00 至 2024年4月24日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…

站立会议和燃尽图07

站立会议和燃尽图07 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月25日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月25日 7:00 至 2024年4月25日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…