#message-format #email #mime #header #internet #mail-server #codec

bin+lib eml-codec

Email 编码解码器,支持互联网消息格式和 MIME(RFC 822, 5322, 2045, 2046, 2047, 2048, 2049)。

3 个版本

0.1.2 2024年1月25日
0.1.1 2023年7月25日
0.1.0 2023年7月24日

#638解析实现

GPL-3.0-or-later

170KB
4K SLoC

eml-codec

⚠️ 目前这只是一个解码器(即解析器),编码尚未实现。

eml-codecAerogramme 的子项目,Aerogramme 是由非营利组织 Deuxfleurs 开发的分布式加密 IMAP 服务器。它的目的是成为一个瑞士军刀,用于处理电子邮件,无论是构建 IMAP/JMAP 服务器、邮件过滤器(如反垃圾邮件)还是邮件客户端。

示例

let input = br#"Date: 7 Mar 2023 08:00:00 +0200
From: [email protected]
To: [email protected]
Subject: An RFC 822 formatted message
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii

This is the plain text body of the message. Note the blank line
between the header information and the body of the message."#;

let (_, email) = eml_codec::parse_message(input).unwrap();
println!(
    "{} just sent you an email with subject \"{}\"",
    email.imf.from[0].to_string(),
    email.imf.subject.unwrap().to_string(),
);

更多示例请参阅 examples/ 文件夹

关于名称

这个库的目标不是实现特定的 RFC,而是一个瑞士军刀,用于解码和编码通常被认为是电子邮件的内容(通常简称为“eml”),因此得名:eml-codec

目标

  • 可维护性 - 修改代码不会产生回归,并且可以由项目外部的人进行。
  • 兼容性 - 总是尝试解析,不要恐慌或返回错误。
  • 全面性 - 作为编码电子邮件知识(现有 MIME 类型、现有头信息等)的通用项目。
  • 类型安全 - 不要仅操作字符串/字节,而是利用 Rust 类型系统,以便在编译时受益于其安全检查。

有关此库目标的更多信息,请参阅 doc/ 文件夹

缺失/已知错误

当前已知限制/错误

  • 部分传输解码尚未实现
  • 尚未实现国际化头信息(UTF-8)
  • 尚未实现 Resent 头字段
  • Return-Path/Received 头信息可能难以使用,因为它们的顺序很重要,而目前它们在最终数据结构中已丢失。
  • 无效日期的日期时间解析可能返回 None 而不是回退到 bad_body 字段
  • 电子邮件头信息中的注释在解析过程中被删除
  • 不提供对 message/external-body(从本地计算机读取数据)和 message/partial(聚合多个分段的电子邮件)的支持,因为它们似乎已经过时且具有风险。

设计

数据结构的概述(受 UML 类图约定启发)

Diagram of class made on Draw.io

测试策略

目前这个crate对其大多数解析函数进行了单元测试。它还被作为Aerogramme项目的一部分进行测试,Aerogramme是它的父项目,在那里它负责解析电子邮件。在这个项目中,eml-codec的解析能力与Dovecot、Cyrus、Maddy和其他IMAP服务器进行了比较。

计划在大型电子邮件数据集(如Enron、jpbush、邮件列表等)上进行测试,但尚未完成。对该库进行模糊测试也很有趣,可能用于检测由于MIME的无穷递归导致的堆栈溢出等崩溃。

RFC和IANA参考文献

RFC

🚩 # 名称
🟩 822 ARPA互联网文本消息
🟩 2822 互联网消息格式(2001年)
🟩 5322 互联网消息格式(2008年)
🟩 2045 ↳ 多用途互联网邮件扩展(MIME)第一部分:互联网消息体格式
🟩 2046 ↳ 多用途互联网邮件扩展(MIME)第二部分:媒体类型
🟩 2047 ↳ MIME(多用途互联网邮件扩展)第三部分:非ASCII文本消息头扩展
🟩 2048 ↳ 多用途互联网邮件扩展(MIME)第四部分:注册过程
🟩 2049 ↳ 多用途互联网邮件扩展(MIME)第五部分:一致性标准与示例
头部扩展
🔴 2183 ↳ 在互联网消息中通信呈现信息:内容处置头字段
🔴 6532 ↳ 国际化电子邮件头部
🔴 9228 ↳ 送达至电子邮件头部字段
MIME扩展
🔴 1847 ↳ MIME的安全多部分:Multipart/Signed和Multipart/Encrypted
🔴 2387 ↳ MIME Multipart/Related内容类型
🔴 3462 ↳ 报告邮件系统管理消息的Multipart/Report内容类型
🔴 3798 ↳ 消息处置通知
🔴 6838 ↳ 媒体类型规范和注册过程

IANA

名称 描述 注意
媒体类型 注册的媒体类型用于内容类型字段 目前只有MIME RFC中的媒体类型在eml-codec中有专用支持。
字符集 支持用于charset参数的字符集 它们都应该通过encoding_rs crate进行支持

技术前沿/替代方案

以下评估不是客观、中立、无偏见的评估。相反,它试图解释我为什么要编写这个库。如果您发现某些内容过时或客观错误,请随时提交PR或问题进行修复。在任何情况下,我认为eml-codec都不是最好的,它只是解决问题的一种方法,我将其视为建筑中的一块石头。

mail_parsermailparserust-email 是三个手动编写的解析器。这种手动编写的解析器不利于关注点的分离:mail_parsermailparse 包含了数百行代码的庞大函数,其圈复杂度很高。由于这种复杂的逻辑,我过去在调试/修复此类代码时失败了。《code>rust-email 代码更易于阅读,但它的 MIME 部分实现被标记为不稳定。《code>mail_parser 被用于 stalwartlabs/mail-server 的 IMAP/JMAP/SMTP 服务器项目,而 rust-email 被用于基于电子邮件的聊天应用 Deltachat(然而 rust-email 的 MIME 解析未使用,Delta Chat 中重新实现了自定义的 MIME 解析器)。必须注意的是,《code>mail_parser 支持大量的扩展(UTF-8 头部、UTF-7 编码、续行、许多自定义字段等),并且比其他库更好地处理格式不正确的电子邮件。《strong>eml_codec 的目标是要开放贡献并随着时间的推移保持可维护性,这是通过解析器组合模式实现的,该模式鼓励编写小、可重用、可独立测试的函数。

rustyknife 使用与《code>eml_codec 相同的设计模式(解析器组合)和相同的库(《code>nom)。然而,《code>rustyknife 更针对 SMTP 服务器(MTA)而不是 IMAP(MDA)和电子邮件客户端(MUA)。因此,它只支持解析头部,而不是电子邮件的主体。一位熟人警告我,这个库有点慢,可能是因为它在解析电子邮件时进行了一些处理(例如重建和分配字符串)。如果这部分后续没有使用,那么分配/处理就被浪费了。《strong>eml_codec 的目标是尽可能少地进行处理以生成电子邮件的 AST,从而保持解析的高效性,然后在调用相应的函数时按需进行分配/处理。这通常被称为零拷贝。

支持

eml-codecAerogramme 项目 的一部分,通过 NGI Assure 基金获得资助,该基金由 NLnet 建立,并由欧盟委员会下一代互联网计划提供资金支持,在通信网络、内容和技术总司的赞助下,根据资助协议 No 957073。

NLnet logo

许可证

eml-codec 版权 (C) 属于 eml-codec 贡献者

本程序是自由软件:您可以按照自由软件基金会发布的 GNU 通用公共许可证的条款重新分发和/或修改它,许可证版本为 3 或(根据您的选择)任何更高版本。

本程序分发时附带的是希望它可能是有用的,但没有任何保证;甚至没有隐含的适销性保证或适用于特定目的的适用性保证。有关详细信息,请参阅 GNU 通用公共许可证。

您应该已收到一份 GNU 通用公共许可证副本。如果没有,请参阅 http://www.gnu.org/licenses/

依赖关系

~5.5MB
~160K SLoC