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 : - SMTPD Restrictions - Header/body Checks - 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...) - Dans le //main.cf// on rajoute //header_checks = regexp:/etc/postfix/header_checks// - 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) - Dans le //main.cf// on rajoute //header_checks = regexp:/etc/postfix/header_checks// - Dans le ///etc/postfix/header_checks// on rajoute ///^Subject:(.*?)/// REPLACE Subject: [OK] $1 ====== Creer un trou noir, ils ne recevront plus de mails ====== - 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: * [[https://pypi.org/project/pymailq/|Un outils de traitement de queue]] ===== 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 ===== - vidage de la queue de hold : postsuper -d ALL hold - 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 ===== * Cf http://mhawthorne.net/posts/postfix-configuring-gmail-as-relay.html # 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… [[http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps|pour forcer le TLS en fonction de la destination]] ====== Relayage de (sous) domaine ====== Le relayage pure peut induire des problematiques de NPAI, cad - des mails arrivent sur des emails qui n'existent pas sur les domaines que vous relayes - vous, vous les acceptez - le serveur a qui vous les relayez les refuse directement (RCPT TO refusé, car mbox inexistante) - et vous, vous tentez d'envoyer un user uknown (npai) a l'emetteur "d'origine" - ca tombe mal, l'emetteur d'origine c'est un spammeur... il existe pas vraiment... et parf... ca s'empile - vous vous faites blacklister... A cela 2 parades... - vous déclarer une liste completes des alias et emails que vous relayez (cf relay_recipient_maps) - utiliser le demon verify (a ne pas confondre avec la commande VRFY a manipuler avec trop de precautions) - Ce service va générer un cache des emails existant ou non sur du serveur cible - 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 ===== - Penser a avoir un postfix __correctement__ configurer, sinon, vous n'aurez aucune email qui fonctionnera... (le check par le device distant pourrait être refusé - 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 - Le fichier de cache peut sembler se reseter tout seul - A lire, mais bon a mon avis l'erreur est ailleurs : [[http://www.debian-fr.org/erreur-dans-le-log-t40633.html]] - address_verify_map = hash:$data_directory/verify_cache - Me semble plus concret, selon la Address verification database/Note 3 de [[http://www.postfix.org/ADDRESS_VERIFICATION_README.html|la doc officielle de postfix]], le fichier est ouvert, puis verify chroot. - Donc forcement, il trouve plus le fichier correctement - Alors probablement il se suicide - Tel le phénix, il reviens, mais __avant__ le chroot il reouvre le fichier - Donc, forcement, il trouve plus le fichier... - Je préconise, via le master.conf d'interdire le chroot pour verify... - Les domaines a vérifier doivent etre listes comme suis dans /etc/postfix/verify_domains : - NDD reject_unverified_recipient - On hash le fichier, on restart le postfix (pour la modif du main.cf) ===== Suivi du fonctionnement de verify ===== - Le fichier de cache est : /var/lib/postfix/verify_cache.db - 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// #!/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 - ressend: ça renvoie le mail vers le destinataire reel - rewrite : ça réécris dans le ressend le To avec le nouveau destinataire - 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 ==== 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 ==== #!/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() { 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 () { $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 : - il faut installer //postfix-pcre// qui rajoute une lib dans ///etc/postfix/dynamicmaps.cf// - 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: - //canonical_maps// là la methode la moins flexible - Cette table fait par defaut dans tout les sens du mail... - //recipient_canonical_maps// un peu moins barbare - //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: - Rajouter dans le main.cf la ligne //canonical_maps=pcre:/etc/postfix/canonical// - 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 à : * http://www.iredmail.org/docs/send.out.email.from.specified.ip.addresses.html * https://www.faqforge.com/linux/send-all-outgoing-email-trough-one-ip-address-in-postfix/ * https://serverfault.com/questions/92181/how-to-make-postfix-use-another-ip-address ====== 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... :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 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 ====== - On ne peut avoir son virus eicar sous forme de fichier => l'AV local l'effacerais - 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 ===== #!/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 ====== * http://www.akadia.com/services/postfix_mta.html * http://zero202.free.fr/cs66-smtp/html/ar01s02.html * http://jigneshdhameliya.blogspot.fr/2011/01/postfix-sendmail-replacement.html ====== 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 ** * suppression d'un mail des queues : **postsuper -d ** * lecture d'un mail : **postcat -q ** * le script #!/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() {} 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=) { 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=; $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 ] [--FromOrTo |[--From |& --To ] [--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() { 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 ==== * http://mrbook.org/tutorials/make/ * http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ * http://bellet.info/creatis/unix/makefile.html * http://icps.u-strasbg.fr/people/loechner/public_html/enseignement/GL/make.pdf 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 */5 7-19 * * * root /usr/bin/make -C /etc/postfix/ >/dev/null * Script /etc/postfix/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 ===== * Cf http://www.anta.net/misc/telnet-troubleshooting/imap.shtml 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