mimedefang-protocol - Conventions used by mimedefang(8) to
communicate with filter programs.
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.
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.
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 "worker 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 worker to begin running in server mode.
- filter_prog
-embserveru
- Similar to -embserver with the additional magic of updating the
worker status from data written to file descriptor 3.
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.
- 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.
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.
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.
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 index'th 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.
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 queue_id
dir
- Run a scan for the mail identiefied by the Sendmail queue-ID
queue_id 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 client_port daemon_ip
daemon_port
- 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).
- helook ip_addr
hostname helo_string client_port daemon_ip
daemon_port
- Test whether or not to accept the HELO/EHLO command. 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. helo_string is the
argument to the HELO/EHLO command. The remaining arguments have the same
meaning as in relayok.
- 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
workers after they have processed a given number of e-mail messages.
mimedefang was written by Dianne Skoll
<dfs@roaringpenguin.com>. The mimedefang home page is
https://www.mimedefang.org/.