Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 24/03/2008, à 12:29

sebg38

Récupérer en-tête mail - sed ?

Bonjour,

Je souhaite envoyer une liste des messages classés spam. Pour cela, je voudrais récupérer une partie des en-tête des messages : les champs From, Subject et X-TRASH dans cette ordre et si ils existent.

Un exemple vaut mieux qu'un long discours. Si le fichier de mail contient :

From: Toto <toto@toto.fr>
To: Tata <tata@tata.fr>
Subject: FELICITATION
X-TRASH: Regle 1

blabla

Subject: Bonjour
From: Tata <tata@tata.fr>
To: Toto <toto@toto.fr>

blabla

Je voudrais obtenir :

  -- De :  Toto <toto@toto.fr>
        Objet :  FELICITATION
        Règle :  Regle 1
  -- De :  Tata <tata@tata.fr>
        Objet :  Bonjour

Pour le moment, j'utilise (le fichier s'appelle Spam) :

grep -Ei '^(From:|Subject:|X-TRASH:)' Spam | sed -e "s/^From:/  -- De : /;s/^Subject:/        Objet : /;s/^X-TRASH:/        Règle : /"

mais évidemment ça ne marche pas car les champs From: et Subject: ne sont pas dans le bon ordre pour le 2ième mail. J'obtiens :

  -- De :  Toto <toto@toto.fr>
        Objet :  FELICITATION
        Règle :  Regle 1
        Objet :  Bonjour
  -- De :  Tata <tata@tata.fr>

J'ai cherché un peu mais j'avoue que je ne suis pas un pro du sed ...
Si vous avez des idées, je suis preneur. D'avance merci,

seb

Hors ligne

#2 Le 24/03/2008, à 19:09

Saito

Re : Récupérer en-tête mail - sed ?

Bonjour,

je n'ai pas trouvé de one-liner avec sed ( quoique ce soit peut-être faisable ) mais à la place j'ai fait un script bash qui donne bien la sortie que tu veux.

#!/bin/bash

from= 
subject= 
regle= 

echo Traitement du fichier "$1"...
function formatage 
{
    echo -e "$@" | sed -e "s/^From:/  -- De : /;s/^Subject:/        Objet : /;s/^X-TRASH:/        Règle : /"
}

while read line
do
[[ $from != '' && $subject != '' ]] && \
[[ $line == From:* || $line == Subject:* ]] && \
formatage $from"\n"$subject"\n"$regle"\n" && \
{ from= ; subject= ; regle= ;}

case $line in
 From:*) [[ -z $from ]] && from=$line
        ;;
 Subject:*) [[ -z $subject ]] && subject=$line
        ;;
 X-TRASH:*) [[ -z $regle ]] && regle=$line
        ;;
esac
done < <(grep -Ei '^(From:|Subject:|X-TRASH:)' "$1")

formatage $from"\n"$subject"\n"$regle"\n"

exit 0

Ca vaut ce que ça vaut, teste-le et vois si ça te convient smile
( Tu dois passer le nom du fichier que tu veux traiter comme premier argument, «./mon_script.sh mes_mails» )


Aku-Soku-Zan_Shinsengumi

Hors ligne

#3 Le 25/03/2008, à 01:16

Laurent82

Re : Récupérer en-tête mail - sed ?

astucieuse l'idée Saito !

Si vous voulez vraiment du one-liner, c'est possible avec awk (en reprenant l'idée de Saito):

awk '$1 ~ /^(From:|Subject:|X-TRASH:)/ {from="--De :" ; trash="\tRègle :" ; subject="\tObjet :" ; sub("From:",from); sub("Subject:",subject); sub("X-TRASH:",trash) ; if((de!="" && objet!="")&&($0 ~ from"|"subject)) {global=global"\n"de"\n"objet"\n"regle"\n" ; de="";objet=""; regle=""} ; if($0 ~ from) de=$0 ; else if($0 ~ subject) objet=$0 ; else regle=$0 } END { print global"\n"de"\n"objet"\n"regle }' Spam

Bah quoi roll

Blague à part, une fois mis en forme et écrit correctement, il y a des chances que l'opération soit un peu plus rapide avec awk

#4 Le 25/03/2008, à 11:31

sebg38

Re : Récupérer en-tête mail - sed ?

Excellente idée Saito, c'est exactement ce que je voulais. Merci. Je n'avais même pas penser à faire un script bash. J'ai juste modifié un peu pour ne pas avoir de \n quand le champ n'est pas présent. Ça marche parfaitement.
Je n'ai pas encore regardé et déchiffré la proposition one-liner de Laurent. Je vais regarder ça.

Sinon, j'ai une question un peu similaire. Comment remplacer tous les _ par des espaces uniquement s'ils sont compris entre deux balises =? et ?=.

Un exemple :

=?to_to_to?= to_to

doit donner

=?to to to?= to_to

J'ai essayé plusieurs trucs dont

echo -e "=?to_to_to?= to_to" | sed -e 's/=?\([^`?=`]*\)_\([^'?=']*\)?=/=?\1 \2?=/g'

et

echo -e "=?to_to_to?= to_to" | sed -e 's/=?\([^`=?`]*\)_/=?\1 /g'

et à chaque fois ça ne marche pas, ça ne remplace que le dernier _, j'obtiens

=?to_to to?= to_to

Cà doit être tout bête mais je ne vois pas. Des idées ?

seb

Hors ligne

#5 Le 25/03/2008, à 11:35

Laurent82

Re : Récupérer en-tête mail - sed ?

Saito (ou les autres bien sûr)

Sais-tu pourquoi si je remplace dans ton script :

< <(grep -Ei '^(From:|Subject:|X-TRASH:)' "$1")

par

grep -Ei '^(From:|Subject:|X-TRASH:)' "$1" | while read line

ça ne fonctionne plus bien ? En fait ça fonctionne sauf pour le dernier message qui passe à la trappe.

Pourtant en théorie le résultat devrait être le même non ?

#6 Le 25/03/2008, à 14:51

Alain.g

Re : Récupérer en-tête mail - sed ?

Bonjour

sebg38 a écrit :

Sinon, j'ai une question un peu similaire. Comment remplacer tous les _ par des espaces uniquement s'ils sont compris entre deux balises =? et ?=.

Avec perl :

echo =?to_to_to?= to_to | perl -pe 's/=\?.*?\?=/($a=$&)=~s,_, ,g,$a/eg'

Si les balises ouvrante et fermante peuvent être sur une ligne différente, il faut passer un "mode" multi-ligne avec -0777 (tout le fichier comme une ligne) ou -00 (paragraphe comme une seule ligne) par exemple

echo -e "=?\nto_to_to\n?= to_to" | perl -0777pe 's/=\?.*?\?=/($a=$&)=~s,_, ,g,$a/seg'

Dernière modification par Alain.g (Le 31/03/2008, à 11:51)


Xubuntu Karmic !

Hors ligne

#7 Le 25/03/2008, à 15:00

Saito

Re : Récupérer en-tête mail - sed ?

@Laurent82: Non c'est diffèrent ( et je me suis fait avoir aussi smile ) car bash exécute la partie droite d'un pipe dans un sous-shell (alors que pour zsh, mon shell de prédilection, c'est la partie gauche), du coup le dernier message que tu affiches étant extérieur à ce sous-shell, les variables sont telles qu'elles ont été définies en dehors du sous-shell, c'est-à-dire vides au début du script. Alors qu'avec le process substitution, c'est le grep qui sera lancé dans un sous-shell.
Sinon, joli one-big-liner avec awk!

@sebg38
J'ai une solution pour ton problème de toto, aimablement fournie par ramok sur le channel #sed de freenode que je remercie:

echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=*\)_\([^?]*?=\)/\1 \2/;tz'

A toi de choisir entre cette solution et celle en Perl d'Alain.g

Dernière modification par Saito (Le 25/03/2008, à 19:25)


Aku-Soku-Zan_Shinsengumi

Hors ligne

#8 Le 25/03/2008, à 21:03

Alain.g

Re : Récupérer en-tête mail - sed ?

J'avoue que je ne comprends pas complètement cette solution avec sed, je vais regarder de plus près, mais si elle fonctionne dans cet exemple précis, dès qu'on ajoute un point d'interrogation ça ne va plus :
Par exemple :

echo 'to_to =?to_to?_to_?= to_to' | sed -e ':z;s/\(=*\)_\([^?]*?=\)/\1 \2/;tz'

renvoie : to_to =?to_to? to ?= to_to

Dernière modification par Alain.g (Le 25/03/2008, à 22:14)


Xubuntu Karmic !

Hors ligne

#9 Le 25/03/2008, à 22:44

Saito

Re : Récupérer en-tête mail - sed ?

Oui exact, j'ai modifié cette version et ça a l'air de mieux marcher:

echo 'to_to =?to_to?_to_?= to_to' | sed -e ':z;s/\(=?.*\)_\(.*?=\)/\1 \2/;tz'

Edit: Mea culpa, en fait j'ai fait une erreur de copie, la solution donnée par ramok était celle-ci.

Dernière modification par Saito (Le 25/03/2008, à 22:53)


Aku-Soku-Zan_Shinsengumi

Hors ligne

#10 Le 25/03/2008, à 23:37

Alain.g

Re : Récupérer en-tête mail - sed ?

oui mais du coup ça ne fonctionne plus avec ton premier texte hmm

echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=?.*\)_\(.*?=\)/\1 \2/;tz'

donne : to_to =?to to to ?= to to =?to to to?= to_to


Xubuntu Karmic !

Hors ligne

#11 Le 26/03/2008, à 00:24

Saito

Re : Récupérer en-tête mail - sed ?

Hihi, en effet, par défaut les quantifieurs de sed sont greedy, et il n'y pas moyen de les rendre stingy... Donc à priori, on ne peut traiter ce cas qu'en modifiant ainsi:

echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=?.*\)_\([^?]*?=\)/\1 \2/;tz'

ce qui revient presque à ce que j'avais dis avant mais qui ne convient toujours pas si il y existe un «?» entre =? et ?=. Mais c'est le seul moyen d'éviter que le premier «.*» ne mange tout.

Dernière modification par Saito (Le 26/03/2008, à 00:27)


Aku-Soku-Zan_Shinsengumi

Hors ligne

#12 Le 26/03/2008, à 22:41

sebg38

Re : Récupérer en-tête mail - sed ?

Bonjour,

Merci pour toutes vos réponses. Ma deuxième question n'était donc pas si simple que ça, et pour le coup perl est gagnant par rapport à sed. Je ne connais pas du tout perl, il va falloir que je m'y mette, ça m'a l'air vraiment efficace. Vous connaissez un bon tuto pour commencer ?

seb

Hors ligne

#13 Le 27/03/2008, à 11:04

philou8237

Re : Récupérer en-tête mail - sed ?

oui : http://sylvain.lhullier.org/publications/perl.html

Bonne doc, bien rédigée (en meme temps c'est sylvain qu'il l'a faite alors bon....) wink

Hors ligne

#14 Le 27/03/2008, à 21:54

sebg38

Re : Récupérer en-tête mail - sed ?

Merci, c'est noté.

Hors ligne