krisdigitx
krisdigitx

Reputation: 7136

postfix regex change for subject headers

I am using the below regex to change the subject on mails sent through postfix on

/etc/postfix/header_checks

/^Subject: System command Run on (.*)-(.*)-(.*)\.(.*)/ REPLACE Subject: System command Run on $4 $2$3
/^Subject: System command Run on (.*)-(.*)-(.*)\.(.*)\.(.*)/ REPLACE Subject: System command Run on $5 $2$3

which means any mail coming from this host

server-env-01.app

will be caught by the first filter and subject will be changed

and hostname with this format

server-prod-01.loc.dc1

will be caught by the second filter

However the second filter is not being used cause the first filter is also applied for the hostname with this format server-prod-01.loc.dc1

any suggestions???

Upvotes: 1

Views: 3157

Answers (2)

krisdigitx
krisdigitx

Reputation: 7136

the below worked fine...though I had some inputs from Tomalak response above.

if /^Subject:/
/^Subject: System command run on \b([^.-]*)-([^.-]*)-([^.-]*)\.([^.-]*)\b$/ REPLACE Subject: System command run on $4 $2$3
/^Subject: System command run on \b([^.-]*)-([^.-]*)-([^.-]*)\.([^.-]*)\.([^.-]*)$/ REPLACE Subject: System command run on $5 $2$3
endif

Upvotes: 0

Tomalak
Tomalak

Reputation: 338406

Your problem is that .* matches every character as often as possible and overshoots your intended sub-match. In fact, every .* goes right to the end of the string, "giving back" characters only as far as it must to allow the rest of the expression to complete. That's called greedy matching and is the default behavior of regex engines.

Therefore it's crucial that you are specific when using the *.

Specific for the individual segments of "server-prod-01.loc.dc1" would be whitelists (like [a-z0-9]* or \w*) or a blacklist [^\s.-]*.

In your case I suppose that \w* would suffice. It neither matches - nor ., so it can't overshoot.

^Subject: System command Run on (\w*)-(\w*)-(\w*)\.(\w*)

and

^Subject: System command Run on (\w*)-(\w*)-(\w*)\.(\w*)\.(\w*)

The alternative would be to use a non-greedy quantifier (*?, or better +?, because * also matches zero characters):

^Subject: System command Run on (.+?)-(.+?)-(.+?)\.(.+?)

Though a) not all engines support non-greedy matching and b) being as specific as possible has a number of advantages... a regex that more clearly states its intention being one of them.


Read about repetition and greedyness.

Upvotes: 1

Related Questions