The SpamAssassin Network Protocol ================================= (This document is perpetually in draft status) Synopsis -------- The protocol for communication between spamc/spamd is somewhat HTTP-like. The conversation looks like: spamc --> PROCESS SPAMC/1.2\r\n spamc --> Content-length: \r\n (optional) spamc --> User: \r\n spamc --> [optional \r\n-delimited headers...] spamc --> \r\n [blank line] spamc --> --message sent here-- spamd --> SPAMD/1.1 0 EX_OK\r\n spamd --> Content-length: \r\n spamc --> [optional \r\n-delimited headers...] spamd --> \r\n [blank line] spamd --> --processed message sent here-- After each side is done writing, it shuts down its side of the connection. The first line from spamc is the command for spamd to execute (PROCESS a message is the command in protocol<=1.5) followed by the protocol version. There may be additional headers following the command, which are as yet undefined. Servers should ignore these, and keep looking for headers which they do support, or the "\r\n\r\n" end-of-headers marker. The first line of the response from spamd is the protocol version (note this is SPAMD here, where it was SPAMC on the other side) followed by a response code from sysexits.h followed by a response message string which describes the error if there was one. If the response code is not 0, then the processed message will not be sent, and the socket will be closed after the first line is sent. Again, there may be additional headers following the response line, which are as yet undefined. Clients should ignore these, and keep looking for headers which they do support, or the "\r\n\r\n" end-of-headers marker. Commands -------- The following commands are defined as of protocol 1.5: CHECK -- Just check if the passed message is spam or not and reply as described below SYMBOLS -- Check if message is spam or not, and return score plus list of symbols hit REPORT -- Check if message is spam or not, and return score plus report REPORT_IFSPAM -- Check if message is spam or not, and return score plus report if the message is spam SKIP -- Ignore this message -- client opened connection then changed its mind PING -- Return a confirmation that spamd is alive. PROCESS -- Process this message as described above and return modified message TELL -- Tell what type of we are to process and what should be done with that message. This includes setting or removing a local or a remote database (learning, reporting, forgetting, revoking). HEADERS -- Same as PROCESS, but return only modified headers, not body (new in protocol 1.4) CHECK command returns just a header (terminated by "\r\n\r\n") with the first line as for PROCESS (ie a response code and message), and then a header called "Spam:" with value of either "True" or "False", then a semi-colon, and then the score for this message, " / " then the threshold. So the entire response looks like either: SPAMD/1.1 0 EX_OK\r\n Spam: True ; 15 / 5\r\n or SPAMD/1.1 0 EX_OK\r\n Spam: False ; 2 / 5\r\n There may be additional headers following the "Spam:" header, which are as yet undefined. Clients should ignore these, and keep looking for headers which they do support, or the "\r\n\r\n" end-of-headers marker. SYMBOLS command returns the same as CHECK, followed by a line listing all the rule names, separated by commas. Note that some versions of the protocol terminate this line with "\r\n", and some do not, due to an oversight; so clients should be flexible on whether or not a CR-LF pair follows the symbol text, and how many CR-LFs there are. Protocol version 1.3 onwards will always not terminate the line with "\r\n". REPORT command returns the same as CHECK, followed immediately by the report generated by spamd: SPAMD/1.1 0 EX_OK\r\n Spam: False ; 2 / 5\r\n \r\n This mail is probably spam. The original message has been attached along with this report, so you can recognize or block similar unwanted mail in future. See https://spamassassin.apache.org/tag/ for more details. [...] Note that the superfluous-score/threshold-line bug that appeared in SpamAssassin 2.5x is fixed. Clients should be flexible on whether or not a CR-LF pair follows the report text, and how many CR-LFs there are. REPORT_IFSPAM returns the same as REPORT if the message is spam, or nothing at all if the message is non-spam. The PING command does not actually trigger any spam checking, and (as with SKIP) no additional headers are expected. It returns a simple confirmation response, like this: SPAMD/1.5 0 PONG\r\n This facility may be useful for monitoring programs which wish to check that the daemon is alive and providing at least a basic response within a reasonable time frame. Note that since the protocol version 1.5, a client sending a PING command is required to follow the command (and a null header) with an empty line, for consistency with other commands (fixes bug 6187). TELL accepts three new headers, Message-class, Set and Remove and will return two possible headers, DidSet and DidRemove which indicate which action was taken. It is up to the caller to determine if the proper action happened. Here are some examples: To learn a message as spam: TELL SPAMC/1.3\r\n Message-class: spam\r\n Set: local\r\n To forget a learned message: TELL SPAMC/1.3\r\n Remove: local\r\n To report a spam message: TELL SPAMC/1.3\r\n Message-class: spam\r\n Set: local, remote\r\n To revoke a ham message: TELL SPAMC/1.3\r\n Message-class: ham\r\n Set: local\r\n Remove: remote\r\n HEADERS returns the same as PROCESS, up to and including the double-newline separator between message headers and body -- but stops there. It was added in SpamAssassin 3.2.0. Note that this requires protocol version 1.4. Headers ------- The following optional headers are defined as of protocol 1.4: Content-length Length of a request or response body, in bytes (generally a requirement as of protocol version 1.2 onwards) Spam See above; used in server responses to the CHECK command. User Username of the user on whose behalf this scan is being performed. The meaning of this is up to the server; format is that of a traditional UNIX username ([-A-Za-z0-9_]+). Compress An optional header, sent by the client to the server, whose value may consist of the string "zlib", indicating that the message body transmitted by the client is compressed using Zlib compression. (This is new in SpamAssassin 3.2.0.) As-yet-undefined headers should not be treated as errors, and instead should be ignored. Multiple headers can appear in requests and responses (this was not clearly defined until protocol version 1.3).