milter-callback 0.1.2

Attribute macros for milter callback generation
Documentation

Procedural macros to generate C callback functions and a thin wrapping layer.

These attribute macros are used to annotate callback functions in milter. These callback functions serve the purpose of event handlers (hence the nomenclature on_*) for the various ‘events’ that happen during an SMTP conversation and are thus exposed in the milter protocol.

Usage

This crate is a dependency of the milter crate, which re-exports all macros under its namespace. Thus you should not need to use this crate directly.

Note that with Rust 2018 there are two ways of importing procedural macros. Nowadays, macros can be imported like other symbols:

use milter::{on_connect, on_close, Milter, Status};

That does require you to list all macros in the use statement, though. The older syntax with extern crate lets you import all macros without listing them explicitly:

#[macro_use] extern crate milter;

use milter::{Milter, Status};

Both notations are fine.

Callback results

The result type may be wrapped in a milter::Result where desired. This is a convenience as most Context methods return milter::Results these can then be propagated with the ? operator.

For example, the end-of-message handler may return plain Status:

# #[macro_use] extern crate milter_callback;
# use milter::{ActionContext, Status};
#[on_eom(eom_callback)]
fn handle_eom(context: ActionContext<()>) -> Status {
Status::Continue
}

Or it may return milter::Result<Status>. The example shows use of the ? operator enabled by choosing this return type.

# #[macro_use] extern crate milter_callback;
# use milter::{ActionContext, Status};
#[on_eom(eom_callback)]
fn handle_eom(context: ActionContext<()>) -> milter::Result<Status> {
if let Some(version) = context.macro_value("v")? {
println!("{}", version);
}

Ok(Status::Continue)
}

This feature is supported on all the callback functions.

Errors

An error result returned from a callback leads to a Status::Tempfail response returned to the MTA. The milter will continue processing.

Panicking leads to shutdown of the milter. That is, Milter::run returns. It could then be restarted by invoking Milter::run again. However, restarting is potentially hazardous as panic exits without going through potential cleanup paths in close or abort. That is, there is a possibility of memory leakage.

Returning an error result does not have this problem. Returning an error leads to tempfail and then the ordinary cleanup path on connection close.