⌘K 切换工具
EMAIL AUTH

EML邮件查看器

查看和解析EML邮件文件内容。

local
eml-viewer
§01 关于此工具

概述

.eml 文件保存的是邮件在传输途中的原样:先是邮件头,一个空行,然后是正文。邮件 客户端把其中绝大部分藏起来了——平时这没什么问题,直到你需要确认这封邮件实际装了 什么:一个客户端不显示的头字段、一个到达时已成乱码的主题,或者一封渲染异常的邮件 究竟是什么结构。

这个查看器在头与正文的分界处切开文件,把折行的头字段还原成完整值,按声明的字符集 解码 MIME encoded-word,然后同时给出关键字段和原始正文。

使用方法

  1. 把邮件另存为 .eml,或者复制它的原始源码。Thunderbird 里直接把邮件拖到桌面; Apple Mail 是 显示 → 邮件 → 原始源码;Outlook 用 另存为 → Outlook 邮件 格式 后导出,或者 文件 → 另存为 → 文本
  2. 粘贴内容。头字段在前,一个空行,然后是正文——整个格式就这么简单。
  3. 先读摘要字段,再扫一遍原始正文,看清结构。

encoded-word 与主题乱码的成因

按规范,邮件头只允许 ASCII。非 ASCII 文本要以 encoded-word 的形式携带: =?charset?encoding?data?=,其中 encoding 取 B(base64)或 Q (quoted-printable 的一个变体)。

中间那段字符集才是关键,而多数工具恰恰在这里出错。日文主题至今仍普遍以 ISO-2022-JP 发送——那是一种早于 Unicode 的转义序列编码,在若干邮件客户端里依然 是默认值。西欧的邮件也还在用 ISO-8859-1windows-1252。一个默认按 UTF-8 解码的实现会把上面这些统统变成乱码,而结果看上去像文件损坏,不像一次解码失误。

本工具读取声明的字符集并据此解码,于是 =?ISO-2022-JP?B?…?= 会还原成可读的日文, =?windows-1252?Q?it=92s?= 会还原成带正确排版撇号的 it's。字符集未知或拼错时 回退到 UTF-8,而不是直接失败。

头字段的折行

过长的头字段会被拆成多行,续行以空白字符开头。一个 Received 头,或者一个包含 二十个地址的 To 列表,在文件里会横跨很多行;这种换行本身没有含义——它是传输层的 规则,不是值的一部分。

解析之前会先把折行还原,因此折过行的值会被当成一整个字符串读取。当你自己直接读 原始文本时这点值得记住:用 grep 找某个头字段的值,凡是碰巧换了行的都会漏掉。

正文为什么保持原样

正文严格按它在文件里的样子展示,这是刻意的。

现实中的邮件大多是 multipart/alternative(同一内容的纯文本版本与 HTML 版本), 或者 multipart/mixed(内容加附件)。每个部分都有自己的 Content-Type、自己的 字符集和自己的 Content-Transfer-Encoding,各部分之间由顶层头字段声明的 boundary 字符串分隔。

把其中某一个解码后的部分当作「这封邮件」展示,就会把这套结构藏起来——而结构通常 正是你要看的东西:客户端渲染的是哪一部分、纯文本版与 HTML 版是否一致、附件是否在 你以为的位置。所以原始正文就保持原始。

代价是:quoted-printable 的正文里 = 会显示成 =3D,软换行显示为行尾的 =, base64 的部分就显示成 base64。如果你确实要解开其中某一段,把那一部分复制出来交给 Base64 解码URL / 百分号解码 处理。

客户端不会给你看的头字段

摘要区列出的是你通常想要的七个字段。其余部分都在你粘贴的原始文本里,其中有好几个 能回答客户端刻意隐藏的问题。

  • Return-Path 是信封发件人——退信寄回的地方。它由发送服务器设置,经常与人眼 看到的 From: 头不一致。SPF 通过而 DMARC 失败时,通常就是这处不一致造成的。
  • List-UnsubscribeList-Unsubscribe-Post 决定 Gmail 里那个一键退订 按钮是否出现。批量邮件缺了它们,被标为垃圾邮件的概率明显更高。
  • Auto-Submitted 标记机器生成的邮件。自动邮件缺这个头,就会触发外出自动回复 和邮件循环。
  • In-Reply-ToReferences 是客户端组织会话线程的依据。一封回复被显示 成新会话,就是少了其中之一。
  • Content-LanguageAccept-Language 解释了多语言发送方为什么挑了这个 版本。
  • X-* 头字段 是发送侧基础设施自行添加的东西。垃圾邮件评分、投放活动 id、 内部队列名都出现在这里,它们也是判定「究竟哪套系统发出了这封邮件」的最快途径。

示例

  • 主题变成一串乱码。 把邮件粘进来。如果主题在这里可读,说明发送方没问题,是 接收端的客户端把字符集处理错了。
  • 「这封邮件在 Outlook 里显示得不一样。」 去看 boundary 结构。这类反馈绝大多数 都能用一个两部分内容互相不一致的 multipart/alternative 解释掉。
  • 某个头字段找不到。 客户端只显示经过挑选的一小部分。List-UnsubscribeAuto-SubmittedX-Failed-Recipients 之类即使界面上一处都不显示,也确实在文件 里躺着。
  • 确认自己到底发出了什么。 从自己的已发送文件夹里存一封回来读。编码上的意外, 在原始形态下要好发现得多。

说明

头与正文的分界就是第一个空行,这是格式规定的。完全没有空行的文件会被当成只有头 字段来处理——当有人只粘贴了头部区块时,这正是你想要的行为。

这里不做任何校验。一封 Date 格式错误、缺少 Message-ID、或者 boundary 在正文里 从未出现过的 .eml,都会被原样显示,因为目的是看文件里有什么,而不是看它本应有 什么。

想看投递路径、逐跳延迟以及 SPF、DKIM、DMARC 的结论,用 邮件头解析。它读的是同一批头字段,但带着另一个问题。

FAQ
报文会被上传到什么地方吗?
不会。文本的切分和解析都在页面内完成,没有任何网络请求。这一点在这里格外重要:一封保存下来的邮件里带着收件人地址、内部主机名,往往还有整段往来对话。
为什么这里的主题读得出来,别的工具却显示成 =?UTF-8?B?…?
那是 RFC 2047 的 encoded-word——邮件头承载非 ASCII 文本时用的 MIME 编码。这里按邮件头自己声明的字符集解码,所以 ISO-2022-JP、Shift_JIS、EUC-JP 以及 ISO-8859 系列都会还原成可读文本,而不是乱码。
正文里满屏都是 =3D 和 =C3=A9,这是怎么回事?
那是 quoted-printable,正文是按它在文件里的原样展示的。这里不对正文解码,因为真实邮件通常是 multipart——若干个部分各自带着不同的编码——把其中一个悄悄拿出来当成「这封邮件」展示,只会误导人。
附件在哪里?
作为 MIME 部分能在原始正文里看到,但不会被提取出来。这是一个读取邮件结构和头字段的工具,不是解包器。从一封不可信的 .eml 里提取并提供附件下载,是另一个工具、另一套风险。
摘要区会列出哪些头字段?
From、To、Cc、Subject、Date、Reply-To 和 Message-ID。其余全都留在你粘贴的原始文本里。想看投递路径和认证结论,请改用邮件头解析。