Regex+postfix+header_checks

Résolu
salut a tous et merci de me lire

j'ai besoins d'aide pour la création d'un régex

En analysant les mails parti depuis mon client outlook (pc at home) en passant par mon serveur postfix (SMTP TLS sur un serveur VPS) je constate ceci :

from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)

que je veux transformer en ceci :

from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMTP id E67A58929974 for <xxx@xxx.com>; Sun, 20 Mar 2011 00:18:41 +0000 (GMT) 

les mots a changer sont donc :
from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx)

par
from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1])

et
with ESMTPA 

par
with SMTP 

dans mon header_checks j'ai déjà essayez plusieurs combinaisons de regex sans succès, j'ai réussi facilement a faire ignorer complétement la ligne et pas a la remplacer correctement.

quelqu'un qui si connait en regex peut-il m'aidez a résoudre mon problème ?

Merci d'avance a tous.
Cordialement
jonigood

14 réponses

Résumé de la discussion

Problème : l'utilisation d'un regex dans header_checks de Postfix pour transformer une ligne d'en-tête mail et remplacer des éléments comme l'adresse source et ESMTPA par des valeurs locales. Des propositions visent à capturer la ligne Received et à remplacer le préambule et le protocole, via des motifs ^Received:\s*(from\s*)192\.168\.1\.\d.*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$ et REPLACE. Des échanges ultérieurs soulignent l'importance de tester avant d'envoyer un mail réel, via postmap -q - regexp:/etc/postfix/header_checks, et d'adapter le motif selon que l'on puisse utiliser [0-9] ou \\d et présence de la ligne Received. Une nuance utile est de vérifier que le header à modifier commence bien par Received, et que l'utilisateur fournisse l'exemple exact d'entrée pour que la regex ne casse pas d'autres lignes.

Bobot (l’IA à votre service)
  1. Contributeur
    Salut,

    Une piste...

    $ cat plop
    from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
    
    $ sed 's/^from 192\.168\.1\.2.*sender:[^)]*)/from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1])/;s/ESMTPA/SMPT/' plop
    from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMPT id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
    
    $

    ;-))
    1. salut zipe31 et merci de ton intervention,

      je ne pense pas que c'est écrit sous la bonne forme, pour exemple voici comment j'arrive a remplacer TOUTE LA LIGNE sans exception (ce n'est donc pas le résultat souhaité) :
      /^Received:.*\[192\.168\.0\.[0-9]/   REPLACE  Received  from mail.MON-SERVEUR-SMTP.com

      ceci remplace toute la ligne par Received from mail.MON-SERVEUR-SMTP.com

      de mon coté voila ou j'en suis :
      /^Received:.*\[192\.168\.0\.[0-9]\(Authenticated sender:.*\)\s+(.*by mail\.MON\-SERVEUR\-SMTP\.com[^\n]+ESMTPSA .*)$/im      REPLACE       from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMPT

      et ca ne fonctionne pas, il doit y avoir une erreur dans ma ligne.
      une idée ?
      1. Contributeur
        Perso j'ai utilisé "sed", mais toi tu utilises (ou comptes utiliser) quel langage ?
      2. langage pcre

        merci de ton aide
      3. Contributeur
        Euh... là je vais céder ma place à "lami20j" qui s'y connait bien plus que moi dans ce genre de regex ;-)

        Par contre dans ta regex il y a un truc qui me chagrine, c'est le "[^\n]+" ???
        Qu'as-tu voulu exprimer avec ça ?
      4. oups
        effectivement "[^\n]+" pas bon, désolé les regex c'est pas mon fort je suis perdu ...

        l'amie20J plese help !!!!!
    2. Modérateur
      Salut à vous deux,

      langage pcre
      Tu ne fais pas ça en php, par hasard?
      1. Contributeur
        Salut à toi,

        Merchi ;-))
      2. Modérateur
        Re,

        De rien.

        Pour joniperdu, je vais regarder ce soir ;-))).
        Ca ne t'empêchera pas de répondre à ma question ;-)
      3. salut l'amie20j !! ;-)

        en php ? comment ca ?

        je met sa dans mon fichier /etc/postfix/header_checks que j'ai préalablement créer suite a la lecture de plusieurs poste

        JONIPERDU lol
      4. Modérateur
        je met sa dans mon fichier /etc/postfix/header_checks

        Ok, mais tu mets avec quoi?
        Script shell, script perl, script php?
        Il faut savoir quelle application utilise les regex.

        pcre ne désigne qu'un type des regex compatible avec perl, mais si tu ne fais pas en perl alors tu fais avec quoi?

        Montre tes tests?
    3. l'ami20j
      Ok, mais tu mets avec quoi?
      Script shell, script perl, script php?
      Il faut savoir quelle application utilise les regex.
      

      désolé l'ami je suis pas encore calé en la matière pour te répondre correctement.
      ce que je sais c'est que postfix doit utiliser cette regex pour filtré les mails sortants et donc REPLACE les mots définits.

      sous putty j'ai créer ce fichier "/etc/postfix/header_checks" et j'écris la regex dedans...

      zipe31
      merci pour ce lien c'est exactement ça.
      mon souci est pour construire cette règle, je n'y arrive pas, j'arrive a replacer la ligne entière avec :
      /^Received:.*\[192\.168\.0\.[0-9]/   REPLACE  Received  from mail.MON-SERVEUR-SMTP.com
      

      qui détecte toutes lignes contenant 192.168.1.2 et la remplace par Received from mail.MON-SERVEUR-SMTP.com
      je doit donc construire cette règle avec les bonnes regex pour ne pas remplacer toute la ligne....
      1. Modérateur
        Ok.

        Mais tu ne donnes pas la ligne complète alors.

        Dans ton premier message tu dis

        from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)

        et puis tu cherche une ligne qui commence avec Received

        Bref, ta regex ne va jamais fonctionner.
        Il faudra que tu donnes le contenus correct des données en entrée.
      2. Modérateur
        En plus entre IP et Authenticated sender il y a des choses qu'on ne voit pas dans ta regex

        \[192\.168\.0\.[0-9]\(Authenticated sender
    4. Modérateur
      mon souci est pour construire cette règle, je n'y arrive pas, j'arrive a replacer la ligne entière avec : 
      
      /^Received:.*\[192\.168\.0\.[0-9]/   REPLACE  Received  from mail.MON-SERVEUR-SMTP.com 
      
      
      qui détecte toutes lignes contenant 192.168.1.2 et la remplace par Received from mail.MON-SERVEUR-SMTP.com 


      Je ne crois pas.
      Dans ta regex tu cherches et les lignes contient 1 (voir en gras

      de mon coté voila ou j'en suis :

      /^Received:.*\[192\.168\.0\.[0-9]\(Authenticated sender:.*\)\s+(.*by mail\.MON\-SERVEUR\-SMTP\.com[^\n]+ESMTPSA .*)$/im REPLACE from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMPT

      et ca ne fonctionne pas, il doit y avoir une erreur dans ma ligne.
      une idée ?


      Oui, t'arrêtes de boire quand tu fais des regex ;-DDD

      - tu cherches ESMTPA mais dans regex tu mets ESMTPSA
      - pour ip dans 192.168 je te conseille d'utiliser 192\.168\.\d{1,3}\.\d{1,3}
      - pourquoi tu mets de backslash avant les tiret?
      - dans ton message initial tu dis que tu veuilles obtenir ceci mais tu changes id et aussi l'heure. C'est normal?
      - c'est quoi le crochet avant 192?

      Quelque chose comme ça, mais je ne suis pas convaincu, il faudrait que tu dises exactement ce que tu veux remplacer exactement et avec quoi.
      A vrai dire ce que tu demande c'est relativement simple.
      Ce n'est pas la construction de la regex qui me pose de problèmes mais la façon dont elle est utilisé. Je ne connais pas headers_check

      /^Received:.*192\.168\.\d{1,3}\.\d{1,3}.*\(Authenticated sender:.*\)\s+by mail\.MON-SERVEUR-SMTP\.com.*ESMTPA.*$/      REPLACE       from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMPT


      GNU/Linux:Linux is Not Ubuntu! Quel linux choisir ne veut pas dire votre Distribution préférée,
      106485010510997108
      1. déjà , merci de prendre de ton temps pour mon problème.

        Dans ton premier message tu dis
        from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)

        et puis tu cherche une ligne qui commence avec Received

        en faite "Received " est forcément avant le "from" c'est un des header des mails envoyés.

        donc quand je fait /^Received:.*\[192\.168\.0\.[0-9]/ REPLACE Received from mail.MON-SERVEUR-SMTP.com sa prend tout ce qui est après "Received: 192.168.1.2" , pour plus de clarté voici la ligne complète :

        Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)


        donc /^Received:.*\[192\.168\.0\.[0-9]/ REPLACE Received from mail.MON-SERVEUR-SMTP.com fonctionne correctement. et transforme toute la ligne en Received: from mail.MON-SERVEUR-SMTP.com qui est après REPLACE de ma regex

        - tu cherches ESMTPA mais dans regex tu mets ESMTPSA
        effectivement une erreur de frape
        - pourquoi tu mets de backslash avant les tiret?
        car c'est plus jolie (lol)
        - dans ton message initial tu dis que tu veuilles obtenir ceci mais tu changes id et aussi l'heure. C'est normal?
        encore une erreur de ma part
        - c'est quoi le crochet avant 192?
        ça aussi c'est jolis :-)

        blague à part , voici exactement ce que je veux obtenir, tout ce qui est en gras doit être changer par la regex :

        Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)

        ce qui donne :

        Received: from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMTP id E67A58929974 for <xxx@xxx.com>; Sun, 20 Mar 2011 00:18:41 +0000 (GMT)

        j'espère que c'est déjà plus compréhensible comme ça
        1. Modérateur
          j'espère que c'est déjà plus compréhensible comme ça

          Pas toute à fait ;-)
          Regarde ce que j'ai souligné.

          Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)


          Ce ne sont pas les mêmes en-têtes (id et heure ont changé)
          C'est normal?

          Received: from mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMTP id E67A58929974 for <xxx@xxx.com>; Sun, 20 Mar 2011 00:18:41 +0000 (GMT)
          


          Il faut que je regarde comment fonctionnent, si jamais c'est possible, les captures des motifs avec headers_check
      2. oui c'est tout a fait normale

        chaque mail a forcément un ID différent
        chaque mail a forcément une heure d'envoi différente

        donc c'est deux information ne doive pas être changer par la regex et c'est la que ça coince pour moi ....
        1. je précise qu'il est possible de mètre plusieurs regex dans ce fichier, peut être que la solution la plus simple serait de faire deux regex différentes ?

          une première regex pour la première partie a changer 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx)

          et une deuxièmes regex pour la deuxièmes parties a changer ESMTPA

          ....
          1. Modérateur
            /^(Received:\s*from\s*)192\.168\.\d{1,3}\.\d{1,3}.*unknown.*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/      REPLACE       $1 mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1])${2}SMTP$3


            GNU/Linux:Linux is Not Ubuntu! Quel linux choisir ne veut pas dire votre Distribution préférée,
            106485010510997108
            1. fonctionne pas :-(

              je précise que le [xx.xxx.xx.xx] dans le header original est une adresse ip....
              1. Modérateur
                peu importe xx.xxx.xxx.xx puisque .* reconnaît tout

                Regarde mon test, on voit que tout est modifié correctement
                lami20j@debian-acer:~$ cat joniperdu.pl 
                #!/usr/bin/perl
                
                while(<DATA>){
                  s/^(Received:\s*from\s*)192\.168\.\d{1,3}\.\d{1,3}.*unknown.*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/$1 mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1])$2SMTP$3/;
                  print;
                }
                __DATA__
                Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
                lami20j@debian-acer:~$ 
                lami20j@debian-acer:~$ perl joniperdu.pl
                Received: from  mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) by mail.MON-SERVEUR-SMTP.com (Postfix) with SMTP id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
                


                Bref, il faudrait que tu montres ce que tu obtiens pour voir ce qui ne va pas sinon on ne peux pas avancer.
            2. pour vérifier je test directement en m'envoyant un mail sur ma boite ymail ou il est possible d'analyser les header, avec ta regex il n'y a aucun changement, le header reste exactement le même

              quand je teste avec un truc simple comme :
              /^Received:.*\[192\.168\.0\.[0-9]/   REPLACE  Received  from mail.MON-SERVEUR-SMTP.com


              me header change correctement en :
              Received  from mail.MON-SERVEUR-SMTP.com


              comment tester la regex sans avoir a m'envoyer un mail a chaque fois ?
              j'ai vue que tu fait sa dans un .pl, tu peut m'expliquer ?
              1. Modérateur
                j'ai vue que tu fait sa dans un .pl, tu peut m'expliquer ?

                Ben, justement, dans le .pl ça marche puisque c'est directement du Perl

                Essaie comme ça

                /^(Received:\s*from\s*)192\.168\.\d{1,3}\.\d{1,3}.*unknown.*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/      REPLACE       "$1" mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) "$2" SMTP "$3"
              2. Modérateur
                Si ça ne marchera pas alors on va faire petit à petit pour voir ce qui ne passe pas.
              3. Modérateur
                Et encore une chose, enlève le crochet, il n'a rien à faire là.
                Il n'y a pas de crochet avec 192

                quand je teste avec un truc simple comme :
                /^Received:.*\[192\.168\.0\.[0-9]/


                Justement je suis vraiment étonné que ça marche
                Si c'est le cas alors il faudrait que tu m'envoie par mail l'entête puisque je dois comprendre que lorsque tu colles sur ccm ça ne passe pas le crochet
              4. je m'inspire de :

                http://www.starbridge.org/support/viewtopic.php?f=2&t=772 (bas de page)
                et
                http://tech.groups.yahoo.com/group/postfix-users/message/274241 (bas de page)

                ça a l'air de fonctionner pour eux ....
            3. RÉSOLU

              my name is jonigood

              winer is l'ami20jgood verry goooooood !

              merci a toi tu a trouver la bonne regex (pas facile tout de même)

              le mot de la fin est :

              /^Received:\s*(from\s*)192\.168\.1\.[0-9].*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/      REPLACE       Received: $1 mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) $2 SMTP $3 


              a bientôt et merci a tous

              petite précision , il fallait mètre Received: après le REPLACE et "\d" n'est pas pris en compte, il fallait donc "[0-9]" a la place
              1. Modérateur
                Re,

                De rien.
                Pour la fin de l'histoire ;-)

                comment tester la regex sans avoir a m'envoyer un mail a chaque fois ?
                Effectivement s'envoyer à chaque fois un mail ce n'est pas le top.

                Voici une manière de tester la regex sans avoir besoin de s'envoyer à chaque fois un mail.
                La commande est (à faire en root)
                postmap -q - regexp:/etc/postfix/header_checks < fichier_qui_contient_l'en_tête


                On constate effectivement que la classe de caractères \d n'est pas reconnue, la commande ne retourne rien

                :~$ cat /etc/postfix/header_checks 
                /^Received:\s*(from\s*)192\.168\.1\.\d.*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/      REPLACE       Received: $1 mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) $2 SMTP $3 
                ~$ cat test_head 
                Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
                ~$ sudo postmap -q - regexp:/etc/postfix/header_checks < test_head 
                ~$ 
                


                Si on mets [0-9] ça fonctionne.
                Cette fois en revanche la commande retourne le contenu de fichier et la chaîne de remplacement obtenu grâce à la regex

                ~$ cat /etc/postfix/header_checks 
                /^Received:\s*(from\s*)192\.168\.1\.[0-9].*\(Authenticated sender:.*\)(\s+by mail\.MON-SERVEUR-SMTP\.com.*)ESMTPA(.*)$/      REPLACE       Received: $1 mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1]) $2 SMTP $3 
                ~$ cat test_head 
                Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)
                ~$ sudo postmap -q - regexp:/etc/postfix/header_checks < test_head 
                Received: from 192.168.1.2 (unknown [xx.xxx.xx.xx]) (Authenticated sender: xxxxxx) by mail.MON-SERVEUR-SMTP.com (Postfix) with ESMTPA id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)	REPLACE       Received: from  mail.MON-SERVEUR-SMTP.com (localhost.localdomain [127.0.0.1])  by mail.MON-SERVEUR-SMTP.com (Postfix) with  SMTP  id 1E-65424927097 for <xxx@xxx.com>; Sun, 20 Mar 2011 02:18:43 +0000 (GMT)