2

I am using header_checks in Postfix to rewrite my headers (for emails sent by Outlook through my server).

Here is the part of the header I am trying to change :

Received: from Raphasus (****.abo.wanadoo.fr [***.***.***.109])
    by mail.********.com (Postfix) with ESMTPSA id 917***CE9
    for <raph*****@hotmail.fr>; Thu, 31 Jul 2014 09:38:35 +0200 (CEST)

What I want to do : Replace the FIRST LINE only (with some personnalized infos), and append the 2 last lines.

What I tried (in header_checks):

/^\s*(Received: from).*$(.*)/ REPLACE $1 my personalized text $2

It works only when I remove the $2 (so it replaces the full Received: from with my text), if I put the $2, it just doesn't replace my header.

I think this part is correct :

/^\s*(Received: from).*$

It is selecting the first line or the "Received: from". But how can I tell that what follows in my regular expression should be considered as $2 parameter?

I searched everywhere and couldn't find (looked at POSIX syntax, PERL syntax (as this doc says that "Substitution of substrings from the matched expression into the action string is possible using the conventional Perl syntax"))

I've found a working example with $1 and $2 parameters :

/^\s*(Received: from)[^\n]*(.*)/ REPLACE $1 [127.0.0.1] (localhost [127.0.0.1])$2

But I just don't get where it decides what is $1 and what is $2

PS : I posted this question on ServerFault but now wonder if it shouldn't be on StackOverflow instead?

EDIT : New things that I tried and the results :

/^\s*(Received: from).*\((.*)/ REPLACE $1 mytext ([xxx.xxx.xxx.xxx])$2

It gives me :

Received: from mytext ([xxx.xxx.xxx.xxx])CEST)

I don't really understand why it is not detecting the opening parenthesis sooner (it seems it detects only after the ";")

EDIT2 : Further testing

So I tried to remove the line to check my header was still the same shape as before. It is, here is the result :

Received: from Raphasus (xxxxxxxxxxxxxxxxx.abo.wanadoo.fr [xxx.xxx.xxx.xxx])
    by mail.xxxxxxxx.com (Postfix) with ESMTPSA id 5B1xxxxxxF
    for <raphxxxxx@hotmail.fr>; Thu, 31 Jul 2014 14:03:57 +0200 (CEST)

So given the fact there is a lot of "0" in this header, I tried to put the following line in my header_checks to see where it cuts :

/^\s*(Received: from).*(0.*)/ REPLACE $1 mytext ([xxx.xxx.xxx.xxx])$2

And I get the following result :

Received: from mytext ([xxx.xxx.xxx.xxx])0 (CEST)

This is incredibly weird and I have no idea why it cuts at this zero and not any of the zeroes before (in 2014, in IP adresses, even in +0200 why the last one?, etc)

Raphael Laurent
  • 219
  • 1
  • 6
  • 17
  • 1
    Anything inside your parentheses, `()` will be a group. So says this page : https://www.cs.cf.ac.uk/Dave/PERL/node90.html , it's called pattern memory. – NickW Jul 31 '14 at 10:13
  • Oh, I should be able to do something knowing that now ^^ Thanks – Raphael Laurent Jul 31 '14 at 10:18
  • I actually just understood why your second regex isn't matching anything, the $ matches the END of the line, and you're asking it to match anything after the end of the line. – NickW Jul 31 '14 at 10:27
  • Well, my "Receive: from" part is on 3 lines. I am trying using another method (looking for closing parenthesis, etc), but I have weird results for now) – Raphael Laurent Jul 31 '14 at 10:30
  • Remember this from the postfix body checks page `These rules operate on one logical message header or one body line at a time. A decision made for one line is not carried over to the next line.` – NickW Jul 31 '14 at 10:34
  • Edited my question with new syntax – Raphael Laurent Jul 31 '14 at 10:39
  • Try putting your escaped parentheses `\(` inside your second group. – NickW Jul 31 '14 at 10:45
  • Didn't fix it ($2 displayed (CEST) instead of CEST), seems logical) – Raphael Laurent Jul 31 '14 at 12:02
  • I'm really not clear on what you're trying to match... – NickW Jul 31 '14 at 12:05
  • Edited with more tests I did. On my unmodified header, I want to replace the first line `Raphasus (xxxxxxxxxxxxxxxxx.abo.wanadoo.fr [xxx.xxx.xxx.xxx])` with a custom text, and keep the following 2 lines untouched. – Raphael Laurent Jul 31 '14 at 12:11
  • Then you need to specifically search for that string (or variations of it) `([a-z]{2,25} \(.*\[\.*]\)` I don't know if that's what will work for you, but it should be closer. – NickW Jul 31 '14 at 12:23
  • Finally I managed to make it work with more specific string like you advised : `/^(Received: from).*\(.*\]\)(.*)/ REPLACE $1 mytext $2`. Thank you very much for your help, I let you post this line of code as an answer for the reputation if you want (or I'll do it myself tonight if it hasn't been done). – Raphael Laurent Jul 31 '14 at 13:09
  • It is probably greedy match. Try using ? after * Something like: /^\s*(Received: from).*?(0.*)/. – Laurentiu Roescu Jul 31 '14 at 13:13

1 Answers1

2

If you're looking to remove/replace specific lines, or parts of lines, it's often better to try and be as specific as possible. In your case you'll want to try and more closely match the text after from and the server name and ip.

Something like this should do a better job:

([a-z]{2,25} \(.*\[.*\]\))

NickW
  • 10,183
  • 1
  • 18
  • 26