Preparation de la page….

Objectif

  • Avoir une passerelle de mail qui
    • Decomptamine les mails
    • TAG les spams
    • Permet le TLS
    • Permet le SMTP Auth (sur une base non local)
    • Proxys l'imap(s) et le pop3(s) (car pas de mail en local)

Fonctionnement de Postfix

(Merci toniotonio que je copie colle depuis https://forum.ubuntu-fr.org/viewtopic.php?id=161292 )

L’ordre global d’application est le suivant :

  1. SMTPD Restrictions
  2. Header/body Checks
  3. Content Filter

Postfix établit 5 étapes de tests (stages) au niveau des SMTPD Restrictions qui correspondent chacune à une commande SMTP :

Test cote postfix Vue SMTP
smtpd_client_restrictions connection du client
smtpd_helo_restrictions HELO
smtpd_sender_restrictions MAIL FROM
smtpd_recipient_restrictions RCPT TO
smtpd_data_restrictions DATA

Par defaut Postfix est configuré pour évaluer les tests au moment de la commande RCPT TO, donc dans la section smtpd_recipient_restrictions.

C’est à dire que le blocage n’interviendra qu’au moment ou le client envoie la dernière commande.

A l’intérieur d’un restriction stage il existe des access lists. Dès qu’une de ces access lists renvoient OK, on passe au stage suivant. (la fin d’un stage par défaut est PERMIT)

Si une access list renvoie REJECT le message est bloqué. Si une access list ne matche pas, on passe a l’access list suivante dans le stage. (DUNNO)

Rajouter des logs

Dans certains cas on peut avoir besoin de loguer certaines caracteristiques des mails… (et voire meme faire d'autres actions Rejets…)

  1. Dans le main.cf on rajoute header_checks = regexp:/etc/postfix/header_checks
  2. Dans le /etc/postfix/header_checks on rajoute /^Subject:/ WARN

Ainsi tout les sujets des mail seront dans les logs Warning :)

Modifier les sujets des mails

A manier avec bcp de precaution (cela peu, forcement, quelque peu indisposer la signature et/ou le chiffrement des mails)

  1. Dans le main.cf on rajoute header_checks = regexp:/etc/postfix/header_checks
  2. Dans le /etc/postfix/header_checks on rajoute /^Subject:(.*?)/ REPLACE Subject: [OK] $1

Creer un trou noir, ils ne recevront plus de mails

  1. Dans la meme lignée que les 2 precedent, dans le header_checks /^To:.*@*.example.lan/ REJECT Sorry we have lost example.lan destination

Ne pas saturer les SMTP des destinataires

#option devant permettre de ne pas saturer le povre mx de wanadoo
smtp_destination_concurrency_limit = 2

Ne pas se faire saturer par des vilains

# à partir de 2 erreurs, chaque erreur impose un délai de 65 secondes
smtpd_soft_error_limit = 1
smtpd_error_sleep_time = 65s
# à la 4è erreur Postfix coupe la session
smtpd_hard_error_limit = 3
# une adresse IP ne peut ouvrir que 3 sessions en parallèle
smtpd_client_connection_count_limit = 3
# une adresse IP ne peut ouvrir que 3 sessions sur le délai de 2 minutes
smtpd_client_connection_rate_limit = 3
smtpd_anvil_rate_time_limit = 2
###unknown_address_reject_code = 550
# les clients qui ne respectent pas le protocole: dehors !
smtpd_helo_required = yes
strict_rfc821_envelopes = yes
###smtpd_delay_reject = yes

Anti-Spam/Virus

GreyListing

Traitement des queues

Changement de queue d'un mail a l'entrée

  • Ici on ne desirais QUE traiter sur le TO

Quelques Urls rigolotes:

Configuration

A rajouter dans le main.cf

smtpd_recipient_restrictions = check_recipient_access hash:/etc/postfix/recipient_restrictions
Creer le fichier comme suit

moche@vilainpas.beau  DISCARD
mafia.gang REJECT
gentilsdeconnecters HOLD

Traitement de la queue obtenue

  1. vidage de la queue de hold : postsuper -d ALL hold
  2. consultation de la queue de hold : qshape hold

Authentification

Mails entrants sur le Postfix

Etant donné que je prefere que ce serveur de decontamination/relayage soit indepedant, il n'appuirais pas son auth en local…

  • Ici, il ne s'agit pas de TLS mais de mail authentifié en mail relais

disable_vrfy_command = yes
smtpd_sasl_auth_enable=yes
broken_sasl_auth_clients=yes
smtpd_sasl_local_domain =
smtpd_sasl_application_name = smtpd
smtpd_sasl_security_options = noanonymous
###smtp_sasl_mechanism_filter = PLAIN LOGIN ANONYMOUS
smtp_sasl_mechanism_filter = PLAIN LOGIN
smtpd_sasl_authenticated_header = yes

FIXME et maintenant expliquer sur quoi on base l'auth ;)

Mails sortants sur par le Postfix

# sets gmail as relay
relayhost = [smtp.gmail.com]:587
#  use tls
smtp_use_tls=yes
# use sasl when authenticating to foreign SMTP servers
smtp_sasl_auth_enable = yes 
# path to password map file
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
# list of CAs to trust when verifying server certificate
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
# eliminates default security options which are imcompatible with gmail
smtp_sasl_security_options =

cat /etc/postfix/sasl_passwd
[smtp.gmail.com]:587  username:password

postmap /etc/postfix/sasl_passwd
chown postfix sasl_passwd*
/etc/init.d/postfix reload

smtp_use_tls=yes in main.cf
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

TLS

TLS In

  • Configuration du TLS

smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache

  • Pour permettre de recevoir des mails pas forcement en TLS, on configure le TLS “a la demande du client”

smtpd_tls_security_level = may
smtpd_tls_auth_only = no
# Decommenter la ligne suivante pour accepter _uniquement_ le traffic en tls
#smtpd_enforce_tls = yes

  • Il est possible d'authentifier les mails entrant par leur certificat

#smtpd_tls_CAfile = /etc/postfix/cacert.pem
# Si on veut authentifier les autres, il faut indiquer ou trouver les certificats
# des CA :
#smtpd_tls_CApath = /etc/ssl/certs

  • Pour verifier si le traffic est bien en TLS nous loggons ds les header SMTP et dans les logs standard

smtpd_tls_received_header = yes
smtpd_tls_loglevel = 1

  • Le TLS n'est securisé que si les clefs sont aleatoire et non conserves

smtpd_tls_session_cache_timeout = 3600s
tls_random_source = dev:/dev/urandom

TLS Out

  • Pour rendre le TLS efficace il faut un peu de hasard…

tls_random_source = dev:/dev/urandom
smtp_tls_session_cache_timeout = 3600s

  • Activation du TLS

smtp_use_tls = yes

  • Rajout dans les logs de l'activation du TLS

smtp_tls_loglevel = 1

  • Certificats TLS sortant

smtp_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtp_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

  • Pour faire du TLS en fnc de la destination

Nous ne forcons pas le traffic TLS sortant, car si la cible dysfonctionne… pour forcer le TLS en fonction de la destination

Relayage de (sous) domaine

Le relayage pure peut induire des problematiques de NPAI, cad

  1. des mails arrivent sur des emails qui n'existent pas sur les domaines que vous relayes
  2. vous, vous les acceptez
  3. le serveur a qui vous les relayez les refuse directement (RCPT TO refusé, car mbox inexistante)
  4. et vous, vous tentez d'envoyer un user uknown (npai) a l'emetteur “d'origine”
  5. ca tombe mal, l'emetteur d'origine c'est un spammeur… il existe pas vraiment… et parf… ca s'empile
  6. vous vous faites blacklister…

A cela 2 parades…

  1. vous déclarer une liste completes des alias et emails que vous relayez (cf relay_recipient_maps)
  2. utiliser le demon verify (a ne pas confondre avec la commande VRFY a manipuler avec trop de precautions)
    1. Ce service va générer un cache des emails existant ou non sur du serveur cible
    2. Ce cache est généré a la volé en initiant en même temps que le mail entrant, un dialogue avec le serveur de mail final

Doc issue de http://forum.ubuntu-fr.org/viewtopic.php?id=299249, mais je recommande de lire les docs de postfix, notament pour mieux appréhender les TTL du cache…

De plus pour avoir teste, si un flux SMTP est a destination de plusieurs emails, et que l'une d'entre elle est inexistante, le mail n'est refusé _que_ pour celle si !

Mise en œuvre du verify

  1. Penser a avoir un postfix correctement configurer, sinon, vous n'aurez aucune email qui fonctionnera… (le check par le device distant pourrait être refusé
  2. A rajouter dans le main.cf la clause check_recipient_access hash:/etc/postfix/verify_domains, après le reject_unauth_destination, dans smtpd_recipient_restrictions
  3. Le fichier de cache peut sembler se reseter tout seul
    1. A lire, mais bon a mon avis l'erreur est ailleurs : http://www.debian-fr.org/erreur-dans-le-log-t40633.html
      1. address_verify_map = hash:$data_directory/verify_cache
    2. Me semble plus concret, selon la Address verification database/Note 3 de la doc officielle de postfix, le fichier est ouvert, puis verify chroot.
      1. Donc forcement, il trouve plus le fichier correctement
      2. Alors probablement il se suicide
      3. Tel le phénix, il reviens, mais avant le chroot il reouvre le fichier
      4. Donc, forcement, il trouve plus le fichier…
    3. Je préconise, via le master.conf d'interdire le chroot pour verify…
  4. Les domaines a vérifier doivent etre listes comme suis dans /etc/postfix/verify_domains :
    1. NDD reject_unverified_recipient
  5. On hash le fichier, on restart le postfix (pour la modif du main.cf)

Suivi du fonctionnement de verify

  1. Le fichier de cache est : /var/lib/postfix/verify_cache.db
  2. Il contient, grossierement, l'heure d'integration de l'email, l'email, le statut

Acceder a ce fichier

Prg issue de http://mail.pm.org/pipermail/za-pm/2005-June/000269.html Il s'agit d'un fichier de type “Berkeley DB (Btree, version 9, native byte-order)” Pour le lire en perl il sera agrable d'installer la lib libberkeleydb-perl

bdbmfile
#!/usr/bin/perl
# Filename: bdbmfile.pl
#
use BerkeleyDB;
use Fcntl;
 
die "Usage\n$0 dbmfile.pl\n" if (@ARGV < 1);
 
my $filename = $ARGV [0];
my %h;
tie %h, 'BerkeleyDB::Btree',
        -Filename       => $filename,
        -Flags          => DB_RDONLY
or die "Cannot open $filename $!\n";
 
my ($status,$null,$time,$msg);
 
my $init=0;
my $mod=0;
 
foreach (keys %h) {
        if(/^_LAST_CACHE_CLEANUP_COMPLETED_/) { $init=$h{$_}; }
        else {
                ($status,$null,$time,$msg)=split(/:/,$h{$_});
                print scalar(localtime($time));
                print " $status $_ =>".$h{$_}."\n";
                if($time>$mod) { $mod=$time; }
                }
        }
 
print "Last init ".scalar(localtime($init))."\n";
print "Last mod  ".scalar(localtime($mod))."\n";
untie %h;
exit;

Creation d'un nouveau transport

Déclaration du nouveau transport

nto unix  -       n       n       -       -       pipe
        flags= user=nobody argv=/usr/local/bin/nto.pl -s $sender -n $nexthop -r $recipient -u $user

Usage du nouveau transport

Ici, c'est par rapport a mon transport…

domaine_ou_email        nto:domaine_ou_email|rewrite,ressend,announce=/etc/postfix/announce.txt

  • après le pipe ce sont des paramètres
  • si pas de paramètres alors l'option ressend est implicite
  1. ressend: ça renvoie le mail vers le destinataire reel
  2. rewrite : ça réécris dans le ressend le To avec le nouveau destinataire
  3. annouce : ça envoie au sender du mail le contenu du fichier précisé avec :
    • En champs From, le nouveau nom
    • Des “variables” dans le fichiers qui peuvent être remplacés automatiquement :
      • SENDER sera remplacé par l'email de l'emetteur du mail
      • RECIPIENT sera remplacé par l'ancienne email qui doit etre reroutée
      • NEXTHOP vers ou elle doit etre rerouté
      • SUBJECT le sujet du mail qui declanche le reroutage

Exemple de /etc/postfix/annouce.txt

announce.txt
From: __RECIPIENT__
To: __SENDER__
Subject: [MAIL LOST] __SUBJECT__
MIME-Version: 1.0
Reply-To: __NEXTHOP__
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
User-Agent: Manual mail
 
 
Bonjour __SENDER__,
 
Nous sommes au regret de vous apprendre que __RECIPIENT__ a demenagé.
 
Maintenant il reside à __NEXTHOP__.
 
 
Cordialement,
Le ReDirecteur.

Le code du nouveau transport

nto
#!/usr/bin/perl
 
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
 
use strict;
use warnings;
use Getopt::Std;
use Net::SMTP;
 
# Configuration dans /etc/postfix/master.cf
# nto unix  -       n       n       -       -       pipe
#        flags= user=nobody argv=/usr/local/bin/nto.pl -s $sender -n $nexthop -r $recipient -u $user
#
# Configuration dans la transportable
#       email/domaine        nto:email/domaine|ressend,announce=/etc/postfix/announce.txt
#       email/domaine           email/domaine | parametres
# Parametres:
#       ressend (par defaut, sauf si announce present), envoie le mail retravaillé pour le destinataire reel
#       annouce=fichier envoie au sender un mail comme quoi l'utilisateur a demenagé
#               Les entrees __SENDER__ __RECIPIENT__ __NEXTHOP__ et __SUBJECT__ seront automatiquement reecrite
#               TODO un lock pour ne pas renvoyer 2 fois au meme emetteur l'annonce de demenagement
#       rewrite (par defaut desactivé) reecris dans le header tout les recipient par des nexthop
 
 
my %opt;
getopts( "s:n:r:u:", \%opt );
my $subject;
my $inbody=0;
my $body="";
my $header="";
my $smtpserver="localhost";
my $smtpport=25;
my %cfg;
 
my ($nexthop,$params)=split(/\|/,$opt{n},2);
$opt{n}=$nexthop;
 
 
my $i=0;
if(defined($params)) {
        foreach (split(/,/,$params)) {
                my ($clef,$val)=split(/=/);
                if(!defined($val)) { $val=1; }
                $cfg{$clef}=$val;
                $i++
                }
        }
if(($i==0) or defined($cfg{rewrite})) {  $cfg{ressend}=1; }
if(defined($cfg{announce}) and ($cfg{annouce}==1)) {
        $cfg{announce}="/etc/postfix/announce.txt";
        }
 
if(!($opt{n} =~ m/@/)) { $opt{n}=$opt{u}."@".$opt{n}; }
 
 
while(<STDIN>) {
        if(/^$/) { $inbody++; }
        if(!$inbody) {
                $header.=$_;
                if(/^Subject/) {
                        chomp();
                        $subject=$_;
                        $subject=~s/^Subject: //g;
                        }
                }
        else    {
                $body.=$_;
                }
        }
 
if($cfg{ressend}) {
        if($cfg{rewrite}) { $header=~s/$opt{r}/$opt{n}/g; }
 
        my $smtp = Net::SMTP->new($smtpserver, Port=>$smtpport, Timeout => 10, Debug => 1); die "Could not connect to server!\n" unless $smtp;
        ###$smtp->auth($smtpuser, $smtppassword);
        $smtp->mail($opt{s});
        $smtp->to($opt{n});
        $smtp->data();
        $smtp->datasend($header."\n".$body);
        $smtp->quit;
        }
 
if(defined($cfg{announce}) and (-r $cfg{announce})) {
        my $mail="";
        open(ANN,"<".$cfg{announce});
        while (<ANN>) {
                $mail.=$_;
                }
        close(ANN);
 
        $mail=~s/__SENDER__/$opt{s}/g;
        $mail=~s/__RECIPIENT__/$opt{r}/g;
        $mail=~s/__NEXTHOP__/$opt{n}/g;
        $mail=~s/__SUBJECT__/$subject/g;
 
        my $smtp = Net::SMTP->new($smtpserver, Port=>$smtpport, Timeout => 10, Debug => 1); die "Could not connect to server!\n" unless $smtp;
        ###$smtp->auth($smtpuser, $smtppassword);
        $smtp->mail($opt{n});
        $smtp->to($opt{s});
        $smtp->data();
        $smtp->datasend($mail);
        $smtp->quit;
        }

Reecriture des emails entrants ou autre chose

postfix-pcre

La réecriture des emails va se faire au travers de regex, effectivement les tables de correspondance, c'est drole– a maintenir Donc a savoir :

  1. il faut installer postfix-pcre qui rajoute une lib dans /etc/postfix/dynamicmaps.cf
  2. a chaque modification de la table pcre, il faut reloader postfix (contrairement aux hash) merci dadu ;)

Tables canonicales (nb j'utilies autre chose maintenant)

Il existe 3 types de tables:

  1. canonical_maps là la methode la moins flexible
    1. Cette table fait par defaut dans tout les sens du mail…
  2. recipient_canonical_maps un peu moins barbare
  3. sender_canonical_maps pareil ;)

Ces 3 tables sont parametrables (modification et ou de l'envelope ou du header)

Un exemple

Que je ne recommande pas, vraiment pas, il reecrit _tout_ et par consequant ne sert plus a rien, generalement

Afin de reecrire les emails de la forme userX@domaine.tld en domaine.tld_userX la syntax est simple:

  1. Rajouter dans le main.cf la ligne canonical_maps=pcre:/etc/postfix/canonical
  2. Integrer dans /etc/postfix/canonical une ligne comme suit: /^(.*)@(domaine.tld)/ ${2}_${1}@mon_supper_domaine.tld
  • Les domaines peuvent etre declarés dans la transportable

Source Routing : Routage en fnc du From

  • Modification du main.cf

sender_dependent_default_transport_maps = hash:/etc/postfix/sender_relayhost

Evidement ce fichier peut en dehors d'etre renomé, etre hashé differement (en **regex** pex)
  • Contenu du fichier /etc/postfix/sender_relayhost

georges@oyesspamme.com smtpip:[smtp.free.fr]

Evidement //smtp.free.fr// peut pointer sur un smtp authentifé, etc. Bien sur on n'est pas obligé de mettre une email, un domaine, c'est faisable.
  • Modification du master.cf (creation de smtpip)

smtpip     unix -       -       n       -       -       smtp
    -o smtp_bind_address=10.0.12.31
    -o smtp_helo_name=FelixBis
    -o syslog_name=Felix2
    -o smtp_sasl_auth_enable=yes
    -o smtp_sasl_security_options=noanonymous
    -o smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
    -o smtp_use_tls=yes
    -o smtp_tls_CAfile=/etc/ssl/certs/ca-certificates.crt

  • 10.0.12.31 est une IP secondaire de la machine Felix

Et un grand merci à :

Serveur de messagerie

  • Script pour permettre des essais personnel cf XXX+echoping@example.com
  • Mise en place uucp
  • Forcer (a la hache) le MailDir
  • Mise en place de connecteurs supplementaires

Echo ping

Et voici la recette miracle a mettre dans le .procmailrc ne pas oublier cependant de creer le fichier local/mail/procmail/echo-reply avec le joli texte que l'on veux…

rc-echoping
:0Hhb
* ^TOuser\+ping@domaine.tld.org
* !^FROM_DAEMON
* $!^X-Loop: $LOOP_TAG
| (tempfile=`mktemp`; cat - > $tempfile; cat $tempfile | \
     formail -r -k -A'Precedence: junk' \
        -A'Auto-Submitted: auto-replied' \
        -A'MIME-Version: 1.0' \
        -A'Content-type: text/plain; charset=US-ASCII' \
        -A"X-Loop: $LOOP_TAG" \
        -A"From: postmaster@$MYDOMAIN (Echo automatic service)" ; \
        cat $HOME/local/mail/procmail/echo-reply; \
        echo ""; echo "Your original message:"; echo ""; \
        cat $tempfile; rm $tempfile) \
      | $SENDMAIL -t

ReImporter des mails - FetchMail

Objectifs:

  • Recuperer les mails d'un serveur tier (ou pas)
  • Les faires filtrer par notre systeme de messagerie préalablement décris
  • Pouvoir les discerner (en tant qu'utilisateur final) du reste des flux de mail

Donc, un fetchmailrc

fetchmailrc-example
server pop.fai.tld
        protocol POP3
        username monuserchezlefai
        password motdepassesupercomplique
        fetchall mimedecode
        ssl
        is monuserdemondimaine+fai@mondomaine.tld
        smtphost smtp.mondomaine.tld

Tester l'AV mis en place

  1. On ne peut avoir son virus eicar sous forme de fichier ⇒ l'AV local l'effacerais
  2. FIXME Ce script est a refaire maintenant… il est bien vieux

Chaines de tests

  • Viral (Eicar)
X50 !P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
  • Spam

Script a refaire car vieux

sendvirus
#!/bin/bash
 
email=$1
serversmtp=$2
domaine=`echo $email | cut -f2 -d"@"`
vise=postmaster@domaine.tld
 
if [ x$1 == x ]; then
    echo "Il faut au moins un parametre : l'email a tester"
    exit
    fi
if [ x$2 != x ]; then
    echo "La foncionnalitee d'utiliser un autre MX n'est pas encore la"
    exit
    echo "MX utilisé : $serversmtp"
    fi  
echo "Envoie le virus a : $email"
echo "Donc aux serveurs de : $domaine"
echo " "
echo "Emission"
 
dig MX $domaine +noall +answer | grep "^$domaine" | tr -s "\t " " " | cut -d" " -f6 | while read serversmtp
do      
    echo "  --> $serversmtp"
 
expect 2>&1 >/dev/null <<__EOF__
spawn telnet $serversmtp smtp
set timeout 60
expect "220 "
send "helo eicar-test-adlp.org\r"
expect "250 "
send "mail from: <$vise>\r"
expect "250 "
send "rcpt to: <$email>\r"
expect "250 "
send "data\r"
expect "354 "
send "From: <$vise>\r"
send "To: <$email>\r"
send "Subject: Test virus sur relais $serversmtp\r"
send "\r\r"
send "Utilsation du relais $serversmtp"
send "Debut d'emission du virus\r"
####### X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
send "\130\065\117\041\120\045\100\101\120\133\064\134\120\132\130\065"
send "\064\050\120\136\051\067\103\103\051\067\175\044\105\111\103\101"
send "\122\055\123\124\101\116\104\101\122\104\055\101\116\124\111\126"
send "\111\122\125\123\055\124\105\123\124\055\106\111\114\105\041\044"
send "\110\053\110\052"
send "\r"
send "Fin d'emission du virus\r"
send "\r"
send ".\r"
close
__EOF__
 
    done

Liens interessants

Outils de maintenance

Traitement mailqon1line pour aider a traiter la mailq

Script en 1 ligne, ultra simplifié

mailq | perl -ne 'chomp();s/^$/\n/g;s/^-.*//g;print $_;'
  • gestion de la queue
    • mettre en hold un mail : postsuper -h <id>
    • suppression d'un mail des queues : postsuper -d <id>
    • lecture d'un mail : postcat -q <id>
  • le script
readmailq
#!/usr/bin/perl
 
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
# Versions
#   1.0 Make a first script who just transform the result of mailq
#       in a one line per mail
#   2.0 Add hability to read mail data from postcat (from,to,subject,date)
#   2.1 Add filtering options (from && to)
#   2.2 Add --delete and --hold option
#   2.3 Add first smtp server sender (and filtering)
#   2.4 Add Help
#   2.5 Add --stat options (who print information by from,to,smtp)
#   TODO: for stat option try to give msgid
#         cleaning the code, (variable name, frenglish, key hash name cf 'From: ')
#         adding an option to give information from logs
#         maybe add an option to do the postcat -q msgid ?
use strict;
use warnings;
use Data::Dumper;
use Getopt::Long;
 
sub trait1msqid {
    my ($id,$tab,$del,$hol)=@_;
 
    print $id.";".$$tab{"Received"}.";".$$tab{"From: "}.";".$$tab{"To: "}.";".$$tab{"Date: "}.";".$$tab{"Subject: "}."\n";
    if( (defined($del) and open(FR,"/usr/sbin/postsuper -d $id 2>/dev/null |"))
      or(defined($hol) and open(FR,"/usr/sbin/postsuper -h $id 2>/dev/null |")) ) {
        while(<FR>) {}
        close(FR);
        }
    }
 
sub getheader {
    my ($ret,$msgid,@toget)=@_;
    my $cont=1;
    my $totest;
    my $ligne;
 
    $$ret{Received}="";
    if(open(FR,"/usr/sbin/postcat -q $msgid 2>/dev/null |")) {
        while($cont and $ligne=<FR>) {
            if($ligne =~ /^$/) { $cont=0; }
            elsif($ligne =~ /^Received: from / and !($ligne =~ /localhost/)) {
                chomp($ligne);
                $ligne=~ s/^Received: from //g;
                $$ret{Received}=$ligne;
                }
            else {
                foreach $totest (@toget) {
                    if($ligne =~ /^$totest/ and !defined($$ret{$totest})) { 
                        chomp($ligne);
                        $ligne=~ s/^$totest//g;
                        $$ret{$totest}=$ligne;
                        }
                    }
                }
            }
        close(FR);
        }
    foreach(@toget) { if(!defined($$ret{$_})) { $$ret{$_}=""; } }
    }
 
sub testheader {
    my ($regex,$chaine)=@_;
    my $ret;
 
    if(defined($regex)) {
        if($chaine =~ /$regex/i)    { $ret=1; }
        else                        { $ret=0; }
        }
    else                            { $ret=1; }
 
    return($ret);
    }
 
sub dossomstat {
    my ($res,$id,$val)=@_;
    my $filtre;
 
    foreach $filtre (("Received","To: ","From: ")) {
        if(defined($$val{$filtre})) {   # FIXME Coder l'integration des msgID
            if(!defined($$res{$filtre}{$$val{$filtre}}{Nb})) {
                $$res{$filtre}{$$val{$filtre}}{Nb}=1;
                }
            else {
                $$res{$filtre}{$$val{$filtre}}{Nb}++;
                }
            }
        }
    }
 
open(MQ,"mailq 2>/dev/null |") or die "Impossible d'ouvrir la mailq...\n";
 
my $precline=<MQ>;
$precline="";
my %tab;
my $id;
my @null;
my %cou;
my %resstat;
my ($stat,$help,$SMTP,$FoT,$From,$To);
my ($actdel,$acthol);
GetOptions('Stat' => \$stat,'help' =>\$help,'SMTP=s'=> \$SMTP,
    'FromOrTo=s' => \$FoT, 'From=s' => \$From, 'To=s' => \$To, 'Delete' => \$actdel, 'Hold' => \$acthol );
 
if(defined($actdel) and defined($acthol)) { 
    print "Options incompatibles\n\n";
    $help=1;
    }
elsif((defined($actdel) or defined($acthol)) and !(defined($From) or defined($To) or defined($SMTP))) { 
    print "On ne peux holder ou deleter sans filtre\n\n";
    $help=1;
    }
 
if($help) {
    print "Fonctions disponibles: ./mailqon1line [--SMTP <srv>] [--FromOrTo <email>|[--From <email> |& --To <email>] [--Delete || --Hold]
  --SMTP %s     : Recherche les serveur SMTP emetteur
  --FromOrTo %s : Recheche dans le champs email from ou to
  --From %s     : Recheche dans le champs email from
  --To %s       : Recheche dans le champs email to
  --Delete      : Supprime le mail de la mailq
  --Hold        : Met dans la queue d'attente
  --Stat        : Ne renvoie des statistiques sur les memes filtres (desactive les options hold et delete)
";
    exit();
    }
 
 
while(<MQ>) {
    chomp();
    if(!/^--/) {
        tr/\t / /s;
        s/\*//g;
        if($precline eq "" and $_ ne "")    { #On va commencer une nouvelle ligne
            ($id,@null)=split(/ /,$_,2);
            $tab{$id}{mq}=$_;
            }
        $tab{$id}{mq}.=$_;
        $precline=$_;
        }
    }
close(MQ);
 
foreach $id (keys(%tab)) { getheader($tab{$id},$id,("From: ","To: ","Date: ","Subject: ")); }
 
if(defined($FoT)) {
    $From=$FoT;
    $To=$FoT;
    }
 
# eviter la double boucle qui est inutil et ralenti trop l'affichage
# surtout en cas de queue de messageries trop pleines
foreach $id (keys(%tab)) {
    $cou{from}=testheader($From,$tab{$id}{"From: "});
    $cou{to}=testheader($To,$tab{$id}{"To: "});
    $cou{smtp}=testheader($SMTP,$tab{$id}{"Received"});
    if($cou{smtp}) { # la recherche sur un champs non defini renvoie toujours ok
        if(defined($FoT)) {
            if($cou{from} or $cou{to}) {
                if($stat)   { dossomstat(\%resstat,$id,$tab{$id}); }
                else        { trait1msqid($id,$tab{$id},$actdel,$acthol); }
                }
            }
        elsif($cou{from} and $cou{to}) {
            if($stat)   { dossomstat(\%resstat,$id,$tab{$id}); }
            else        { trait1msqid($id,$tab{$id},$actdel,$acthol); }
            }
        }
    }
 
if($stat) {
    foreach my $filtre (keys(%resstat)) {
        foreach my $val (keys($resstat{$filtre})) {
            print "$filtre;$val;".$resstat{$filtre}{$val}{Nb}."\n";
            }
        }
    }

Recompile des hash automatique

Liens referrents

Script'n Co Ce Makefile est lancé via une crontab, il rehash les fichiers si necessaire, voire relance postifix… FIXME: pour le moment, pas de traitement d'erreure d'un hash….

  • Crontab
crontab
*/5 7-19 * * *  root    /usr/bin/make -C /etc/postfix/ >/dev/null
  • Script /etc/postfix/Makefile
Makefile
#!/usr/bin/make -f
 
MAPS=transport.db relayed-emails.db
ALIASES= aliases
RESTART= mynetwork
 
CMDAL=/usr/bin/newaliases
CMDPM=/usr/sbin/postmap
###peut etre voire du coté de VPATH
 
# Je doute de l'utilitee aujourd'hui de cela, mais ca marche(tm)
.SUFFIXES: . .db
 
all: $(MAPS) /var/spool/postfix/pid/master.pid aliases.db
 
/var/spool/postfix/pid/master.pid: $(RESTART)
        echo RESTART
        /etc/init.d/postfix restart
 
aliases.db: aliases
        echo ALIASING
        $(CMDAL) || { rm -f $@ $.dir; exit 1; }
 
%.db : %
        echo COMPILING
        $(CMDPM) $*

Validation d'existance/parametrage des domaines relayes

Accompagnement au traitement des Mail Queue

Suivi du traitement (nagios) des mails

Tester le serveur IMAP



The initial telnet: > symbolises your shell prompt.

telnet: > telnet imap.example.com imap
[...]
client: a1 LOGIN MyUsername MyPassword
[...]
server: a1 OK Logged in.
client: a2 LIST "" "*"
server: * LIST (\HasNoChildren) "." "INBOX"
server: a2 OK List completed.
client: a3 EXAMINE INBOX
server: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
server: * OK [PERMANENTFLAGS ()] Read-only mailbox.
server: * 1 EXISTS
server: * 1 RECENT
server: * OK [UNSEEN 1] First unseen.
server: * OK [UIDVALIDITY 1257842737] UIDs valid
server: * OK [UIDNEXT 2] Predicted next UID
server: a3 OK [READ-ONLY] Select completed.
client: a4 FETCH 1 BODY[]
server: * 1 FETCH (BODY[] {405}
server: Return-Path: sender@example.com
[...]
server: )
server: a4 OK Fetch completed.
client: a5 LOGOUT

docs/linuxeries/postfix.txt · Dernière modification: 2021/08/20 15:47 (édition externe)
Recent changes RSS feed Debian Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki