Score:0

How to add a single header for any incoming mail with Postfix?

id flag

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?

in flag
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)
id flag
@GeraldSchneider Not really, check_recipient_access has the same downside as header_checks, I'm afraid.
anx avatar
fr flag
anx
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)
Score:0
in flag

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.

id flag
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.
id flag
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.
FatRabbit avatar
in flag
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.
Score:0
fr flag
anx

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
id flag
This sounds very interesting and neat. Let me try this out later!
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.