0

I have Postfix running with a number of smtpd processes configured in master.cf like this:

# Internet facing one
1.2.3.4:25      inet  n       -       y       -       -       smtpd
  -o ...   # internet-only overrides

# Internal facing one
10.0.0.1:10026      inet  n       -       y       -       -       smtpd
  -o ...   # internal-only overrides

Now, I'd like to add a single header, with static name and value, to incoming mail depending on which smtpd it was received on.

Example:

X-Gert-Postfix-Received-From: the evil internet

My options considered:

  1. Add the header_checks option and use the PREPEND action in the file.

    Nearly there, but:

    • It requires to match an existing header and will then add one more on subsequent matches.
    • I don't always have a certain header present already, perhaps even a From is missing, for example.
    • In case you have existing header_checks, there's no easy way to stack two header_check files, I think.
  2. Build a custom app that uses the Milter protocol and hook that up to Postfix with smtpd_milters.

    Of course, this will work. I can inspect the mail in my own app, then inject the header there. Seems over-engineering for a simple task like adding a header. Additionally, it requires extra maintenance with the need to run another daemon app, quite some boilerplate code, etc.

  3. As suggested in a comment, use check_recipient_access (related Q).

    Same downsides as header_checks (see 1).

I feel like I'm missing something simple. Anyone got a better idea?

gertvdijk
  • 3,362
  • 4
  • 30
  • 46
  • Does this answer your question? [Add a custom header to Postfix with the relayed domain](https://serverfault.com/questions/693904/add-a-custom-header-to-postfix-with-the-relayed-domain) – Gerald Schneider Apr 07 '22 at 13:35
  • @GeraldSchneider Not really, check_recipient_access has the same downside as header_checks, I'm afraid. – gertvdijk Apr 07 '22 at 14:10
  • Postfix parameters specifying lookup tables are just comma/space separated lists of `type:name` references, so there *is* an easy way to stack them. I was going to suggest using that in conjunction with `always_add_missing_headers=yes`, but I am uncertain whether that is a complete answer (as documentation in some places sounds like `cleanup` is adding missing headers only once *after* `header_checks` processing) – anx Apr 09 '22 at 12:20

2 Answers2

0

In case you have existing header_checks, there's no easy way to stack two header_check files, I think.

There actually is a way to have multiple independent header_checks files per daemon.

each -o option in you master.cf overrides a default value or any postfix configuration parameter in main.cf. To have a different header_checks per daemon (say /etc/postfix/header_checks1 and /etc/postfix/header_checks2), you have to override each header_checks parameter:

# Internet facing one
1.2.3.4:25      inet  n       -       y       -       -       smtpd
-o header_checks = regexp:/etc/postfix/header_checks1

# Internal facing one
10.0.0.1:10026      inet  n       -       y       -       -       smtpd
-o header_checks = regexp:/etc/postfix/header_checks2

This way you will have completely independent header_checks files per smtpd daemon. From there you can add rules that PREPENDs the tag you were talking about.

FatRabbit
  • 136
  • 5
  • I've considered this, but as I stated: 1) it overrides my common header_checks. 2) all the downsides of header_checks in general. I have email arriving from untrusted sources like the worldwide internet. Not sure how this is an answer to my question given that this is in my question already basically. – gertvdijk Apr 07 '22 at 14:09
  • To be clear; if you have existing common logic in `main.cf`'s `header_checks`, then the override in `master.cf` masks it. This is a feature, but a downside/issue in this case. – gertvdijk Apr 07 '22 at 16:00
  • 2
    if you need a common header_checks for both daemons, just add it back in both of the 'override', you can have as many header_checks as you want, just list them. master.cf does not support spaces so you need to store the list of you header_checks files in a variable. – FatRabbit Apr 08 '22 at 11:26
0

To workaround the limitations of smtpd_*_restrictions:

A message - even one with "null" sender - has exactly one envelope sender. So use check_sender_access instead of check_recipient_access. The used lookup type can be static: because we do not care about the specifics of the return path. Add it in your list of smtpd_sender_restrictions before any checks generating ACCEPT results (postfix would not query additional lookups beyond).

# in main.cf
common_sender_restrictions =
  reject_non_fqdn_sender
  reject_unknown_sender_domain
  ..
internet_sender_restrictions =
  $common_sender_restrictions
  check_sender_access static:{PREPEND X-Gert-Postfix-Received-From: the evil internet}

# in master.cf
192.0.2.0:25        inet  n       -       y       -       -       smtpd
 -o smtpd_sender_restrictions=$internet_sender_restrictions
10.0.0.1:10026      inet  n       -       y       -       -       smtpd
 -o smtpd_sender_restrictions=$common_sender_restrictions
anx
  • 6,875
  • 4
  • 22
  • 45