# milter

The milter library provides Rust bindings to libmilter, the sendmail mail filter
API.

This library serves the creation of *milters*: mail filtering applications that
can be integrated with MTAs (mail servers) such as [Postfix].

[Postfix]: http://www.postfix.org

## Requirements

This crate requires the milter C library (libmilter) to be available.

☞ *On Debian and Ubuntu, install the package `libmilter-dev`.*

If your distribution does not provide pkg-config metadata for libmilter, try
using the provided `milter.pc` file when executing the build:

```
PKG_CONFIG_PATH=. cargo build
```

The integration tests of this crate require the third-party `miltertest` utility
in order to exercise the test milters. This program can be found among the
OpenDKIM command-line tools.

☞ *On Debian and Ubuntu, install either the `miltertest` or the `opendkim-tools`
package (only required when working on the milter crate itself).*

The minimum supported Rust version is 1.42.0.

## Usage

The main use case of this library is creating milter applications, that is,
executable programs with a `main` function.

Include [libc] in addition to milter in `Cargo.toml`:

```toml
[dependencies]
milter = "0.2"
libc = "0.2"
```

Here’s a simple milter application that logs client IP addresses:

```rust
use milter::{on_connect, Context, Milter, Status};
use std::net::SocketAddr;

#[on_connect(connect_callback)]
fn handle_connect(
    _: Context<()>,
    _: &str,
    socket_addr: Option<SocketAddr>,
) -> Status {
    if let Some(socket_addr) = socket_addr {
        println!("Connect from {}", socket_addr.ip());
    }

    Status::Continue
}

fn main() {
    Milter::new("unix:/run/ipmilter.sock")
        .name("IPMilter")
        .on_connect(connect_callback)
        .run()
        .expect("milter execution failed");
}
```

Refer to the [API documentation] for complete usage instructions.

[libc]: https://crates.io/crates/libc
[API documentation]: https://docs.rs/milter

## Examples

This package includes an example milter `inspect`, which prints all arguments
and macros for each stage, and so is immediately useful as a view into how
milters operate, and what shape the received data has.

Start the `inspect` example by passing a socket spec with an unused port (again,
if your distribution does not provide the requisite pkg-config metadata, you may
need to adjust `PKG_CONFIG_PATH`, see above):

```
cargo run --example inspect inet:3000@localhost
```

After the milter has started, configure the MTA – Postfix – to connect to it.
Add the following parameters to `/etc/postfix/main.cf`, and reload the Postfix
configuration:

```
smtpd_milters = inet:localhost:3000
non_smtpd_milters = $smtpd_milters
```

The `inspect` milter will then print everything it receives from Postfix.

## Licence

Copyright © 2019–2021 David Bürgin

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
