MIMEDEFANG-PROTOCOL(7)
β¨ NAME β¨
mimedefang-protocol β the conventions that mimedefang(8) uses to talk to filter programs. iykyk π
π¦ DESCRIPTION π¦
okay so, mimedefang(8) and mimedefang-multiplexor(8) are out here giving you a simplified way to hook your scripts and programs into Sendmail's milter API. lowkey iconic.
the milter API itself is multi-threaded and written in C, which is giving very "good luck bestie" energy. mimedefang says no π β it lets you write single-threaded filters in literally whatever language you want. yes, some of milter's flexibility and speed gets sacrificed, but the ease of writing filters more than compensates for that slight loss. worth it, no cap.
this manual describes how mimedefang communicates with the filter program, and gives you enough info to write your own filter program as a replacement for mimedefang.pl if you feel like it. main character move fr fr.
π 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. then it calls the filter, and the filter is expected to populate that working directory with more files, which communicate the scan results back to mimedefang. it's giving pen pals but make it filesystem π
this simple mechanism lets you easily write filters in scripting languages without worrying about C-level details. slay.
π FILTER INVOCATION π
the filter program may be invoked in one of five ways:
filter_progdirectory β 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's 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's expected to run as a server. plus, anything it prints to file descriptor3is used to update the "worker status" field in the multiplexor. this lets the filter tell administrators exactly what it's doing. (see the-Zoption tomimedefang-multiplexor.) very "keeping everyone in the loop" of it π«Ά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 routinedo_main_loopwhen it's time for the worker to begin running in server mode.filter_prog -embserveruβ similar to-embserverwith the additional magic of updating the worker status from data written to file descriptor3. β¨
πΈ 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. don't skip this step bestie, it's not optional π
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 asSIZE=54432). there is onesline for each ESMTP argument.Usubjectβ the message subject.Xmessage_idβ the Message-ID.Rrecipient mailer host addrβ a recipient. there is oneRline 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 asNOTIFY=never). there is onerline 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. iconic longevity tbh.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. and here's the best part: you do not have to clean up your working files, because mimedefang deletes the working directory when the filter returns. no chores, we love that π
π 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. sneaky but valid π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 fileNEWBODYmust contain the new message body.Mheader_valβ replace the MIMEContent-Typeheader 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 anFline is ignored. periodt.
π₯οΈ SERVER MODE
Okay bestie, plot twist: there's a whole other mode and it's giving main character energy. 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. That's the whole vibe β stdin in, stdout out, forever. π¦
And here's the part where you gotta be on your best behaviour: 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. And if that still does not work? Then after a further 10 seconds, it is killed with SIGKILL. π Like, no more chances, bestie. Just exit when you see EOF.
π SERVER COMMANDS
All server commands are single line commands. Each command is followed by a space-separated list of arguments, and each argument is percent-encoded. The commands defined are:
ping
Elicits a reply of "PONG" from the server. That's it. That's the whole command. Adorable. π
scan
scan queue_id dir
Run a scan for the mail identified 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
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
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
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
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 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
tick band
The filter should run filter_tick with the specified band argument. It should print a single line to standard output:
tock band
That's the tick-tock of it, bestie. β°
π 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. Future-proofing is self-care, periodt. π
π 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. Do not do it. And you should not terminate the program in server mode; simply echo an error: reply and return to the server loop. π
β οΈ Bestie, listen: 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. The way that forever-waiting is so not the vibe. π
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. π§
π AUTHOR
mimedefang was written by Dianne Skoll <dfs@roaringpenguin.com>. The mimedefang home page is https://www.mimedefang.org/. Iconic behaviour, honestly. π
π SEE ALSO
And that's the whole page, bestie β from the 4th Berkeley Distribution, dated 8 February 2005, living in the MIMEDEFANG-PROTOCOL(7) section. Go forth and flush your standard output. πβ¨π
π¦ where this page comes from
- debian bookworm: mimedefang 3.3-1
- debian trixie: mimedefang 3.6-2 Β· GPL-2.0-only
- epel 10: mimedefang 3.7.1-1.el10_3 Β· GPL-2.0-only AND GPL-2.0-or-later
- epel 9: mimedefang 3.7.1-1.el9 Β· GPL-2.0-only AND GPL-2.0-or-later
- fedora 43: mimedefang 3.6-3.fc43 Β· GPL-2.0-only AND GPL-2.0-or-later
- fedora 43: mimedefang 3.7.1-1.fc43 Β· GPL-2.0-only AND GPL-2.0-or-later
- fedora 44: mimedefang 3.6-4.fc44 Β· GPL-2.0-only AND GPL-2.0-or-later
- fedora 44: mimedefang 3.7.1-1.fc44 Β· GPL-2.0-only AND GPL-2.0-or-later
- ubuntu noble: mimedefang 3.3-1build4
- ubuntu questing: mimedefang 3.6-2.1
- ubuntu resolute: mimedefang 3.6-2.1build1 Β· GPL-2.0-only
- ubuntu stonking: mimedefang 3.6-2.1build2 Β· GPL-2.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms