NAME
mimedefang-protocol - Conventions used by mimedefang(8) to communicate
with filter programs.
DESCRIPTION
mimedefang(8) and mimedefang-multiplexor(8) provide a simplified
mechanism for hooking scripts and programs into Sendmail’s milter API.
The milter API is multi-threaded and written in C; mimedefang lets you
write single-threaded filters written in the language of your choice.
Some of the flexibility and speed of milter is sacrificed, but the ease
of writing filters more than compensates for this slight loss.
This manual describes how mimedefang communicates with the filter
program, and gives you enough information to write your own filter
program as a replacement for mimedefang.pl if you wish.
PROTOCOL OVERVIEW
The protocol is a simple file-based protocol. For each invocation of a
filter, mimedefang creates a unique working directory and populates it
with files. It calls the filter, which is expected to populate the
working directory with more files, which communicate the scan results
back to mimedefang. This simple mechanism allows you to easily write
filters in scripting languages without worrying about C-level details.
FILTER INVOCATION
The filter program may be invoked in one of five ways:
filter_prog directory
If the program is invoked with a single argument which is an
absolute path name (called the working directory, the program is
expected to perform filtering in that directory and then exit.
filter_prog -server
If the program is invoked with the single argument -server, it
is expected to run as a server. See SERVER MODE for details.
filter_prog -serveru
If the program is invoked with the single argument -serveru, it
is expected to run as a server. In addition, anything it prints
to file descriptor 3 is used to update the "slave status" field
in the multiplexor. This lets the filter inform administrators
exactly what it is doing. (See the -Z option to mimedefang-
multiplexor.)
filter_prog -embserver
Similar to -server, but used by the embedded Perl code. The
program should run any initialization routines and then exit.
The multiplexor will subsequently call the Perl routine
do_main_loop when it is time for the slave to begin running in
server mode.
filter_prog -embserveru
Similar to -embserver with the additional magic of updating the
slave status from data written to file descriptor 3.
INITIAL FILE LAYOUT
When the filter begins a scan, it should change directories to the
working directory. In that directory, it will find the following
files.
INPUTMSG
A file containing the complete input e-mail message, including
headers.
HEADERS
A file containing just the headers, one per line. Headers which
are continued over several lines in the original message are
collapsed into a single line in this file.
COMMANDS
A file containing a list of commands. Each command is a single
letter and may be followed by arguments. Each command is on its
own line.
THE COMMANDS FILE
All commands have their arguments encoded as follows: All characters
outside the range 33 to 126 ASCII, as well as the characters "%", "\",
"’" and double-quote, are replaced by a percent sign followed by two
hex digits specifying the character’s numerical value. The filter must
un-escape the arguments when it reads the COMMANDS file.
The commands from the C to Perl filters are:
Ssender
The sender of the message.
sesmtp_arg
An ESMTP argument associated with the sender (such as
SIZE=54432). There is one s line for each ESMTP argument.
Usubject
The message subject.
Xmessage_id
The Message-ID.
Rrecipient mailer host addr
A recipient. There is one R line for each recipient. The
mailer, host and addr parts of the line are the values of the
Sendmail {rcpt_mailer}, {rcpt_host} and {rcpt_addr} macros if
they are available, or "?" if not.
resmtp_arg
An ESMTP argument associated with the most recent recipient
(such as NOTIFY=never). There is one r line for each SMTP
argument.
! If this command is present, there are suspicious characters in
the message headers.
? If this command is present, there are suspicious characters in
the message body.
Ihost_addr
The SMTP relay host’s IP address in dotted-quad notation.
iidentifier
An identifier generated by MIMEDefang. On a given host, this
identifier is very likely to be unique over a timespan of about
24 years.
Jhost_addr
The "real" SMTP relay host’s IP address in dotted-quad notation.
Multi-stage MIMEDefang relays can use a special IP validation
header so that even the innermost MIMEDefang relay can see the
"original" relay’s IP address.
Hhost_name
The SMTP relay host name.
Eargument
The argument to the SMTP "EHLO" or "HELO" command.
Qqid The message’s Sendmail queue-ID.
=macro val
Set the value of the specified Sendmail macro to val. Both
macro and val are percent-encoded, but the single space
character between them is not.
FILTER OPERATION
When the filter performs a scan, it can make use of all the information
in the files mentioned previously. If the filter needs temporary
working files, it should create a subdirectory under the working
directory for its own use. In this case, you do not have to clean up
your working files, because mimedefang deletes the working directory
when the filter returns.
FINAL FILE LAYOUT
The filter communicates the results of the scan back to mimedefang by
creating additional files in the working directory. The most important
file is called RESULTS, and it contains a list of one-letter, one-line
commands back to the filter. As usual, command arguments are percent-
escaped. The commands from the filter back to mimedefang are:
Bcode dsn reply_text
Bounce (reject) the message with the specified SMTP reply code,
DSN code and reply text.
D Silently discard the message and pretend it was delivered.
Tcode dsn reply_text
Return an SMTP temporary failure code with the specified SMTP
code, DSN and reply text.
C Replace the message body. If this command is present, the file
NEWBODY must contain the new message body.
Mheader_val
Replace the MIME Content-Type header with a new value. Used to
change MIME boundaries or convert non-MIME to MIME messages.
Hheader val
Add a new header header with value val. The header should not
contain a colon. Each of header and val is percent-escaped, but
the single space between them is not.
Nheader index val
Adds a new header header with value val in position index. An
index of zero specifies that the new header should be prepended
before all existing headers.
Iheader index val
Replace the indexth occurrence of header with value val. The
index is 1-based. The header should not contain a colon. Each
of header, index and val is percent-escaped, but the single
space between them is not.
Jheader index
Delete the index’th occurrence of header.
Rrecip Add a new recipient recip to the message.
Srecip Delete recip from the list of message recipients.
fsender
Change the envelope sender to sender. This is only supported by
Sendmail 8.14.0 and higher.
F Indicate that we have finished issuing commands. Anything after
an F line is ignored.
SERVER MODE
In server mode, mimedefang-multiplexor runs the filter program
continuously in a server loop. The filter program reads commands from
standard input, and writes results to standard output. The filter
program must exit shortly after it sees EOF on its standard input. If
it does not exit within 10 seconds, it will be terminated with SIGTERM.
If that still does not work, then after a further 10 seconds, it is
killed with SIGKILL.
SERVER COMMANDS
All server commands are single line commands. Each command is
followed by a space-separated list of arguments; each argument
is percent-encoded. The commands defined are:
ping Elicits a reply of "PONG" from the server.
scan dir
Run a scan in the directory dir. The command is terminated with
a newline. The server must write a newline-terminated "ok" if
the scan completed successfully, or "error: msg" if something
went wrong.
relayok ip_addr hostname
Test whether or not to accept a connection from the specified
host. The server must write "ok 1" if we will accept the
connection, or "ok 0 error_message code dsn" if not. It can
indicate a temporary failure by writing "ok -1 error_message
code dsn". Note that even if the connection is accepted, a
later scan can still reject the message based on other criteria.
"ip_addr" is the IP address of the relay and "hostname" is the
hostname (if it could be determined; otherwise, the IP address
in square brackets).
senderok sender_addr ip_addr hostname helo_string dir queue_id
[esmtp_args...]
Test whether or not to accept mail from the specified sender.
The server must write "ok 1" if we will accept the mail attempt,
or "ok 0 error_message code dsn" if not. "ok -1 error_message
code dsn" indicates a temporary failure. Note that even if the
sender is accepted, a later scan can still reject the message
based on other criteria. "sender_addr" is the sender’s e-mail
address. The "ip_addr" and "hostname" arguments are as in
relayok. "helo_string" is the argument to the SMTP HELO/EHLO
command. "dir" is the MIMEDefang spool directory, and "queue_id"
is the Sendmail queue identifier.
The optional "esmtp_args" are space-separated, percent-encoded
ESMTP arguments supplied with the MAIL FROM: command.
recipok recip_addr sender_addr ip_addr hostname first_recip helo_string
dir queue_id [esmtp_args...]
Test whether or not to accept mail for the specified recipient.
The server must write "ok 1" if we will accept it, or "ok 0
error_message code dsn" if not. ok -1 error_message code dsn"
indicates a temporary-failure.
"recip_addr" is the argument to the RCPT TO: command, and
"first_recip" is the argument to the first RCPT TO: command for
this message. Other arguments are as in senderok.
map map_name key
If you are using a map socket (the -N option to mimedefang-
multiplexor), then the server should look up the key key in the
map map_name. The server should print a single line to standard
output. The first word on the line should be one of OK,
NOTFOUND, TEMP, TIMEOUT or PERM, indicating a successful lookup,
absence of the key, a temporary failure, a timeout or a
permanent failure, respectively. This should be followed by a
space and a percent-encoded string representing the value of the
key (if it was found) or an optional error message (if something
went wrong.)
tick band
The filter should run filter_tick with the specified band
argument. It should print a single line to standard output:
tock band
Additional Commands
The filter can define a function filter_unknown_cmd that can
extend the list of server commands. If you do this, make sure
all of your commands start with an upper-case letter to avoid
conflicts if more built-in commands are defined in the future.
SERVER REPLIES
The reply codes are:
ok [return_code] [parameters]
The operation completed successfully. Some operations have an
associated return code, and possibly other parameters as well.
See the source code for the gory details.
error: Message
The operation failed. Message may give additional details.
In server mode, you should not write anything to standard output except
reply codes, or the multiplexor will become confused. You should not
terminate the program in server mode; simply echo an error: reply and
return to the server loop.
When you send a reply code back to the multiplexor, be sure to
terminate it with a newline, and to flush standard output. If your
program uses the Standard I/O library, standard output may not be
flushed immediately, and mimedefang-multiplexor will wait forever for
the filter’s reply, and eventually kill the filter on the assumption it
has hung up.
In server mode, if the filter program receives a SIGINT signal, it must
terminate. This is used by mimedefang-multiplexor to terminate slaves
after they have processed a given number of e-mail messages.
AUTHOR
mimedefang was written by David F. Skoll <dfs@roaringpenguin.com>. The
mimedefang home page is http://www.mimedefang.org/.
SEE ALSO
mimedefang.pl(8), mimedefang(8), mimedefang-multiplexor(8), mimedefang-
filter(5)