This process consists of three parts: message data is read by a handler from the standard input, processed by the handler, and the result of the operation is written to the standard output.

Message Input

The message is fed to the handler on the standard input.

The input contains the message headers, an empty line, and the message body. The message ends when end-of-stream is encountered. The envelope information is not included here.

Lines are separated by bare LF in the message.

Handler Output

The handler is expected to produce the following output on standard error:

  • PASS

    The message should be passed further. The handler should write the message, possibly modified, on the standard output.

  • STOP

    The message should not be passed further and this is not an error. This should be used when the handler implements its own custom delivery instead of the delivery provided by the MTA. Subsequent handlers won’t be called.

  • DEFER

    The message should not be passed further. A temporary error condition should be indicated. Subsequent handlers won’t be called.

  • REJECT

    The message should not be passed further. A permanent error condition should be indicated. Subsequent handlers won’t be called.

  • LOG text

    The line of text should be treated as a warning or error message and added to the appropriate log.

  • SKIP

    The handler should not process and pass the message to the handler’s output. The message should be passed further without any modifications.

Each line of output on the standard error should be terminated with LF. After the first PASS, STOP, DEFER, REJECT, or SKIP line, further output is not accepted, so any LOG lines must precede the above.

The exit code from the handler should be 0 on PASS or STOP and not 0 in other cases.

Message Output

The handler should only write to its standard output after writing PASS or REJECT on the standard error.

For PASS, the output should be a message in the same format as found on input.

Exit Code

The exit code from the handler should be 0 on PASS or STOP and not 0 in other cases.

Invocation Context

The handler will be invoked with the rights defined for its owner, regardless of those rights with which MTA is running. If specific rights for file system access are required, the handler should be given the SETUID bit.

The current working directory is undefined.

Most environment variables are removed, only the essential ones are left: PATH and LANG. The latter will be set to the value C.