Internet-Draft Milter Protocol October 2026
Adams & Kucherawy Expires 29 April 2027 [Page]
Workgroup:
TBD
Internet-Draft:
draft-adams-milter-protocol-00
Published:
Intended Status:
Informational
Expires:
Authors:
T. Adams
Proofpoint, Inc.
M. Kucherawy, Ed.

The Mail Filter (milter) Protocol

Abstract

This document specifies the "milter" protocol, a binary request/response protocol by which a Mail Transfer Agent (MTA) can delegate inspection and modification of an SMTP transaction to one or more external filtering processes.

Editorial Note

This note is to be removed before publishing as an RFC.

This document describes existing widely deployed practice originating in the sendmail "libmilter" implementation. Prose sections marked [[TODO]] are placeholders.

Publication is being sought to archive the protocol which has never been publicly documented other than in its code form. The protocol has not evolved substantially since the release of version 6, and prior versions are considered historical.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 29 April 2027.

▲

Table of Contents

1. Introduction

Milter (a portmanteau of "mail filter") was officially introduced into open source Sendmail 8.12.0 released on September 8, 2001. It provided a plugin architecture by which a Mail Transfer Agent (MTA) can communicate with an arbitrary number of local filtering agents to observe and possibly modify messages in transit or influence their delivery. Filters implementing the milter protocol (called "milters") are optionally involved at each phase of an SMTP [RFC5321] transaction.

Milter is also supported by Postfix, which together with Sendmail provides milter capabilities to the bulk of open source MTA deployment worldwide.

2. Conventions and Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

MTA:
The Mail Transfer Agent; the client of this protocol.
Filter (or milter):
The server of this protocol.
Octet:
An 8-bit byte.
Network byte order:
Big-endian, most significant octet first.
Null-terminated string:
A sequence of zero or more non-NUL octets followed by one octet of value 0x00. Unless stated otherwise, such strings are US-ASCII.

Numeric constants are given in hexadecimal with a "0x" prefix. Command and response identifiers are single US-ASCII characters and are shown in single quotes; the quotes are not part of the protocol.

3. Protocol Model

The milter protocol is a connection-oriented, binary, largely half-duplex request/response protocol. The MTA connects to the filter and drives the exchange; the filter reacts. There is no filter-initiated request other than responses.

3.1. Transport

The protocol runs over any reliable, ordered, octet-stream transport. In practice this is TCP [RFC9293] over IPv4 or IPv6, or a local (AF_UNIX) stream socket. No port number is reserved; the port or socket path is a matter of local configuration. The protocol provides no authentication, integrity, or confidentiality of its own (see Section 11).

3.2. Transaction Phases

One milter connection carries the negotiation phase followed by zero or more SMTP connection contexts, each carrying zero or more message transactions:

  1. Option negotiation (Section 5), exactly once per milter connection, before anything else.
  2. SMTP connection context: connection information, then HELO/EHLO.
  3. Per-message transaction: envelope sender, envelope recipients, DATA, headers, end of headers, body chunks, end of message.
  4. End of message is the only point at which message modifications may be requested.

An abort resets to the start of a message transaction while preserving the SMTP connection context. A quit ends the milter connection; a "quit but new connection follows" resets to the start of an SMTP connection context while preserving negotiated options.

3.3. Normal Message Flow

  MTA                                     Filter
   |--- 'O' OPTNEG ----------------------->|
   |<-- 'O' OPTNEG (agreed) --------------|
   |--- 'D' MACRO(for 'C') --------------->|   (optional, no reply)
   |--- 'C' CONNECT ---------------------->|
   |<-- 'c' CONTINUE ---------------------|
   |--- 'H' HELO ------------------------->|
   |<-- 'c' CONTINUE ---------------------|
   |--- 'M' MAIL ------------------------->|
   |<-- 'c' CONTINUE ---------------------|
   |--- 'R' RCPT ------------------------->|   (once per recipient)
   |<-- 'c' CONTINUE ---------------------|
   |--- 'T' DATA ------------------------->|
   |<-- 'c' CONTINUE ---------------------|
   |--- 'L' HEADER ----------------------->|   (once per header field)
   |<-- 'c' CONTINUE ---------------------|
   |--- 'N' EOH -------------------------->|
   |<-- 'c' CONTINUE ---------------------|
   |--- 'B' BODY ------------------------->|   (repeated)
   |<-- 'c' CONTINUE  or  'S' SKIP -------|
   |--- 'E' BODYEOB ---------------------->|
   |<-- zero or more modification actions -|
   |<-- final disposition ----------------|
   |--- 'A' ABORT / 'Q' QUIT / 'K' QUIT_NC >|

4. Packet Framing

All protocol data units ("packets") share one framing:

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                          len (uint32)                         |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |    cmd/resp   |                                               |
  +-+-+-+-+-+-+-+-+          data (len - 1 octets)                +
  |                             ...                               |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
len:
Unsigned 32-bit integer in network byte order, giving the number of octets that follow, i.e. one octet of command/response identifier plus the length of the data. The value MUST be at least 1. The length field itself is not counted.
cmd/resp:
One octet identifying the command (Section 6) or response (Section 7).
data:
Exactly len-1 octets, whose interpretation depends on the identifier. Where a field is a null-terminated string, the terminating NUL is included in len.

A receiver MUST impose an upper bound on len and MUST close the connection rather than attempt to buffer an implausibly large packet. Implementations commonly bound the negotiated maximum body chunk (Section 5.3) and reject packets exceeding it. A receiver MUST treat an unknown identifier, a truncated packet, a missing NUL terminator, or a data length inconsistent with the identifier's definition as a protocol error and close the connection.

Multiple packets MAY be coalesced into a single transport write; receivers MUST NOT rely on message boundaries in the transport stream.

5. Option Negotiation

Immediately after the connection is established, the MTA MUST send SMFIC_OPTNEG ('O') and the filter MUST reply with SMFIC_OPTNEG ('O'). No other command may precede this exchange.

  'O'  version   (uint32)   protocol version, 6 for this specification
       actions   (uint32)   bitmask of SMFIF_* (Section 5.2)
       protocol  (uint32)   bitmask of SMFIP_* (Section 5.3)

In the MTA's offer, "actions" and "protocol" advertise everything the MTA is able to support. In the filter's reply, the filter MUST NOT set any bit the MTA did not offer; the reply bits are the operative agreement for the remainder of the connection. The filter MUST request in "actions" every modification it may later attempt, and MUST set in "protocol" the bits describing the commands it wishes to be spared and the replies it will omit. An MTA that receives a version it does not support, or a bit it did not offer, MUST close the connection.

The filter's reply MAY be followed by zero or more macro list entries, permitted only if SMFIF_SETSYMLIST was negotiated:

       stage     (uint32)   0=connect 1=helo 2=mail 3=rcpt
                            4=data 5=eom 6=eoh
       macros    (string)   space-separated macro names, NUL-terminated

Each entry replaces the MTA's default macro set for that stage. A stage MUST NOT appear more than once.

5.1. Protocol Versions

Version 6 is specified by this document and is the only version implementations are expected to support. Versions 2 and 4 exist in historical deployments; they lack, among other things, the DATA and UNKNOWN commands, recipient-parameter and sender-change actions, the SKIP response, and the no-reply protocol bits. Implementations SHOULD offer version 6 and MAY accept earlier versions for interoperability.

5.2. Action Flags (SMFIF_*)

Table 1: Action Flags
Value Name Permits
0x00000001 SMFIF_ADDHDRS Add header fields ('h')
0x00000002 SMFIF_CHGBODY Replace the body ('b')
0x00000004 SMFIF_ADDRCPT Add a recipient ('+')
0x00000008 SMFIF_DELRCPT Delete a recipient ('-')
0x00000010 SMFIF_CHGHDRS Change or delete header fields ('m'), insert ('i')
0x00000020 SMFIF_QUARANTINE Quarantine the message ('q')
0x00000040 SMFIF_CHGFROM Change the envelope sender ('e')
0x00000080 SMFIF_ADDRCPT_PAR Add a recipient with ESMTP parameters ('2')
0x00000100 SMFIF_SETSYMLIST Send macro lists during negotiation

5.3. Protocol Flags (SMFIP_*)

Bits in the first group suppress a command entirely: the MTA will not send it and the filter will not reply to it. Bits in the second group ("no reply") keep the command but declare that the filter will send no response packet for it; the MTA MUST proceed as if SMFIR_CONTINUE had been received. Filters MUST NOT send a response for a stage whose no-reply bit was negotiated.

Table 2: Protocol Flags
Value Name Meaning
0x00000001 SMFIP_NOCONNECT Do not send 'C'
0x00000002 SMFIP_NOHELO Do not send 'H'
0x00000004 SMFIP_NOMAIL Do not send 'M'
0x00000008 SMFIP_NORCPT Do not send 'R'
0x00000010 SMFIP_NOBODY Do not send 'B'
0x00000020 SMFIP_NOHDRS Do not send 'L'
0x00000040 SMFIP_NOEOH Do not send 'N'
0x00000080 SMFIP_NR_HDR No reply for 'L'
0x00000100 SMFIP_NOUNKNOWN Do not send 'U'
0x00000200 SMFIP_NODATA Do not send 'T'
0x00000400 SMFIP_SKIP Filter may send 'S' (SKIP)
0x00000800 SMFIP_RCPT_REJ Also report recipients the MTA rejected
0x00001000 SMFIP_NR_CONN No reply for 'C'
0x00002000 SMFIP_NR_HELO No reply for 'H'
0x00004000 SMFIP_NR_MAIL No reply for 'M'
0x00008000 SMFIP_NR_RCPT No reply for 'R'
0x00010000 SMFIP_NR_DATA No reply for 'T'
0x00020000 SMFIP_NR_UNKN No reply for 'U'
0x00040000 SMFIP_NR_EOH No reply for 'N'
0x00080000 SMFIP_NR_BODY No reply for 'B'
0x00100000 SMFIP_HDR_LEADSPC Header values retain leading space; no space is added on output
0x10000000 SMFIP_MDS_256K Maximum body chunk 262144 octets
0x20000000 SMFIP_MDS_1M Maximum body chunk 1048576 octets

Absent an MDS bit, the maximum body chunk is 65535 octets. If both MDS bits are offered the filter MUST select at most one. There is no no-reply bit for end of message ('E'); a filter MUST always answer 'E'.

6. Commands (MTA to Filter)

Unless a no-reply or suppression bit was negotiated, the MTA MUST wait for a response to each command before sending the next, and the filter MUST send exactly one terminal response per command.

Table 3: Command Codes
Code Name Stage
'O' (0x4F) SMFIC_OPTNEG Negotiation
'D' (0x44) SMFIC_MACRO Any (no reply)
'C' (0x43) SMFIC_CONNECT Connection
'H' (0x48) SMFIC_HELO Connection
'M' (0x4D) SMFIC_MAIL Envelope
'R' (0x52) SMFIC_RCPT Envelope
'T' (0x54) SMFIC_DATA Envelope
'L' (0x4C) SMFIC_HEADER Message
'N' (0x4E) SMFIC_EOH Message
'B' (0x42) SMFIC_BODY Message
'E' (0x45) SMFIC_BODYEOB End of message
'U' (0x55) SMFIC_UNKNOWN Any
'A' (0x41) SMFIC_ABORT Any (no reply)
'Q' (0x51) SMFIC_QUIT Any (no reply)
'K' (0x4B) SMFIC_QUIT_NC Any (no reply)

6.1. SMFIC_MACRO ('D')

  'D'  cmdcode   (char)     command letter these macros apply to
       pairs      ...       name NUL value NUL, repeated to end of packet

Conveys named symbols ("macros") describing the state of the SMTP session. It is not a command in its own right: it carries no reply, and it MUST immediately precede the command identified by cmdcode. Macro values persist for the scope of the stage in which they were sent and are discarded when that scope ends. Names are conveyed without the leading '$' or enclosing braces used in MTA configuration syntax. See Section 8.

6.2. SMFIC_CONNECT ('C')

  'C'  hostname  (string)   validated client name, or bracketed address
       family    (char)     'U' unknown, 'L' unix, '4' inet, '6' inet6
       port      (uint16)   client source port, present unless family 'U'
       address   (string)   textual address, present unless family 'U'

Sent once per SMTP connection, before any other transaction command. When family is 'U', port and address are absent. For 'L', port is present but meaningless and address is the socket path. Address literals follow [RFC5321] textual form.

6.3. SMFIC_HELO ('H')

  'H'  helo      (string)   argument of the HELO or EHLO command

May occur more than once per SMTP connection. A second HELO/EHLO resets the SMTP transaction but not the milter connection context.

6.4. SMFIC_MAIL ('M')

  'M'  args       ...       one or more NUL-terminated strings

The first string is the envelope sender in angle-bracketed [RFC5321] form; the remainder, if any, are the ESMTP parameters of the MAIL command, one per string. This command begins a message transaction.

6.5. SMFIC_RCPT ('R')

  'R'  args       ...       one or more NUL-terminated strings

As for 'M', but the first string is one envelope recipient. Sent once per recipient. A rejection response applies only to that recipient and does not terminate the transaction. If SMFIP_RCPT_REJ was negotiated, recipients the MTA itself rejected are also reported, distinguishable through macros.

6.6. SMFIC_DATA ('T')

  'T'  (no data)

Signals the SMTP DATA command, after the last recipient and before any header. A rejection here rejects the whole message.

6.7. SMFIC_HEADER ('L')

  'L'  name      (string)   header field name, without the colon
       value     (string)   header field value

Sent once per header field, in the order the fields appear. Folded fields are delivered with their embedded CRLF sequences intact and are not unfolded. Unless SMFIP_HDR_LEADSPC was negotiated, the whitespace separating the colon from the value is removed from value, and the MTA reinserts a single space when emitting header fields supplied by the filter.

6.8. SMFIC_EOH ('N')

  'N'  (no data)

Marks the end of the header block.

6.9. SMFIC_BODY ('B')

  'B'  chunk      ...       opaque body octets, not NUL-terminated

Sent zero or more times. Each chunk carries at most the negotiated maximum (Section 5.3) minus framing overhead. Chunk boundaries are arbitrary and carry no semantics: they need not align with line boundaries, and a filter MUST NOT assume otherwise. Line endings are CRLF as received on the wire. Dot-stuffing as defined in [RFC5321] is removed by the MTA before the body is presented.

6.10. SMFIC_BODYEOB ('E')

  'E'  (no data)

Marks the end of the message body. This is the only stage at which the filter may send modification actions (Section 7.5). The filter MUST conclude with exactly one terminal response.

6.11. SMFIC_UNKNOWN ('U')

  'U'  command   (string)   the unrecognized SMTP command text

Reports an SMTP command the MTA did not recognize or could not process. It does not change the transaction state.

6.12. SMFIC_ABORT ('A')

  'A'  (no data)

Abandons the current message transaction. The filter MUST NOT reply and MUST discard all state accumulated since 'M', retaining connection and HELO state. It may arrive at any point in a transaction, including after 'E'.

6.13. SMFIC_QUIT ('Q') and SMFIC_QUIT_NC ('K')

  'Q'  (no data)     close the milter connection
  'K'  (no data)     close the SMTP connection context; reuse this one

Neither is answered. After 'Q' the filter MUST release all state and close the connection. After 'K' the filter MUST discard transaction and connection state but retain the negotiated options and await a new 'C' on the same milter connection.

7. Responses (Filter to MTA)

Responses fall into three classes: terminal dispositions, which conclude the handling of a command; non-terminal responses, which do not conclude it; and modification actions, valid only at end of message and always followed by a terminal disposition.

Table 4: Response Codes
Code Name Class
'c' (0x63) SMFIR_CONTINUE Terminal
'a' (0x61) SMFIR_ACCEPT Terminal
'r' (0x72) SMFIR_REJECT Terminal
'd' (0x64) SMFIR_DISCARD Terminal
't' (0x74) SMFIR_TEMPFAIL Terminal
'y' (0x79) SMFIR_REPLYCODE Terminal
'f' (0x66) SMFIR_SHUTDOWN Terminal
'p' (0x70) SMFIR_PROGRESS Non-terminal
'S' (0x53) SMFIR_SKIP Terminal (body only)
'O' (0x4F) SMFIC_OPTNEG Negotiation only
'+' (0x2B) SMFIR_ADDRCPT Modification
'2' (0x32) SMFIR_ADDRCPT_PAR Modification
'-' (0x2D) SMFIR_DELRCPT Modification
'e' (0x65) SMFIR_CHGFROM Modification
'h' (0x68) SMFIR_ADDHEADER Modification
'i' (0x69) SMFIR_INSHEADER Modification
'm' (0x6D) SMFIR_CHGHEADER Modification
'b' (0x62) SMFIR_REPLBODY Modification
'q' (0x71) SMFIR_QUARANTINE Modification

7.1. Terminal Dispositions

SMFIR_CONTINUE ('c'), no data:
Proceed with normal processing. This is the implied response whenever a no-reply protocol bit is in effect.
SMFIR_ACCEPT ('a'), no data:
Accept without further filtering by this filter. Sent at a recipient stage it accepts that recipient; sent at any other stage it accepts the message and this filter is not consulted again for the remainder of the transaction.
SMFIR_REJECT ('r'), no data:
Reject permanently. The MTA issues a 5yz reply. At a recipient stage only that recipient is rejected; elsewhere the message is rejected.
SMFIR_TEMPFAIL ('t'), no data:
Reject temporarily. The MTA issues a 4yz reply, inviting a later retry. Scope is as for SMFIR_REJECT.
SMFIR_DISCARD ('d'), no data:
Accept the message at the SMTP level and then silently discard it. The sending client is given a success reply. If sent at a recipient stage, that recipient's copy is discarded.
SMFIR_SHUTDOWN ('f'), no data:
Reject and close the SMTP connection immediately. Not supported by all MTAs; filters SHOULD NOT depend on it.

The effect of a disposition sent before the message transaction begins — that is, at connect or HELO — applies to the SMTP connection rather than to a single message.

7.2. SMFIR_REPLYCODE ('y')

  'y'  reply     (string)   "NNN[ ENH.S.C] text", NUL-terminated

Rejects with a filter-supplied SMTP reply. The first three octets MUST be a three-digit reply code beginning with '4' or '5' as defined in [RFC5321], optionally followed by a space, an enhanced status code [RFC3463], and free text. Whether the reply is treated as temporary or permanent follows its leading digit. The text MUST NOT contain bare CR or LF; a multiline reply is expressed by embedding CRLF-separated lines formatted per [RFC5321], and MTAs MAY refuse such replies. A "%" in the text is interpreted by some MTAs as introducing a format directive and MUST therefore be escaped as "%%".

7.3. SMFIR_PROGRESS ('p')

  'p'  (no data)

Indicates that the filter is still working and requests that the MTA reset its response timer. It does not conclude the command; the filter MUST still send a terminal response. It MAY be sent repeatedly and is intended chiefly for long-running end-of-message processing.

7.5. Modification Actions

Modification actions MUST be sent only in response to SMFIC_BODYEOB, MUST be permitted by the action flags agreed during negotiation, and MUST be followed by exactly one terminal disposition. Any number may be sent, and their effects are applied by the MTA in the order received. A filter MUST NOT expect the MTA to report the outcome of an individual action; the MTA MAY reject the whole connection if an action is malformed or unnegotiated.

  'h'  name      (string)   append a header field
       value     (string)
  ---
  'i'  index     (uint32)   insert a header field; 1 = before the first
       name      (string)   existing field, 0 is treated as 1; an index
       value     (string)   past the end appends
  ---
  'm'  index     (uint32)   1-based occurrence of this field name to
       name      (string)   change; empty value deletes the field
       value     (string)
  ---
  'b'  data       ...       replacement body octets, not NUL-terminated
  ---
  '+'  rcpt      (string)   add envelope recipient
  ---
  '2'  rcpt      (string)   add envelope recipient with ESMTP parameters
       args      (string)
  ---
  '-'  rcpt      (string)   delete envelope recipient
  ---
  'e'  from      (string)   replace envelope sender
       args      (string)   optional ESMTP parameters; may be absent
  ---
  'q'  reason    (string)   quarantine; empty reason releases

Notes on individual actions:

  • Header names and values in 'h', 'i', and 'm' are subject to the SMFIP_HDR_LEADSPC convention described in Section 6. Values MUST NOT contain bare CR or LF; folding is expressed with CRLF followed by whitespace.
  • 'm' with an index greater than the number of occurrences of that field name has no effect. Deletion renumbers subsequent occurrences, so a filter deleting several occurrences SHOULD work from the highest index downward.
  • 'b' replaces the entire body. It MAY be sent repeatedly, in which case the chunks are concatenated in order to form the new body; sending 'b' with no data yields an empty body. Each packet is bounded as for SMFIC_BODY. Lines MUST be CRLF-terminated and MUST NOT be dot-stuffed.
  • Recipient and sender addresses are in angle-bracketed [RFC5321] form. Adding a recipient that is already present, or deleting one that is not, has no effect.
  • 'q' places the message in the MTA's held queue rather than delivering it; the reason is recorded for the administrator. It is normally paired with a terminal SMFIR_ACCEPT.

8. Macros

Macros are name/value pairs supplied through SMFIC_MACRO (Section 6) and give the filter access to MTA state not otherwise carried on the wire. Availability is MTA-specific and, when SMFIF_SETSYMLIST is negotiated, configurable per stage. A filter MUST tolerate the absence of any macro. The following are widely implemented.

Table 5: Commonly Available Macros
Name Earliest stage Value
j connect Canonical name of the MTA host
_ connect Validated client name and address
{daemon_name} connect Name of the MTA daemon instance
{daemon_port} connect Local port the client connected to
{if_name}, {if_addr} connect Local interface name and address
{client_addr}, {client_port} connect Client address and source port
{client_name} connect Client PTR name, if verified
{client_ptr} connect Result of the reverse lookup
{client_connections} connect Concurrent connections from this client
{tls_version}, {cipher}, {cipher_bits} helo TLS session parameters
{cert_subject}, {cert_issuer} helo Client certificate identity
{verify} helo Certificate verification result
{auth_type}, {auth_authen} mail SASL mechanism and authenticated identity
{auth_author} mail Authorization identity, if asserted
{auth_ssf} mail SASL security strength factor
{mail_addr}, {mail_host}, {mail_mailer} mail Resolved envelope sender
i mail MTA queue identifier for this message
{rcpt_addr}, {rcpt_host}, {rcpt_mailer} rcpt Resolved current recipient
{rcpt_reject} rcpt Set when the MTA itself rejected this recipient

9. Error Handling and Timeouts

The protocol carries no error response. Any framing violation, unexpected or out-of-sequence identifier, or action that was not negotiated is a protocol error, and the detecting party MUST close the connection without further exchange.

An MTA MUST apply a timeout to each response and SHOULD apply separate timeouts to connection establishment, to sending, and to end-of-message processing. SMFIR_PROGRESS restarts the response timer. On timeout, or on any failure to connect to or communicate with a filter, the MTA MUST apply a locally configured default action; a temporary rejection is RECOMMENDED as it is fail-closed without permanently losing mail.

Where an MTA consults several filters, it does so in a configured order, passing each stage through the filters in turn; the first non-continue disposition terminates consideration of that stage, and modifications made by one filter are visible to those following it.

10. IANA Considerations

This document specifies no actions for IANA.

11. Security Considerations

The protocol provides no authentication, integrity protection, or confidentiality. A milter connection can carry the full content of every message, including credentials asserted through macros, in cleartext, and a filter can reject, discard, or rewrite any message. Deployments MUST therefore confine milter traffic to a trusted path — a local socket with restrictive permissions, a loopback interface, or a channel protected by TLS [RFC8446] or an equivalent — and MTAs MUST NOT accept filter connections from, nor connect to filters at, unauthenticated network locations.

Further considerations: length fields are attacker-influenced and invite memory exhaustion if not bounded; a slow or wedged filter is a denial-of-service vector against the MTA, and the fail-open default action is a filtering-bypass vector; header and body modifications can invalidate signatures such as DKIM [RFC6376]; filter-supplied reply text is echoed to untrusted clients and can leak internal detail or be used for injection if not sanitized.

12. References

12.1. Normative References

[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC3463]
Vaudreuil, G., "Enhanced Mail System Status Codes", RFC 3463, DOI 10.17487/RFC3463, , <https://www.rfc-editor.org/info/rfc3463>.
[RFC5321]
Klensin, J., "Simple Mail Transfer Protocol", RFC 5321, DOI 10.17487/RFC5321, , <https://www.rfc-editor.org/info/rfc5321>.
[RFC5322]
Resnick, P., Ed., "Internet Message Format", RFC 5322, DOI 10.17487/RFC5322, , <https://www.rfc-editor.org/info/rfc5322>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.

12.2. Informative References

[RFC6376]
Crocker, D., Ed., Hansen, T., Ed., and M. Kucherawy, Ed., "DomainKeys Identified Mail (DKIM) Signatures", STD 76, RFC 6376, DOI 10.17487/RFC6376, , <https://www.rfc-editor.org/info/rfc6376>.
[RFC8446]
Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/info/rfc8446>.
[RFC9293]
Eddy, W., Ed., "Transmission Control Protocol (TCP)", STD 7, RFC 9293, DOI 10.17487/RFC9293, , <https://www.rfc-editor.org/info/rfc9293>.

Acknowledgments

[[TODO]]

Authors' Addresses

Trent Adams
Proofpoint, Inc.
Murray Kucherawy (editor)