[][src]Crate milter_callback

Procedural macros that generate C callback functions for use in milter implementation.

The attribute macros in this crate facilitate the creation of FFI callback functions that are required for the configuration of a Milter. The attribute macros are used to annotate ordinary Rust functions as milter callbacks. A C function is then generated that delegates to the Rust callback, safely, and taking care of conversion between Rust/C types.

Callback functions serve the purpose of event handlers (hence the nomenclature on_*) for the various ‘events’ that happen during an SMTP conversation. For each of the stages in the milter protocol there is a corresponding attribute macro.

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 acceptable.

Raw string inputs

By default, callbacks receive string inputs of type &str, that is, UTF-8 strings. Where UTF-8 encoding is not desired, it is possible to substitute the C string type &CStr for &str in your handler function signature in order to receive the raw bytes instead.

Contrast the following example with the one shown at on_header.

use std::ffi::CStr;

#[on_header(header_callback)]
fn handle_header(context: Context<()>, name: &CStr, value: &CStr) -> Status {
    //                                       ^^^^^         ^^^^^
    Status::Continue
}

This feature is supported wherever &str appears in callback function arguments.

Callback results

The return type of a callback function may be wrapped in a milter::Result where desired. This is a convenience: as most context API methods return milter::Results these can then be unwrapped with the ? operator.

Compare the following example with the one shown at on_eom. This code fragment also demonstrates the use of the ? operator enabled by choosing this return type.

#[on_eom(eom_callback)]
fn handle_eom(context: Context<()>) -> milter::Result<Status> {
    //                                 ^^^^^^^^^^^^^^^^^^^^^^
    if let Some(version) = context.api.macro_value("v")? {
        println!("{}", version);
    }

    Ok(Status::Continue)
}

This feature is supported on all callback functions.

Failure modes

An Err result returned from a callback leads to a temporary failure (Status::Tempfail) response being returned to the MTA. The milter then continues to handle requests normally.

Panicking, on the other hand, leads to immediate shutdown of the milter. All stages switch to returning a failure response and no longer execute the handler functions (however, currently executing callback handlers are allowed to finish). The milter library worker processes are terminated and the currently blocked invocation of Milter::run returns. Cleanup logic in the close or other stages is not executed.

The principle behind the panicking behaviour is, as elsewhere, exit as quickly as possible, within the constraints posed by the milter library and the FFI interface.

The above failure modes are provided as a convenience. Use explicit error handling if they don’t satisfy your requirements.

Attribute Macros

on_abort

Generates a callback function of type AbortCallback that delegates to the annotated function.

on_body

Generates a callback function of type BodyCallback that delegates to the annotated function.

on_close

Generates a callback function of type CloseCallback that delegates to the annotated function.

on_connect

Generates a callback function of type ConnectCallback that delegates to the annotated function.

on_data

Generates a callback function of type DataCallback that delegates to the annotated function.

on_eoh

Generates a callback function of type EohCallback that delegates to the annotated function.

on_eom

Generates a callback function of type EomCallback that delegates to the annotated function.

on_header

Generates a callback function of type HeaderCallback that delegates to the annotated function.

on_helo

Generates a callback function of type HeloCallback that delegates to the annotated function.

on_mail

Generates a callback function of type MailCallback that delegates to the annotated function.

on_negotiate

Generates a callback function of type NegotiateCallback that delegates to the annotated function.

on_rcpt

Generates a callback function of type RcptCallback that delegates to the annotated function.

on_unknown

Generates a callback function of type UnknownCallback that delegates to the annotated function.