#集成测试 #电子邮件 #替换 #sendmail #存储 #命令行

bin+lib trapmail

sendmail的命令行替换工具,用于存储邮件。适用于集成测试。

6个版本 (3个重大更新)

0.4.0 2020年1月15日
0.3.1 2019年12月10日
0.2.1 2019年12月9日
0.1.1 2019年12月9日

#800 in 测试

MIT/Apache

20KB
271

trapmail

trapmail 是一个用于单元和集成测试的 sendmail 替换,它会捕获传入的邮件并将其存储在文件系统中。有关详细信息,请参阅文档


lib.rs:

trapmail:集成测试的 sendmail 替换

trapmail 是一个用于单元和集成测试的 sendmail 替换,它会捕获传入的邮件并将其存储在文件系统中。测试用例可以检查“已发送”的邮件。

用例

trapmail 旨在用于黑盒测试使用系统级 sendmail 实例发送电子邮件的系统。示例

  1. trapmail 已安装,并替换测试系统/容器中的 sendmail,或者测试的应用程序已配置为使用 trapmail 作为其 sendmail 二进制文件。
  2. 一个集成测试(用 Rust 编写)触发各种进程,导致应用程序发送邮件,这些邮件被收集在 TRAPMAIL_STORE 中。
  3. 通过访问 TRAPMAIL_STOREtrapmail 库可以在集成测试中使用,以检查邮件是否按预期排队。

命令行界面

trapmail 的命令行界面旨在模仿原始 sendmail 参数,这些参数也通常由其他 MTA(如 Exim 或 Postfix)实现。

trapmail 收到一条消息时,它会将消息以及元数据存储在一个名为 TRAPMAIL_STORE 环境变量的目录中的 JSON 文件中,如果未找到则回退到 /tmp。文件命名为 trapmail_PPID_PID_TIMESTAMP.json,其中 PPID 是父进程的 PID,PID 是调用时 trapmail 的 PID,TIMESTAMP 是微秒级的精确时间戳。

命令行选项

目前,trapmail 并不完全“支持”与 sendmail 相同的所有命令行选项(所有选项都将被忽略,但会记录日志)。如果您遇到因不支持的选项引起的问题,请随时提交 PR 以添加它。

示例

$ trapmail --debug -i -t foo@bar
To: Santa Clause <[email protected]>
From: Marc <[email protected]>
Subject: Please remove me from the naughty list.

Example body.
^D
Mail written to "/tmp/trapmail_1575911147313470_5913_6299.json"

生成的邮件是(稍微可读的)JSON,但也可以使用 cli 工具导出

$ trapmail --dump /tmp/trapmail_1575911147313470_5913_6299.json
Mail sent on 2019-12-09 17:05:47.000313 UTC from PID 6299 (PPID 5913).
CliOptions {
    debug: true,
    ignore_dots: true,
    inline_recipients: true,
    addresses: [
        "foo@bar",
    ],
    dump: None,
}
To: Santa Claus <[email protected]>
From: Marc <[email protected]>
Subject: Please remove me from the naughty list.

Example body.

并发

虽然 trapmail 通过其命名方案避免了不同进程存储消息之间的冲突,但重要的是要记住,它无法访问测试本身的数据(PPID 来自测试应用的 PID,而不是测试二进制文件)。

提供不同的 TRAPMAIL_STORE 目标可以允许对数据进行命名空间划分,但在封闭系统中可能无法始终确保每个测试都设置了此变量。

API

trapmail 包包含一个命令行应用程序以及一个库。该库可以在测试和应用程序中使用,以访问 trapmail 编写的所有数据。

读取当前 trapmail 文件夹内容的最小示例

use trapmail::MailStore;

// Load mail from the default mail directory.
let store = MailStore::new();

for load_result in store.iter_mails().expect("could not open mail store") {
    let mail = load_result.expect("could not load mail from file");
    println!("{}", mail);
}

依赖项

~6.5–9MB
~157K SLoC