在 Power Automate 中将每封收到的电子邮件转换为可用于审计的 PDF 存档:7 个步骤的 Outlook 工作流程

电子邮件转PDF存档 这是一个 Power Automate 流,它会在收到每封新的 Outlook 邮件时触发,将邮件正文和所有附件转换为 PDF 格式,合并成一个带有时间戳的 PDF 文件,并将结果写入 Dropbox 以进行长期合规性保存。共七个操作。无需编写代码。每封邮件生成一个文件,先生成邮件正文,然后按顺序生成附件。输出文件名为 merge-YYYYMMDD-HHmmss.pdf 因此,每个存档条目都可以唯一排序。
审计团队、档案管理负责人和合规官需要以防篡改、可搜索的格式保存电子邮件证据,并确保其符合 Exchange 的数据保留策略。Outlook 原生导出功能需要手动逐个文件导出,并且会丢失附件。本教程将介绍一种无需编写代码的替代方案:所有收到的电子邮件都会自动合并成一个 PDF 文件,并保留原始文件。 .eml 附件仍保留在 Outlook 中以作法律保留,但存档 PDF 才是权威记录副本。
Outlook 触发器会在收到发送到受监控地址的每封入站电子邮件时触发。一个名为 电子邮件 打开。PDF4me 转换为 PDF 首先将 HTML 正文转换为 PDF(成为第 1 页)。 适用于每个 遍历每个附件,使用 Aspose Words/Cells/Slides 渲染器将每个附件转换为 PDF,然后依次追加。PDF4me 合并多个PDF文件 它会读取整个数组并生成一个合并后的 PDF 文件。Dropbox 将其写入为: merge-20260611-103323.pdf正文在前,附件按顺序排列,带时间戳,存档级别。
基于原因的问答
为什么不直接保存 .eml 文件,而是将其转换为 PDF 格式进行存档? EML 文件需要使用 Outlook 或兼容的阅读器才能打开,附件嵌入在二进制流中,审计人员无法搜索,并且依赖于发件人的邮件客户端格式。而单个合并的 PDF 文件则具有通用可读性、支持 OCR 识别、包含附件,并且符合大多数法律取证和 SOX/GDPR 审计所要求的保存格式。
为什么将身体和附件放在同一个数组变量中? “合并多个 PDF 文件”操作需要一个有序的集合。只需初始化一次,在步骤 4 中推送正文,在步骤 5 中推送每个转换后的附件,即可得到一个符合归档所需文档顺序的数组(正文在前,附件按发送顺序排列)。如果使用两个独立的数组,则之后需要执行一次“撰写”操作才能将它们连接起来。
为什么 base64 转二进制 每次推动都这样吗? PDF4me 转换为 PDF 时,会将输出结果以 base64 字符串的形式返回。 $contentOutlook 附件以 base64 编码格式接收。 内容字节合并多个 PDF 文件需要二进制缓冲区,而不是 base64 字符串。 base64ToBinary(...) 调用桥接器会同时调用这两个数据源,只是指向不同的属性名称。跳过转换,合并操作会因“内容无效”而报错。
为什么输出名称要带时间戳? 同一分钟内发送到同一邮箱地址的两封邮件会因为文件名相同而冲突。 concat('merge-', formatDateTime(utcNow(), 'yyyyMMdd-HHmmss'), '.pdf') 生成精度为秒的 UTC 名称,例如 merge-20260611-103323.pdf:可按词典顺序排序,即时可读,且结构独特。审计人员非常喜欢这种格式。
您将获得
输入: 任何发送到受监控 Outlook 地址(此处)的入站电子邮件 [email protected])以及一个或多个附件。本教程使用简短的消息正文(“嗨,希望你一切都好……”)和两个 DOCX 附件(3Page.docx, Docx_2Pages.docx)。 输出: 单个合并存档 PDF /blog data/merge blog template/output/名为 merge-YYYYMMDD-HHmmss.pdf第 1 页是正文。从第 2 页开始,依次显示附件,使用 Aspose Words 渲染。
收到的电子邮件

两次运行后的存档文件夹

合并存档 PDF 的第 1 页

你需要什么
- 动力自动化。 打开 Power Automate任何包含高级连接器的套餐(PDF4me Connect 属于高级套餐)。
- PDF4me API密钥。 获取您的 API 密钥首次添加 PDF4me 操作时进行连接。
- Office 365 Outlook用于“当收到新邮件时”V3触发器,并读取附件内容字节。连接器可以验证的任何收件箱均可正常工作。
- Dropbox (或 SharePoint、OneDrive、Google Drive)。作为存档目标位置。
- 一封带有附件的测试邮件本教程使用了两个 DOCX 示例。 3页.docx 和 Docx_2Pages.docx。
首先获取样本和预期输出。 下载这两个 DOCX 文件,将它们作为附件发送到您关注的邮箱地址,然后发布流程。首次运行应该会生成一个结果。 merge-YYYYMMDD-HHmmss.pdf 它与链接的示例完全一致(只有时间戳不同)。
流程概览
- Outlook:收到新邮件时(V3) (扳机)。
- 初始化变量 命名
email(大批)。 - PDF4me:转换为 PDF(正文)读取 HTML 正文,返回 PDF。
- 追加到数组变量 和
base64ToBinary在改装后的车身上。 - 适用于每个 在
triggerOutputs()?['body/attachments']:- PDF4me:转换为 PDF 附件。
- 追加到数组变量 和
base64ToBinary在转换后的PDF文件上。
- PDF4me:将多个 PDF 文件合并成一个 PDF 文件输入数组,输出一个 PDF 文件。
- Dropbox:创建文件文件名表达式会添加 UTC 时间戳。
完整流程概述

七个步骤。PDF4me 在流程中出现三次:转换正文、转换每个附件、合并所有内容。
Outlook附件字段(参考)
展望 当收到新邮件时 V3 触发器会显示您映射到转换器中的这些附件字段:
| 场地 | 类型 | 源表达式 | 它承载着什么 |
|---|---|---|---|
name | 细绳 | items('Apply_to_each')?['name'] | 原始文件名(包括扩展名)Invoice.docx) |
contentBytes | base64字符串 | items('Apply_to_each')?['contentBytes'] | 附件的二进制内容,采用 Base64 编码。 |
contentType | 细绳 | items('Apply_to_each')?['contentType'] | MIME 类型(application/vnd.openxmlformats-officedocument.wordprocessingml.document) |
size | 整数 | items('Apply_to_each')?['size'] | 字节,可用于过滤掉大型附件 |
isInline | 布尔值 | items('Apply_to_each')?['isInline'] | 对于嵌入在正文中的内联图片,此规则适用;通常会被过滤掉。 |
PDF4me 转换为 PDF 时会读取文件扩展名。 name 选择合适的渲染器(.docx → 反对言语, .xlsx → 排列细胞, .pptx → Aspose Slides、图像和 PDF 可原生处理)。
第一步:如何查看 Outlook 收件箱中的入站邮件?
目前为止的流程: 仅触发。
- 在 动力自动化 点击 创造, 选择 自动化云流。
- 给流程命名(例如:
Email Archive to PDF), 挑选 Office 365 Outlook:收到新邮件时(V3) 以点击作为触发器 创造。 - 连接 您的 Office 365 邮箱。
- 扩张 高级参数 点击 显示全部 显示筛选选项。
- 配置:
- 到:
[email protected](筛选出只有发送到此地址的邮件才能触发流程) - 包含附件:
Yes - 仅带附件:
Yes
- 到:
触发器配置

提示。 仅限附件 是 正是这一点阻止了流程在每个内部通知、日历邀请或自动回复时触发。结合使用 到 筛选专用存档别名(例如 [email protected]) 创建一个干净的接收地址,该地址只接收您真正想要存档的邮件。
步骤 2:初始化变量电子邮件
目前为止的流程: 触发器加上初始化变量。
打开一个空数组来收集正文 PDF 和所有附件 PDF。
- 点击 + 新步骤, 挑选 初始化变量。
- 配置:
- 姓名:
email - 类型:
Array - 价值:留空
- 姓名:
初始化变量配置

步骤 3:PDF4me 如何将电子邮件正文渲染成 PDF?
目前为止的流程: 触发器 + 初始化变量 + 转换为 PDF 正文。
Outlook 触发器以 HTML 格式发出邮件正文。 body/bodyPDF4me 转换为 PDF 直接读取 HTML,因此整个转换过程只需一次操作调用。
- 点击 + 新步骤, 搜索 PDF4me, 挑选 转换为 PDF。
- 重命名 采取行动 转换为 PDF 正文 因此,步骤 5 的“转换为 PDF”操作稍后会获得一个更清晰的名称。
- 连接 PDF4me 连接时请使用您的 API 密钥(仅限首次连接)。
- 配置:
- 文件内容 (表达式,点击)
fx):triggerOutputs()?['body/body'] - 文件名:
email-body.html
- 文件内容 (表达式,点击)
转换为 PDF 正文配置

这 .html 文件名扩展名告诉 PDF4me 使用哪个渲染器。发送 .docx, .xlsx, .png, 或者 .jpg 同样的操作可以轻松处理所有这些问题。
步骤 4:追加到数组变量(电子邮件正文)
目前为止的流程: 触发器 + 初始化变量 + 转换为 PDF 正文 + 追加(电子邮件正文)。
将转换后的正文 PDF 文件推送到目标位置。 email 数组作为第 1 页。
- 点击 + 新步骤, 挑选 追加到数组变量。
- 重命名 采取行动 将内容追加到数组变量(电子邮件正文) 为了更清楚地说明。
- 配置:
- 姓名:
email - 价值 (表达):
base64ToBinary(body('Convert_to_PDF_Body')?['$content'])
- 姓名:
追加电子邮件正文配置

步骤 5:如何遍历每个附件并转换每个附件?
目前为止的流程: 触发器 + 初始化变量 + 转换为 PDF 正文 + 追加(电子邮件正文) + 应用于每个。
遍历每个附件,将每个附件转换为 PDF,并依次添加,以便最终合并时能够保持附件顺序。
步骤 5a:应用于每个(选择来源)
- 点击 + 新步骤, 挑选 适用于每个。
- 配置:
- 从之前的步骤中选择一个输出。 (表达):
triggerOutputs()?['body/attachments']
- 从之前的步骤中选择一个输出。 (表达):

步骤 5b:转换为 PDF 格式(附件)
- 在循环内点击 添加操作, 挑选 PDF4me:转换为 PDF。
- 配置:
- 文件内容 (表达):
base64ToBinary(items('Apply_to_each')?['contentBytes']) - 文件名 (动态内容):选择 姓名 从“应用于每个当前项目”
- 文件内容 (表达):

这 姓名 动态内容令牌在运行时解析为 items('Apply_to_each')?['name']因此,每个附件都会使用其原始文件名进行转换。PDF4me 会读取文件扩展名来选择正确的渲染器。

步骤 5c:将转换后的附件添加到数组变量中
- 下面这行代码在同一个循环内转换为PDF格式, 添加操作, 挑选 追加到数组变量。
- 配置:
- 姓名:
email - 价值 (表达):
base64ToBinary(body('Convert_to_PDF')?['$content'])
- 姓名:

这两个物业名称很重要。 Outlook 附件字节流 内容字节PDF4me 转换为 PDF 输出的功能仍然存在。 $content两者都是 base64 编码。粘贴表达式时请保持名称一致,循环就能正常运行。
步骤 6:将多个 PDF 文件合并到一个压缩 PDF 文件中
目前为止的流程: 触发器 + 初始化变量 + 转换为 PDF 正文 + 追加(正文) + 应用于每个 + 合并多个 PDF。
整个 email 数组(首先是正文 PDF,然后是附件 PDF,按附件顺序)会进入单个 Merge 调用。
- 在“应用到每个循环”下方单击 + 新步骤, 搜索 PDF4me, 挑选 将多个 PDF 文件合并成一个 PDF 文件。
- 配置:
- 正文/文档内容选择
email变量标记 - 输出文件名:
Email Attachment Merge Output.pdf
- 正文/文档内容选择
合并操作配置

步骤 7:为什么存档文件名需要带时间戳?
目前为止的流程: 触发器 + 初始化变量 + 转换为 PDF 正文 + 追加 + 应用于每个 + 合并 + 创建文件。
将合并后的 PDF 文件以带有 UTC 时间戳的文件名写入 Dropbox,这样每个存档条目都是一个全新的、可排序的文件。同一秒内向同一地址发送两封邮件的情况非常罕见,因此无需嵌入邮件 ID 即可有效保证唯一性。
- 点击 + 新步骤, 挑选 Dropbox:创建文件。
- 配置:
- 文件夹路径:
/blog data/merge blog template/output - 文件名 (表达式,点击)
fx):concat('merge-', formatDateTime(utcNow(), 'yyyyMMdd-HHmmss'), '.pdf') - 文件内容选择 文件内容 来自“合并多个 PDF”操作的令牌
- 文件夹路径:
文件名表达式

最终操作,文件内容已映射

针对邮件量较大的收件箱的建议。 对于每分钟接收 10 封以上电子邮件的邮箱,请在邮件末尾附加一个简短的邮件 ID 哈希值,以确保邮件的唯一性: concat('merge-', formatDateTime(utcNow(), 'yyyyMMdd-HHmmss'), '-', substring(triggerOutputs()?['body/internetMessageId'], 0, 8), '.pdf')审计跟踪仍然可读,不可能发生冲突。
运行流程并验证
- 节省 右上角的流水。
- 向被监控的邮箱地址发送一封包含一个或多个附件的电子邮件。
- 打开 运行历史记录扳机应在几秒钟内击发。
- 打开 Dropbox
/blog data/merge blog template/output/一个名为merge-YYYYMMDD-HHmmss.pdf有没有。 - 打开PDF文件。第1页是正文。从第2页开始,依次显示所有附件,附件内容完整呈现。
你实际建造了什么? 实现零接触式邮件归档流程。所有带附件的邮件都会被合并成一个PDF文件,先是邮件正文,然后按顺序添加附件,并添加时间戳以避免冲突,最后放入一个共享文件夹,方便您的档案管理团队或审计人员进行搜索。同样的流程可以处理两个附件或二十个附件,无需任何更改。
无需重建即可添加的常见变体
endsWith(toLower(items('Apply_to_each')?['name']), '.pdf'). 跳过电子邮件签名和内嵌图像附件。PDF/A-2b 合并后,存档的PDF文件符合ISO 19005标准,可用于法律保留和监管机构提交。电子邮件存档:PDF 与 EML
| 方面 | 合并后的 PDF(此流程) | 原始 EML 导出 |
|---|---|---|
| 普遍可读 | 是的,任何PDF阅读器都可以。 | 不,需要 Outlook 或兼容的客户端 |
| 按内容搜索 | 是的,对OCR友好 | 仅限主体 |
| 包括附件 | 是的,以页面形式内联显示 | 是的,作为二进制流 |
| 审计格式匹配 | SOX、GDPR、HIPAA、FINRA 接受 | 经常被拒绝 |
| 防篡改 | 是的,如果添加了数字签名 | 可在任何编辑器中轻松编辑 |
| 文件大小 | 更大(所有已渲染页面) | 较小(无渲染) |
| 留存渠道 | 每封邮件发送一个PDF文件,方便链接。 | EML 需要容器格式 |
常见问题
如何在共享邮箱而不是个人收件箱上触发此流程?
替换 当收到新邮件时(V3) 用触发器 当共享邮箱收到新邮件时 (V2)将邮箱地址作为参数传递。 原始邮箱地址 字段。其余流程保持不变,每个附件引用和主体表达式的解析方式都相同。
如果电子邮件没有附件怎么办?
触发器的 仅限附件 是 此过滤器会阻止流程在仅包含邮件正文的电子邮件上触发。如果您也想归档仅包含邮件正文的电子邮件,请将该过滤器设置为“否”,并将“应用到每个”循环包装在“条件:仅当满足特定条件时运行”中。 length(triggerOutputs()?['body/attachments']) 大于零。即使数组中只有一个正文 PDF 文件,合并操作仍然可以正常工作,生成单页存档。
如何在存档的第一页上显示发件人、主题和接收日期?
在步骤 3 之前,添加一个 撰写 带有 HTML 前导符的操作:
<h2>From: @{triggerOutputs()?['body/from']}</h2>
<h2>Subject: @{triggerOutputs()?['body/subject']}</h2>
<p>Received: @{triggerOutputs()?['body/receivedDateTime']}</p>
<hr>
@{triggerOutputs()?['body/body']}
然后将步骤 3 中的“文件内容”指向“撰写”输出。现在,第 1 页包含可搜索的页眉元数据。
这种方法适用于包含内嵌图片的HTML邮件吗?
是的。PDF4me 转换为 PDF 时会渲染带有内联的 HTML。 <img src="cid:..."> 引用和嵌入式 base64 图像。Outlook 的 body/body 包含完整的 HTML 和内联内容,因此渲染后的 PDF 能够保持接收者所见内容的视觉效果。
该流程需要运行多长时间?
单页 DOCX 文件每个附件大约需要 10-15 秒,加上触发和最终上传所需的 5-10 秒。一封典型的包含两个附件的电子邮件从头到尾需要 35-45 秒。Power Automate 的“应用到每个”功能默认按顺序运行,以生成有序输出;如果顺序无关紧要且需要速度,请进行相应设置。 并发控制 在循环设置中设置为 20。
故障排除
添加到数组之一 价值 表达式没有被包装 base64ToBinary(...)每次推送(正文和附件)都需要转换。重新打开两个追加操作,切换到表达式编辑器,并确认表达式是否正确。 base64ToBinary(body('Convert_to_PDF_Body')?['$content']) 和 base64ToBinary(body('Convert_to_PDF')?['$content']) 逐字。
“转换为 PDF 正文”操作未接收到实际的 HTML 代码。请检查触发器的设置。 包含附件 留下了“是”(如果没有它,尸体有时会空着送来),而且 文件内容 决定 triggerOutputs()?['body/body'], 不是 身体/身体预览。
默认值 适用于每个 并行运行,这可能会打乱追加顺序。打开循环的 设置 并设置 并发控制 与……的平行程度 1现在循环按顺序运行,附件按数组顺序放置。
时间戳分辨率为一秒。对于邮件量较大的收件箱,请附加 Internet 邮件 ID 哈希值: concat('merge-', formatDateTime(utcNow(), 'yyyyMMdd-HHmmss'), '-', substring(triggerOutputs()?['body/internetMessageId'], 0, 8), '.pdf')。
后续步骤
同样的七步模式(触发、初始化数组、转换正文、循环转换并追加、合并、最后保存并添加时间戳)适用于任何“将电子邮件及其附件合并到一个 PDF 文件中”的自动化操作。只需执行一次,所有收到的邮件都会自动生成一个可搜索、可排序、可用于审计的存档条目。