如何解析EML(邮件)格式的文件以及一款小巧的EML邮件阅读工具

2023-11-09

在理解EML格式的时候,先回顾一下历史,这样有助于理解邮件的格式,比如邮件传输时为何会有多种编码方式。此外,理解EML格式也有助于理解HTTP协议。

历史溯源

由于历史原因,我们目前看到的大部分的网络协议都是基于ASCII码这种纯文本方式,也就是基于字符串的命令行方式,比如HTTP、FTP、POP3、SMTP、TELNET等。
 
早期操作系统比如Unix或DOS没有图形界面,用户与电脑之间只能通过控制台进行交互,也就是通过键盘将命令(或请求)输入到电脑,当用户回车换行(\r\n)时,表示命令输入完毕。如果存在网络通信,则该命令包括用户敲击的回车换行会一并发送到服务器端,服务器端接收数据时,就会以回车换行来界定一条完整的命令是否获取完毕,否则会继续等待直到接收到"\r\n"或超时,当请求接收完毕后,服务端会执行该请求并将响应结果返回给客户端。
 
理解这一点非常重要,这就是为什么很多网络应用层协议都是以"\r\n"来作为结束标记。对于多行请求时,通常以两个连续的回车换行表示请求结束,也就是"\r\n\r\n",直观的用肉眼观察就是存在一个空行。
比如HTTP协议,与主机建立连接后,输入"GET / HTTP/1.1\r\n\r\n"即可获取网站的主页。

 
回到Email协议(SMTP和POP3),早期的电子邮件只支持ASCII码这种纯文本传输方式,但随着全世界人民对物质文化生活的不断向往,这种落后的传输方式,已经无法满足世界人民对美好生活的追求,比如图像、视频、音频、Office文件如何在邮件中展现?不同国家(非英语国家)字符集该如何传输和展现?
换句话说,就是这种非ASCII的二进制富文本,该如何传输和呈现?

MIME的诞生

此时MIME标准诞生了,MIME的出现更多的是一种向下兼容的无奈,而不是革命。通过对二进制数据或非ASCII码数据进行base64或quoted-printable编码,来实现纯ASCII码的传输。显然这种方式会让你的邮件体变大,传输效率下降。尤其附件很多时,通过MIME的boundary来解析邮件的附件也是一笔额外的负担。

同时MIME的标准也被HTTP协议所采用,我们可以通过content-type字段指定传输的内容是什么类型,通过MIME的boundary来对Form-Data数据进行扩展,让我们在POST数据时也能够在“表格”数据中插入文件,从而达到上传文件的效果。
 
下面是一个EML格式的文件截图,该截图是一个邮件头,该邮件头包含几个重要字段,Subject(主题),From(发件人)To(接收人),Cc(抄送人),Date(发送日期)。
其中一个最重要的字段就是Content-Type。只有解析了Content-type字段我们才能准确的将邮件体给解析并展现出来。
 
在这里插入图片描述

通过上图我们可以观察到该邮件的内容是一个混合类型,由多个部分组成,Content-type字段中的boundary被用来分割不同的部分。下图显示的是一个邮件的附件文件,该文件类型为pdf。
 
在这里插入图片描述

boundary的前缀加上"- -"表示新的邮件内容的开始,紧接着为几行MIME头,仔细观察MIME头则会发现,这些字段其实和HTTP协议的头的字段是相同的。空行后则是具体的邮件内容,这些邮件内容的传输编码方式有两种:一种是base64,一种是quoted-printale,当然也可能是未编码。通常情况下,采用quoted-printable方式对HTML(邮件正文)进行编码,而对于附件文件(比如二进制文件),则采用base64进行编码。
邮件的正文可能有两个:一个是HTML格式,一个是Plain格式。为什么会有两个格式的正文?其实这两个格式展现出来的内容都是一样的,这样做的目的是为了客户端的兼容,早期的的邮件客户端可能无法显示HTML格式,或者对HTML格式的兼容性不是很好,当然喽这也是历史原因造成的。现在的邮件客户端都能显示HTML的正文了。
当邮件结束时,是以"- -“+boundary+”- -“来标记,也就是给boundary加上前缀”- -“和后缀”- -“。
通过对MIME格式的分析我们可以看到解析Content-type字段很重要,通过提取boundary并循环查找,就可以解析出不同的邮件体,从而将一封EML格式的电子邮件展现出来。
最后注意一点: MIME头中字符串采用特有的简洁的编码方式,将字符集和编码方式集成到了一起,以”=?“开始,以”?=“结束。”=?“后为字符集,紧接着”?"后表示编码方式。B(b)为base64编码,Q(q)为quoted-printable编码。如下图:
在这里插入图片描述

 
附:一款小巧的EML邮件阅读工具(不到300K)
 
在这里插入图片描述
在这里插入图片描述
 
EmlReader是一个客户端程序,比这更轻量级的是下面的EmlParse工具,不到150K,可批量解析eml格式邮件,并提取邮件中的正文和附件到指定目录中:
EmlParse:一款超轻量级的批量解析EML格式电子邮件的工具

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何解析EML(邮件)格式的文件以及一款小巧的EML邮件阅读工具 的相关文章

  • Non-Authoritative-Reason 标头字段 [HTTP]

    当我有响应标头时 我很难找出它的含义Non Authoritative Reason HSTS 我搜索了很多 但只是想出了一些关于 HSTS 从 HTTP 重定向到 HTTPS 的解释 有人能帮我吗 顺便说一句 我正在使用 Chrome T
  • AWS ALB 截断 HTTP 响应

    我有一个带有目标组的 ALB 和运行 PHP API 的 ECS 集群 我正在尝试查询 API 以获得 CSV 响应 但如果请求通过 ALB 我会得到被截断的结果 当我通过 SSH 连接到运行集群的 EC2 实例并尝试手动运行curl 通过
  • 为什么使用 HTTP 动词?

    因为动词的目标是像 server domain getallrecords 或 server domain delete1record 或类似的 URL 而getallrecords delete1record都是专门为特定目的而设计的 为
  • 减少1000张图片的HTTP请求?

    我知道这个问题可能听起来有点疯狂 但我想也许有人会想出一个聪明的主意 假设您在一个 HTML 页面上有 1000 个缩略图 图像大小约为5 10 kb 有没有办法在单个请求中加载所有图像 以某种方式将所有图像压缩到一个文件中 或者您对该主题
  • 使用 Google OAuth2.0 时出现错误请求

    从 Salesforce 中使用 Google OAuth 时 我收到 400 错误请求 以下错误与无效的 grant type 有关 但如果您查看 使用刷新令牌 下的文档 您会发现它是正确的 https developers google
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • Vertx HttpClient getNow 不工作

    我的 vertx HttpClient 有问题 下面的代码显示使用 vertx 和纯 java 测试 GET Vertx vertx Vertx vertx HttpClientOptions options new HttpClientO
  • POST 后使用 303 重定向以避免“网页已过期”:如果字节数超过 GET 请求可以处理的字节数,它会工作吗?

    我想解决 网页已过期 问题 首先 我刚刚将 POST 更改为 GET 但这导致出现错误 我的 HTTP 请求超出了 GET 的最大大小 所以 现在我想尝试下面链接中描述的技术 帖子 303 重定向 但是我仍然会遇到相同的大小限制问题吗 对
  • 我应该使用多个 HttpClient 来进行批量异步 GET 请求吗?

    我有一个场景 我需要在尽可能短的时间内发出大量 GET 请求 想想大约 1000 个 我知道通常最好保留一个客户端并尽可能重用它 Create Single HTTP Client HttpClient client new HttpCli
  • 如何增加asp classic的请求接受限制

    我从java小程序向asp classic发送post请求 我在此请求中发送非常大的数据 即 csv 数据 当此请求中的字符数增加并超过 138000 时 asp 不接受该请求 java 小程序给出 500 错误 所以有人可以告诉我如何才能
  • 如何使用 Emacs 通过 HTTP 打开远程文件?

    大多数开源软件都通过某些 HTTP 服务公开其代码 我想从 Emacs 打开并浏览此类代码 但 AFAICS trapmp 只允许ssh and ftp 因此 我的第一个问题是如何打开 HTTP URL 以便在 Emacs 中进行读取 然后
  • iOS 上的多个 HTTP 请求与单个 TCP 连接

    我正在开发一个 iPhone 应用程序 它使用我控制的基于 Web 的 API 连接到持续打开的 TCP 端口并通过 TCP API 发出请求 或者为我想要获取的所有数据发出新的 HTTP 请求 会更快或更高效吗 我认为差异可以忽略不计 但
  • 在读取正文之前拒绝 HTTP 请求

    我正在开发一个网站 用户需要上传一些非常大的文件 该网站是用 PHP 编写的 在某些情况下 我想根据标头拒绝文件 理想情况下 我想在收到标头后立即拒绝请求 而不读取正文 如果标头足以表明该文件应被拒绝 则没有理由读取 200M 的文件 此外
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • python 2.7 中的 HTTP 2 请求

    在 python 中向 HTTP 1 和 HTTP 2 发出请求有什么区别吗 我可以像这样在 python 中进行 HTTP 1 x 调用 url http someURL values param1 key param2 key2 dat
  • HTTP Header Key 可以重复吗?

    在 JAVA HttpUrlConnection 中 请求 Header 设置的主要逻辑代码如下 public synchronized void set String k String v for int i nkeys i gt 0 i
  • 我可以使用 HTTP 范围标头“有意”加载部分文件吗?

    我正在研究 HTTP 范围标头 specs http www w3 org Protocols rfc2616 rfc2616 sec14 html sec14 16 据我了解 我可以设置文件的字节范围ala 0 199 2000 200
  • Django HTTPS 和 HTTP 会话

    我使用 Django 1 1 1 和 ssl 重定向中间件 通过 HTTPS 创建的会话数据 身份验证等 在站点的 HTTP 部分中不可用 无需将整个站点设置为 HTTPS 即可使其可用的最佳方法是什么 这是设计使然 您无法轻易更改 当通过
  • 自定义 HTTP 标头:命名约定

    我们的一些用户要求我们将与其帐户相关的数据包含在HTTP 标头我们向他们发送的请求 甚至是他们从我们的 API 获得的响应 添加自定义 HTTP 标头的一般约定是什么 naming format etc 另外 请随意发布您在网络上偶然发现的
  • Apache 未发送 304 响应(如果启用了 mod_deflate 和 AddOutputFilterByType)

    我在 Apache httpd conf 中添加了以下行 AddOutputFilterByType DEFLATE text html text css application javascript application x javas

随机推荐

  • Spark数据分析之pyspark

    Spark数据分析之pyspark 一 大数据简史 从hadoop到Spark 1 hadoop的出现 1 问题 1990年 电商爆发以及机器产生了大量数据 单一的系统无法承担 2 办法 为了解决 1 的问题许多公司 尤其是大公司领导了普通
  • 【VUE】拖动侧边栏以便自由调整左右两侧的宽度

    效果 1 拖动前 2 拖动后 主要代码
  • Python 爬虫爬取豆瓣读书小说类前十页标签

    呜呜呜 小白的爬虫之路 留个记录 一 导入库 import requests from bs4 import BeautifulSoup import sqlite3 二 获取豆瓣读书小说类1 10页网址 获取分页的地址 root url
  • 关于Jquery中ajax方法data参数用法的总结

    data 发送到服务器的数据 将自动转换为请求字符串格式 GET 请求中将附加在 URL 后 查看 processData 选项说明以禁止此自动转换 必须为 Key Value 格式 如果为数组 jQuery 将自动为不同值对应同一个名称
  • 高级API(UDP连接&Map集合&Collection集合)

    UDP协议 DatagramSocket 该对象可以代表接收端也可以代表发送端 DatagramPacket 数据打包对象 数据报对象 将发送的内容通过该对象进行打包 在通过指定的方法将该对象进行传输 1 通过DatagramSocket建
  • STM32学习笔记—I2C通信

    1 I2C介绍 2 I2C通讯过程介绍 3 函数配置 4 代码 1 I2C介绍 i2c总线是nxp公司 philp公司 开发的两线式串行总线 用于连接微控制器及外围设备 它是由数据线SDA和时钟线SCL构成 我们平常使用还会加上一个供电即v
  • Centos下安装gitolite+git

    一直以来我都是用SVN的 但最近做迭代开发 多分支时 发现SVN使用起来极不方便 因此打算换成git做源码管理 git的理论以及特性本文就不做讲解了 本主主要讲解怎么安装 配置git 以及git权限管理服务gitolite 组网结构 git
  • 计算机视觉基础(八)—— LBP特征描述算子之人脸检测

    1 简介 LBP指局部二值模式 Local Binary Pattern 是一种用来描述图像局部特征的算子 具有灰度不变性和旋转不变性等显著优点 LBP常应用于人脸识别和目标检测中 在OpenCV中有使用LBP特征进行人脸识别的接口 也有用
  • python opencv imread()中文路径返回为空None的解决办法 (imdecode函数的使用)

    本质原因并非网上某些地方说的是中文编码UNICODE UTF 8之类的问题 其实是python版opencv不接受NON ASCII的中文路径 为了使用中文路径 可以借助一些其他的库 本文首先介绍一种通过numpy库 毕竟这个是python
  • 编程问题(持续记录)

    问题记录 一 vue问题记录 1 vue elementui项目 build后在ie下报 Promise 未定义错误 2 elementui ie下icon不显示 3 npm run dev 时 报babel runtime core js
  • 两种方法将oracle数据库中的一张表的数据导入到另外一个oracle数据库中

    oracle数据库实现一张表的数据导入到另外一个数据库的表中的方法有很多 在这介绍两个 第一种 把oracle查询的数据导出为sql文件 执行sql文件里的insert语句 如下 第一步 导出sql文件 第二步 用PL Sql Develo
  • 快速幂理解

    2 9 gt gt 2 2 8 2 2 8 gt gt 2 4 4 2 4 4 gt gt 2 16 2 2 16 2 gt gt 2 256 1 思想 通过降阶的方式每次将幂除 2 将底数每次乘方 因为幂不能为奇数 所以如果幂为奇数必须处
  • 数据筛选特征方法-方差法

    在数理统计中 方差是测算随机变量离散趋势最重要 最常用的指标 方差是各变量值与其均值离差平方的平均数 它是测算数值型数据离散程度的最重要的方法 当数据分布比较集中时 各个数据与平均数的差的平方和较小 当数据分布比较分散 即数据在平均数附近波
  • 正确理解层次方框图

    正确的层次方框图示例 图片来源 https blog csdn net qq 15037231 article details 60467793 注意 在网上搜索层次方框图会出现很多类似的图 但很多都是错的 层次方框图用树形结构的一系列多层
  • 重定向与请求转发

    分享一下在华清远见学习的知识点 重定向与请求转发也是面试中容易问到的问题 目录 一 重定向 二 请求转发 三 请求转发与重定向数据传递 四 请求转发与重定向的区别 总结 一 重定向 重定向是指由原请求地址重新定位到某个新地址 原有的 req
  • Java培训班学费一般多少?Java自学成功率是多少?

    Java培训班学费一般多少呢 Java自学成功率是多少 很多想学Java的新手对培训学费很是好奇 同时也想知道自学成功率 毕竟能不花钱就能学好的话 没必要花巨款学习 关于Java培训费用与自学成功率的答案请往下看 Java培训班学费一般多少
  • 鼠标移入背景图片放大(还原)

  • maven 配置 Tomcat7 插件和启动

    如果想使用 在 maven中使用 Tomcat7 来启动的话 可以这样配置
  • ORBSLAM2计算描述子距离——C++ 位操作得到二进制32位int值中有多少个1

    看ORBSLAM2时算描述子之间的距离时看到的神奇的位操作 特此记录一哈 unsigned int v pa pb v v v gt gt 1 0x55555555 v v 0x33333333 v gt gt 2 0x33333333 d
  • 如何解析EML(邮件)格式的文件以及一款小巧的EML邮件阅读工具

    在理解EML格式的时候 先回顾一下历史 这样有助于理解邮件的格式 比如邮件传输时为何会有多种编码方式 此外 理解EML格式也有助于理解HTTP协议 历史溯源 由于历史原因 我们目前看到的大部分的网络协议都是基于ASCII码这种纯文本方式 也