12 个版本

0.3.0 2024年3月4日
0.3.0-alpha.12024年1月12日
0.2.0 2023年1月9日
0.2.0-alpha.12022年10月31日
0.0.2 2021年11月15日

#137 in 电子邮件

Download history 210/week @ 2024-03-11 37/week @ 2024-03-18 74/week @ 2024-03-25 137/week @ 2024-04-01 135/week @ 2024-04-08 45/week @ 2024-04-15 49/week @ 2024-04-22 5/week @ 2024-04-29 65/week @ 2024-05-06 22/week @ 2024-05-13 32/week @ 2024-05-20 41/week @ 2024-05-27 93/week @ 2024-06-03 52/week @ 2024-06-10 41/week @ 2024-06-17 24/week @ 2024-06-24

每月212次下载
4 crates 中使用

GPL-3.0-or-later

150KB
3K SLoC

indymilter

为 Rust 编写的独立异步 milter 库

  • 纯、安全 Rust 库,用于编写 milter
  • 基于 Tokio 的异步实现
  • 不依赖于 libmilter C 库
  • 完全兼容现有的 milter 感知 MTA

indymilter 库为在纯异步 Rust 中创建 milter 提供了功能。一个 milter 是一种可以与 MTA(邮件服务器)如 Postfix 集成的邮件过滤应用程序。

indymilter 与类似库相比的主要优势是它全心全意采用异步范式,这可以实现几乎无限的并发性。任意数量的 MTA 连接可以由少量线程并发处理。内部,该库基于 Tokio

此库是 sendmail milter 协议的 milter 方面的实现。作为这样的,它取代了与 sendmail 一起分发的 libmilter C 库。它不依赖于该库,但是一个独立、纯、安全的(没有 unsafe)Rust 产品。

由于 libmilter 是古老的 milter 协议的标准实现,indymilter 准确地模仿了其行为。为了确保与现有 MTA 的完美兼容性,indymilter 旨在实现 bug-for-bug 的兼容性,而不是对协议进行花哨的“现代”重新构想。有关 indymilter 源代码的问题可以通过查看 libmilter 源代码来回答。

使用方法

要使用 indymilter,将其作为依赖项添加到 Cargo.toml。有关进一步的使用信息,请参阅以下位置

有关协议设计和详细 API 功能的概述,请参阅原始 sendmail milter API 文档。此文档可以在您的发行版的 sendmail 软件包中找到(例如,在 Debian 和 Ubuntu 上为 /usr/share/doc/sendmail-doc/libmilter/html/index.html),或直接在 sendmail 源代码的 tarball 中找到 ftp://ftp.sendmail.org/pub/sendmail

以上很重要:虽然 indymilter 提供了与 libmilter 类似的 API,但它并没有复制整个 API 的文档。有关详细信息,您需要检查 sendmail 文档。

示例

这里是一个简单但完整的milter程序,用于记录客户端IP地址。

use indymilter::{Callbacks, Context, SocketInfo, Status};
use tokio::{net::TcpListener, signal};

#[tokio::main]
async fn main() {
    let listener = TcpListener::bind("127.0.0.1:3000")
        .await
        .expect("cannot open milter socket");

    let callbacks = Callbacks::new()
        .on_connect(|context, _, socket_info| {
            Box::pin(handle_connect(context, socket_info))
        });

    let config = Default::default();

    indymilter::run(listener, callbacks, config, signal::ctrl_c())
        .await
        .expect("milter execution failed");
}

async fn handle_connect(
    _: &mut Context<()>,
    socket_info: SocketInfo,
) -> Status {
    if let SocketInfo::Inet(addr) = socket_info {
        println!("connect from {}", addr.ip());
    }

    Status::Continue
}

上述milter将尝试在端口3000上打开TCP套接字,然后处理传入的MTA连接,直到通过Control-C关闭。

许可证

版权所有 © 2021–2024 David Bürgin

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

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

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

依赖项

~3–13MB
~128K SLoC