BOITE À OUTILS : Postfix et Dovecot
Publié par The Troll le 01 05 2015

Et bien, j'avais promis la chose, la voila... C'est le truc qui m'avait pris le plus de temps à comprendre et mettre en place. C'est le genre de truc pas aussi courant qu'un virtualhost apache et qui a besoin de pas mal de configuration pour fonctionner.

Comme à chaque fois, c'est un truc qui marche chez moi, mais je ne peux pas vous certifier qu'il marchera chez vous. De plus je vous conseille de lire l'introduction à tous mes billets "boite à outils pour gestion de serveur".

Donc passons aux choses sérieuses. j'utilise postfix et dovecot-pop3d de la manière qui me semble la plus simple, il y a des milliers d'autres manières de faire, peut être même plus intelligentes mais celle-ci me convient. TOUS les mails sont indépendants des utilisateurs du système.

1 - d'abord quelques réglages dans le fichier /etc/postfix/main.cf


virtual_mailbox_domains = /etc/postfix/domains
virtual_mailbox_base = /var/vmail/
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_alias_maps = hash:/etc/postfix/virtual
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = virtual

Le reste du fichier n'est pas concerné par la configuration que nous faisons.

Comme vous le voyez, vous devez créer les fichiers /etc/postfix/domains /etc/postfix/vmailbox et /etc/postfix/virtual (ce sont des noms que j'ai choisis tout seul et qui sont utilisés dans le script_de_la_mort_qui_tue), vous pouvez tout à fait les changer. Pas besoin de les remplir, le script d'en chargera.

Pour résumer, le fichier domains contiendra les noms de domaines que votre serveur gère, le fichier virtual contiendra les mails redirigés et le fichier vmailbox contiendra les mails avec une boite pop dispo sur votre serveur.

Comme vous le voyez j'ai un utilisateur 5000, pour le créer :


groupadd -g 5000 vmail
useradd -s /usr/sbin/nologin -g vmail -u 5000 vmail -d /var/vmail -m

J'ai choisi de mettre les boites mails dans /var/vmail/ le script en tient compte, si vous voulez changer vous devez également le faire dans le script.

2 - Passons à dovecot.

J'ai décidé d'utiliser un seul fichier pour gérer les identifiants et mots de passe que l'on peut créer ou l'on veut, par exemple /etc/dovecot/fichier_user

On doit modifier /etc/dovecot/conf.d/10-master.conf, dans service auth {


# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
  mode = 0666
  user = postfix
  group = postfix
}

(on a ajouté le user et le group.)

puis on modifie : /etc/dovecot/conf.d/10-auth.conf


#!include auth-deny.conf.ext
#!include auth-master.conf.ext
#!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext

(on désactive tous les protocoles et laisse auth-passwdfile.conf.ext)

ce qui amène à modifier le fichier : /etc/dovecot/conf.d/auth-passwdfile.conf.ext


passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/fichier_user
}

userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/fichier_user
}

Comme vous le voyez, on retrouve ici le fichier que l'on a créé pour les utilisateurs : /etc/dovecot/fichier_user

Il reste ensuite à modifier le fichier /etc/dovecot/conf.d/10-mail.conf pour y ajouter la ligne suivante :


mail_location = maildir:/var/vmail/%d/%n/

Ici le chemin /var/vmail/ est le chemin choisi ET dans le fichier /etc/postfix/main.cf ET lors de la création de l'utilisateur virtuel vmail.

Normalement vous redémarrez postifx et dovecot et vous êtes près à commencer.

Maintenant le morceaux de choix : le fameux (fumeux?) script. Je l'ai appelé manage_mail. Comme pour le reste je le pose dans un dossier, le rend exécutable et ./manage_mail pour l'appeler.


#!/bin/sh

[ "$1" = "" ] && echo "$0 help pour de l aide" && exit

# conf postfix
virtual_alias_file=/etc/postfix/virtual
virtual_mailbox_file=/etc/postfix/vmailbox
virtual_domains=/etc/postfix/domains

# conf dovecot
dovecot_passwd="/usr/bin/doveadm pw"
dovecot_make_dir=/usr/bin/maildirmake.dovecot
directory_mail=/var/vmail
dovecot_id=5000
dovecot_users=/etc/dovecot/users

# conf sauvegarde
file_to_save="$virtual_alias_file $virtual_mailbox_file $virtual_domains $dovecot_users"
save_dir=/home/herve


action=$1
data=$2
la_date=`date +"%Y-%m-%d"`
its_done="     ....... fait"
already="     ...... existait déjà"

get_stats(){
        echo "#####################"
        [ "$data" != "" ] && echo "# Recherche sur $data" || echo "# liste générale"
        echo "#####################\n"

        echo "## domaines gérés  ##############"
        [ "$data" != "" ] && grep $data $virtual_domains || cat $virtual_domains |tr "\n" " "
        echo $domains

        echo "## adresses box ##############"
        [ "$data" != "" ] && grep $data $virtual_mailbox_file | cut -f1-2 --output-delimiter " ->[*]" || cut $virtual_mailbox_file -f1-2 --output-delimiter " ->[*]"
        echo "\n"

        echo "## adresses alias ##############"
        [ "$data" != "" ] && grep $data $virtual_alias_file | cut -f1-2 --output-delimiter " -> " || cut $virtual_alias_file -f1-2 --output-delimiter " -> "
        echo "\n"
}

re_start_all(){
        echo -n "Redemarrage du service"
        postmap $virtual_alias_file
        postmap $virtual_mailbox_file
        postfix reload
        /etc/init.d/postfix restart
        echo "$its_done"

}

add_domains(){
        if (grep -q $data $virtual_domains )
        then
                echo "domaine $data déja présent"
        else
                echo "$data" >> $virtual_domains
                echo "#$data" >> $virtual_alias_file
                echo "#$data" >> $virtual_mailbox_file
                echo "#$data" >> $dovecot_users
                echo "Domaine $data ajouté."
        fi
}

del_domains(){
        [ "$data" != "" ] && sed -i '/'"$data"'/d' $virtual_domains && echo "Domain $data effacé"
        read -p "Effacer toutes les adresses mails afférentes ? [o/n]" del_mails
        if [ $del_mails = "o" ]
        then
                sed -i '/'"$data"'/d' $virtual_alias_file
                sed -i '/'"$data"'/d' $virtual_mailbox_file
                sed -i '/'"$data"'/d' $dovecot_users
                rm -rf $directory_mail/$data/
                echo "$its_done"
        fi
}


add_aliass(){
        if (grep -q $data $virtual_alias_file )
        then
                echo "Alias $data déja présent"
        else
                sed -i 's/#'"$domain"'/#'"$domain"'\n'"$data"'  '"$redir"'/' $virtual_alias_file
                echo "Alias $data -> $redir  ajouté."
        fi
}

del_aliass(){
        sed -i '/'"$data"'/d' $virtual_alias_file
        echo "$its_done"

}

del_boxes(){
        read -p "Effacer l'adresse $data  [o/n]? " del_box

        if [ $del_box = "o" ]
        then
                sed -i '/'"$data"'/d' $virtual_mailbox_file
                sed -i '/'"$data"'/d' $dovecot_users
                rm -rf $directory_mail/$domain/$user
                echo "$its_done"
        fi
}

add_boxes(){
        echo "Ajout de la boite mail  $data..."
        read -p "Mot de passe pour l'utilisateur:  " the_pass
        the_passwd=`$dovecot_passwd -p $the_pass`

        if (grep  -q $data $dovecot_users)
        then
                sed -i '/'"$data"'/d' $dovecot_users
        fi

        echo -n "Ajout de l utilisateur  $user@$domain au fichier $dovecot_users"
        sed -i 's|#'$domain'|#'$domain'\n'$data':'$the_passwd':5000:5000::'$directory_mail'\/'$domain'\/'$user'\/:\/bin\/false::|' $dovecot_users && echo "$its_done"

        echo -n "Creation du répertoire $directory_mail/$domain/$user"

        if [ ! -d $directory_mail/$domain ]
        then
                mkdir $directory_mail/$domain
                chown $dovecot_id:$dovecot_id $directory_mail/$domain
                chmod 700 $directory_mail/$domain
                echo "$its_done"
        else
                echo "$already"
        fi

        $dovecot_make_dir $directory_mail/$domain/$user $dovecot_id:$dovecot_id
        for i in Drafts Sent Junk Trash
          do
          $dovecot_make_dir $directory_mail/$domain/$user/.$i $dovecot_id:$dovecot_id
        done

        echo -n "Ajout de l utilisateur au fichier $virtual_mailbox_file"

        if (grep  -q $data $virtual_mailbox_file)
        then
                echo "$already";
        else
                sed -i 's/#'"$domain"'/#'"$domain"'\n'"$data"'  '"$domain\/$user\/"'/' $virtual_mailbox_file
                echo "$its_done";
        fi

        #################### pour garder les informations dans un fichier ##################################
        echo "======================"
        echo "$user@$domain -> $the_pass"
        echo "======================"
        ####################################################################################################

}

save_conf(){
        for i in $file_to_save
        do
        cp $i $save_dir/"$la_date"_"$i".bak
        done
        echo "$its_done"

}
case $action in
        stats)
                get_stats;;

        add_domain)
                add_domains;;

        del_domain)
                del_domains;;

        add_alias)
                user=`echo "$data" | cut -f1 -d "@"`
                domain=`echo "$data" | cut -s -f2 -d "@"`
                if !(grep  -q $domain $virtual_domains);then echo "le domaine $domain n est pas géré, il faut le créer avant"; exit;fi
                [ "$3" = "" ] && echo "il manque l adresse de redirection. add_alias user@domain.tld redir@domain.tld" && exit
                redir=$3
                [ "$data" != "" ] && add_aliass;;


        del_alias)
                [ "$data" != "" ] && del_aliass;;

        add_box)
                user=`echo "$data" | cut -f1 -d "@"`
                domain=`echo "$data" | cut -s -f2 -d "@"`
                if !(grep  -q $domain $virtual_domains);then echo "le domaine $domain n est pas géré, il faut le créer avant"; exit;fi
                [ "$data" = "" ] && echo "il manque l adresse à créer. add_box user@domain.tld" && exit
                add_boxes;;

        del_box)
                [ "$data" = "" ] && echo "il manque l adresse à supprimer. del_box user@domain.tld" && exit
                user=`echo "$data" | cut -f1 -d "@"`
                domain=`echo "$data" | cut -s -f2 -d "@"`
                del_boxes;;

        restart)
                re_start_all;;

        save)
                save_conf;;

        help)
                echo "###############################"
                echo "Usage $0 action data"
                echo "----------------"
                echo " action:  stats -> listes de tout ( stats | stats motif_de_recherche) "
                echo "          add_domain -> ajoute un domaine à gerer (add_domain domain.ltd)"
                echo "          del_domain -> supprime un domaine à gerer (del_domain domain.ltd)"
                echo "          add_alias -> ajoute une adresse redirigée (add_alias from_mail@domain.tld to_mail@anotherdomain.tld)"
                echo "          del_alias -> supprime une adresse redirigée (del_alias from_mail@domain.tld )"
                echo "          add_box -> ajoute une adresse pop (add_box mail@domain.tld )"
                echo "          del_box -> supprime une adresse pop (del_box mail@domain.tld )"
                echo "          restart -> redemmare le serveur et remet à jour les hash des fichiers (restart)"
                echo "          save -> sauvegarde les fichiers de config en .bak (save)"

esac

comment il marche : l'aide dit :

Usage ./manage_mail action data
----------------
action:
stats -> listes de tout ( stats ou stats motif-de-recherche)
add_domain -> ajoute un domaine à gerer (add_domain domain.ltd)
del_domain -> supprime un domaine à gerer (del_domain domain.ltd)
add_alias -> ajoute une adresse redirigée (add_alias from_mail@domain.tld to_mail@anotherdomain.tld)
del_alias -> supprime une adresse redirigée (del_alias from_mail@domain.tld )
add_box -> ajoute une adresse pop (add_box mail@domain.tld )
del_box -> supprime une adresse pop (del_box mail@domain.tld )
restart -> redemmare le serveur et remet à jour les hash des fichiers (restart)
save -> sauvegarde les fichiers de config en .bak (save)

L'aide est assez claire.

il y a juste à configurer les variables en début de fichier


# conf postfix
virtual_alias_file=/etc/postfix/virtual (fichier défini dans /etc/postfix/main.cf)
virtual_mailbox_file=/etc/postfix/vmailbox (fichier défini dans /etc/postfix/main.cf)
virtual_domains=/etc/postfix/domains (fichier défini dans /etc/postfix/main.cf)

# conf dovecot
dovecot_passwd="/usr/bin/doveadm pw" (normalement inchangé dans debian 7)
dovecot_make_dir=/usr/bin/maildirmake.dovecot (normalement inchangé dans debian 7)
directory_mail=/var/vmail (fichier défini dans /etc/postfix/main.cf, /etc/dovecot/conf.d/10-mail.conf et home de l'utilisateur vmail )
dovecot_id=5000 (id de l'utilisateur vmail)
dovecot_users=/etc/dovecot/fichier_user (fichier défini dans /etc/dovecot/conf.d/auth-passwdfile.conf.ext)

# conf sauvegarde
file_to_save="$virtual_alias_file $virtual_mailbox_file $virtual_domains $dovecot_users"
save_dir=/rertoire/ou/vous/sauvegarder (doit exister)

le fichier /etc/dovecot/fichier_user sera sous la forme :


user@domaine.ltd:{CRAM-MD5}mot_de_passe_hash_md5:5000:5000::/var/vmail/domaine.ltd/user/:/bin/false::

Vous pouvez tout à fait faire vos test avant de le mettre en production, en donnant des fichiers "factices" (que vous avez créés dans votre home) ainsi qu'un sous répertoire de test (pour les mails) dans votre home.

Normalement cela fonctionne, il ne reste qu'à faite un test :


./manage_mail add_domain domaine_que_vous_gerez.com
./manage_mail add_box mon_user@domain_que_vous_gerez.com (vous donnez le mot de passe et il fait tout le travail).
./manage_mail restart (pour que tout soit pris en compte)

Enfin plus qu'à tester en ligne de commande :


mail user@domain_que_vous_gerez.com

vous renseignez le sujet, puis tappez le corps du message, vous terminez par une ligne avec juste un . (puis entrer) et vous devez voir passez dans vos logs

Nov 22 09:48:27 votre_server postfix/qmgr[6034]: 87F9A564670B: from=, size=292, nrcpt=1 (queue active)
Nov 22 09:48:28 votre_server postfix/virtual[8508]: 87F9A564670B: to=, relay=virtual, delay=0.77, 
    delays=0.49/0.09/0/0.19, dsn=2.0.0, status=sent (delivered to maildir)
Nov 22 09:48:28 votre_server postfix/qmgr[6034]: 87F9A564670B: removed

pffff. bon voila qui est fait, comme promis. Et le mot de la fin n]'oubliez pas de mettre à jour redémarrer votre serveur sinon cela n'est pas pris en compte.


./manage_mail restart

commentaire(s)
Posté par Michael le 16 08 2015 à 21:50
Salut, j'ai survolé ton shell script, j'ai quelques remarques de style.

– 1. Le `` est moins maniable que la syntaxe $()

– 2. En général on écrit plutôt "${data}" que $data tout court. Les "" sont pour contrôler la découpe de mots et les {} pour facilter l'utilisation de modificateurs comme :- ou :? ou :)

– 3. Pour générer tes scripts SED utilise plutôt une fonction à part ou bien printf, la mise au point est plus facile.

– 4. La plupart des tes commandes echo gagneraient à être transformées en printf.

– 5. Cas typique d'utilisation de :? est la commande dangereuse rm -rf $directory_mail/$domain/$user

– 6. Ton utilisation de && n'est pas toujours très cohérente, pour simplifier tu peux aussi utiliser l'opérateur set -e en limitant sa portée à un sous-shell ou en utilisant set +e.

http://linuxfr.org/news/revue-des-techniques-de-programmation-en-shell
Ajouter un commentaire