1

I am trying to implement MTA using Postfix. I am struck at how to implement standard services like SPF, DKIM etc. as well as some custom services. They can either be implemented as policy delegation service and called by check_policy_service or as smtpd milters, but I am confused which method will be more appropriate and why.

I see policy service will give more flexibility in terms of where I can apply it. Also the documentation says policy services also enjoy wider action list like Defer, Dunno which are not available to milter actions. But there should be some distinct advantages that milter's implementation offer. I'd like a comparison between these two types of implementation.

1 Answer 1

4

For most purposes, including basic message authentication checks (SPF, DMARC, BIMI, ..), either interface is suitable. For content checking (blocking unwanted attachment), signatures (DKIM, ARC) and such, you need an interface that gives you that information, such as the milter one.

The interfaces do offer most features and basic actions, namely both can:

  1. investigate the sending address, name and envelope information
  2. permanently reject (code 5XX) or temporarily defer (code 4XX a.k.a "tempfail"), with optionally custom smtp status code, extended status code, and (possibly multi-line) smtp status text.
  3. receive additional configuration: milter_macro_v/policy_context
  4. prepend message headers (a popular choice would be Authentication-Results:)
  5. schedule a message for silent discarding or quarantine despite signalling acceptance

The interface also share some limitations, though specifics differ:

  1. your software must not malfunction on multi-recipient messages
  2. your software needs to get IDN handling right. (those lovely xn-- A-labels in domains)
  3. partly by their nature, partly by design, neither interface permits graceful handling local maildrop (non-SMTP-submissions) in all the same ways you could handle SMTP submissions.
  4. your software needs to get stuff done while the sender is waiting - expensive processing, network lookups or unreliable checks must at some point be interrupted, the message deferred, and measures taken so it finishes in time next time.

Unique for milter interface

The milter interface allows you to parse, and selectively remove or rewrite arbitrary headers, or message body (parts). However, editing is possibly better done in post-queue processing, past address-rewriting and multi-recipient pitfalls.

In any case, message syntax and encoding features must not not make your software misbehave. Think of the notoriously difficult-to-parse address headers and attachment filenames. I have yet to encounter software that gets this 100% right.

You want to use the milter interface if you need to act on non-default SMTP commands, or care about SMTP session state transitions. In the milter interface, you get to handle things like RSET and (must) handle your local state accordingly - where in the policy interface postfix sends you what you need with the effective protocol_state.

Beware: the milter interface documentation is far from clear on where Postfix aims for sendmail bug-compatibility, and where it deviates. Also, the header hook was broken in the past (in by now unsupported releases).

Milters signals their final decisions to postfix by (if using the C library) returning fixed SMFIS_* codes (e.g. SMFIS_TEMPFAIL for deferral), but may precede that to with a smfi_setreply(…, "4XX", "4.X.X", text) call to customize the return.

Unique to policy daemon interface

You may choose the order between restriction classes and your daemon - that is much more versatile than just ordering milters against other milters.

You want to use the the policy interface if you need to return non-SMTP results, such as defer_if_permit or your custom smtpd_restriction_classes. Cases where you will need this include the performance motivated need skip some checks for very busy servers. E.g. when your policy must be, rather than being the final arbiter of what can be accepted or not, merely select a message class to be processed in additional checks or routing decisions.

Policy daemons signal their final decisions to postfix via textual actions and their arguments, if applicable, e.g. action=DEFER optional text... (which is a fancier way of saying action=450 4.7.1 optional text...)

3
  • I am really new to it can you please explain how can milter defer an email, as per the documentation milter's fail is basically reject with temporary eror while quarantine move the mail to hold queue and not defer queue. 2 days ago
  • @SUNITAGUPTA Can you rephrase that? I am not sure whether you are surprised by the fact Postfix documentation distinguishes tempfail & defer where sendmail used the term tempfail for both policy and error results, or whether you are surprised that before-queue deferral means this happens before entering a local queue ;)
    – anx
    2 days ago
  • In postfix documentation it mentions under milter default actions "tempfail Reject all further commands in this session with a temporary status code." 2 days ago

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .