--- categories: mail title: Howto Postfix ... * Documentation : * Options `main.cf` : * Rôle Ansible : [Postfix](http://www.postfix.org/) est serveur [SMTP](HowtoSMTP) libre et populaire sous GNU/Linux et BSD. Il a été développé en 1999 par [Wietse Venema](http://www.porcupine.org/wietse/) comme une alternative plus facile à administrer et plus sécurisée que l'historique _Sendmail_. Un serveur SMTP, appelé aussi MTA (Mail Transport Agent), est l'élément principal d'un serveur d'emails. Tout email transite forcément par un serveur SMTP dont il existe de nombreuses implémentations libres (Postfix, Exim, Sendmail, Qmail etc.) ou propriétaires (Microsoft Exchange, Sun Java System Messaging Server, IBM Lotus Domino, etc.). ## Installation ~~~ # apt install postfix # postconf -d | grep ^mail_version mail_version = 2.11.3 ~~~ ## Configuration Postfix n'est pas monolithique : le processus `master` tourne en permanence et gère le démarrage d'autres processus qui ont des tâches dédiées (cleanup, smtpd, pickup, etc.) notamment la transition entre les différentes files d'attente de Postfix (incoming, active, deferred, corrupt, hold). La configuration de ces processus se trouve dans le fichier `/etc/postfix/master.cf`. Et le fichier `/etc/postfix/main.cf` gère les nombreuses options de configuration. L'utilitaire **postconf** permet de lister/vérifier les options du `main.cf`. ~~~ ## Vérifier la validité de la configuration (check conf) # postconf >/dev/null ## Lister les options par défaut # postconf -d ## Lister les options actuelles # postconf ## Lister les options modifiées par rapport au défaut # postconf -n ## Manpage très détaillée sur toutes les options disponibles # man 5 postconf ~~~ ### Configuration minimale Pour une configuration minimale, nous conseillons d'avoir le fichier `main.cf` suivant en ajustant le paramètre _myhostname_ avec un enregistrement DNS existant pointant vers le serveur concerné : ~~~ smtpd_banner = $myhostname ESMTP mail server biff = no append_dot_mydomain = no myhostname = hosting.example.com alias_maps = hash:/etc/aliases alias_database = hash:/etc/aliases myorigin = $myhostname mydestination = $myhostname localhost.localdomain localhost localhost.$mydomain relayhost = mynetworks = 127.0.0.0/8 mailbox_size_limit = 0 recipient_delimiter = + inet_interfaces = all inet_protocols = ipv4 disable_vrfy_command = yes smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination smtp_tls_security_level = may smtp_tls_mandatory_protocols=!SSLv2,!SSLv3 smtp_tls_protocols=!SSLv2,!SSLv3 smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtp_tls_loglevel = 1 ~~~ ### Configuration minimale pour serveur web N.B. : cette configuration complète la [configuration minimale](#configuration-minimale) donnée plus haut. Un serveur web va souvent envoyer des emails, et notamment vers des fournisseurs d'accès connus (gmail.com, orange.fr, etc.). On conseille donc d'ajouter les options suivantes dans `main.cf` pour gérer le rythme d'envoi : ~~~ #delay_warning_time = 4h minimal_backoff_time = 15m maximal_backoff_time = 6h maximal_queue_lifetime = 4d queue_run_delay = 100s bounce_queue_lifetime = 1d initial_destination_concurrency = 5 default_destination_concurrency_limit = 20 slow_destination_rate_delay = 0 slow_destination_concurrency_limit = 1 slow_destination_concurrency_failed_cohort_limit = 100 slow_destination_recipient_limit = 25 transport_maps = hash:$config_directory/transport ~~~ et on ajoute la ligne suivante dans `master.cf` : ~~~ slow unix - - n - - smtp -o syslog_name=postfix-slow ~~~ Il faut également créer le fichier `/etc/postfix/transport` et indiquer des domaines vers lesquels le rythme d'envoi sera plus lent (à cause de restrictions de leur côté) : ~~~ orange.fr slow: wanadoo.fr slow: voila.fr slow: laposte.net slow: ~~~ On fera ensuite : ~~~ # postmap /etc/postfix/transport # systemctl restart postfix ~~~ On peut ensuite vérifier que la configuration est bien prise en compte en regardant dans les logs de Postfix. On doit pouvoir observer des processus « postfix-slow » pour tous les domaines concernés. ### alias Postfix utilise par défaut une base d'alias située dans le fichier `/etc/aliases`. Voici un exemple : ~~~ root: jdoe abuse: root noc: root security: root postmaster: msmith MAILER-DAEMON: postmaster daemon: /dev/null bin: /dev/null sys: /dev/null hey: foo@example.com hello: foo@example.com, bar@example.com ~~~ Si l'on modifie `/etc/aliases` il faut ensuite la « regénérer » pour qu'elle soit prise en compte : ~~~ # newaliases ~~~ ### Configuration avancée pour serveur de messagerie Voici un exemple détaillé de fichier `main.cf` avec des commentaires en français : #### Section : Emplacements ~~~ ## fichier principal de configuration de Postfix ## commentaires de Gregory Colpart reg AT evolix DOT fr ## version 1.0 : 1ere version publique (05.04.2010) ######################## # Section : Emplacements ######################## # Repertoire ou se trouvent les commandes de postfix [OBLIGATOIRE] #par defaut, = $program_directory command_directory = /usr/sbin # Repertoire ou se trouvent les demons de postfix [OBLIGATOIRE] #par defaut, = $program_directory daemon_directory = /usr/lib/postfix # Variable pour indiquer les emplacements des commandes et demons de postfix #program_directory = /usr/lib/postfix # Repertoire contenant les fichiers de boites aux lettres #par defaut, = /var/mail #mail_spool_directory = # Repertoire de la file d'attente de postfix #par defaut, = /var/spool/postfix #queue_directory = # Boites aux lettres #par defaut, = home_mailbox = Maildir/ # Transmettre les mails a un MDA #par defaut, = #mailbox_command = /usr/bin/procmail # Separateur entre noms d'utilisateur et extensions d'adresse # mettre + pour intégration avec amavis #par defaut, = recipient_delimiter = + # Controle si le repertoire existe (souvent pour les systemes de fichiers montes) #par defaut, = no #require_home_directory = # Commande pour transmettre le courrier a un MDA #par defaut, = #mailbox_command = /usr/bin/procmail # Banniere SMTP affichee #par default, = $myhostname ESMTP $mail_name smtpd_banner = $myhostname ESMTP mail server # Groupe des commandes set-gid ayant des acces en ecriture #par defaut, = postdrop # setgid_group = postdrop # Produire des "biff notifications" aux utilisateurs pour # prevenir de l'arrivee de nouveaux mails # par default, = yes #biff = no ~~~ #### Section : domaines ~~~ #################### # Section : domaines #################### # Indique le nom d'hote pleinement qualifie ou se trouve postfix [OBLIGATOIRE] #par defaut, = [retour de la commande Unix hostname] myhostname = computer.example.com # Variable indiquant le domaine dans lequel se trouve la machine #par defaut, = [partie domain de la variable $myhostname] #mydomain = # Liste des noms de domaine (ou IP) consideres comme local #par defaut, = $myhostname, localhost.$mydomain, localhost mydestination = $myhostname # Indique le domaine apparaissant dans le courrier envoye #par defaut, = $myhostname myorigin = example.com # Liste de domaine fonctionnant UNIQUEMENT avec des alias virtuels #par defaut, = $virtual_alias_maps virtual_alias_domains = [ domaines avec alias virtuels ] # Liste de domaine fonctionnant avec des comptes virtuels #par defaut, = $virtual_mailbox_maps virtual_mailbox_domains = [ domaines avec comptes virtuels ] # Repertoire de base de l'espace de stockage #par defaut, = virtual_mailbox_base = / # Ajoute $mydomain aux adresse ne compoirtant que la partie hote sans le domaine #par defaut, = yes #append_dot_mydomain = no # Ajoute $myorigin aux adresses ne comportant pas de composante de domaine #par defaut, = yes #append_at_myorigin = no # Liste de domaines cachant des sous-domaines internes #par defaut, = #masquerade_domains = # A l'exception de certains comptes : #par defaut, = #masquerade_exceptions = root, admin # Champs d'application de la reecriture des sous-domaines caches #par defaut, = envelope_sender, header_sender, header_recipient #masquerade_classes = # Sites eligibles pour un vidage rapide (postqueue -s [domain.tld]) #par defaut, = $relay_domains #fast_flush_domains = # Interfaces sur lesquelles ecoutent postfix #par defaut, = all #inet_interfaces = all # Envoyer les mails avec une IP spécifique smtp_bind_address = 192.168.1.1 # Adresse IP externe du firewall/proxy si derriere NAT ou proxy # evite principalement les boucles si MX secondaire et MX primaire indisponible #par defaut, = #proxy_interfaces = [adresse IP] # Domaines acceptes pour faire relai (MX 2aire) #relay_domains = [domaine a relayer] ~~~ #### Section : base de donnees ~~~ ########################### # Section : base de donnees ########################### # Liste des bases de donnees utilisees par l'agent de distribution locale # Pour regenerer une base de donnees : postalias /etc/aliases (par ex) #par defaut, = hash:/etc/aliases, nis:mail.aliases alias_maps = hash:/etc/aliases hash:/etc/postfix/liste_diff ldap:ldapaliases # Liste des bases de donnees locales # Pour regenerer avec newaliases #par defaut, = hash:/etc/aliases alias_database = hash:/etc/aliases hash:/etc/postfix/liste_diff # Chemin vers la commande newaliases #par defaut, = /usr/bin/newaliases #newaliases_path = # Base de donnes d'alias virtuels # ne pas oublier : postmap /etc/postfix/virtual #par defaut, = $virtual_maps virtual_alias_maps = hash:/etc/postfix/virtual # Base de donners des boites virtuelles # ne pas oublier : postmap /etc/postfix/vmailbox #par defaut, = virtual_mailbox_maps = hash:/etc/postfix/vmailbox # Reecriture des adresses #par defaut, = #canonical_maps = hash:/etc/postfix/canonical # Reecriture des adresses a l'arrivee (ecrase $canonical_maps) #par defaut, = #recipient_canonical_maps = hash:/etc/postfix/canonical # Reecriture des adresses au depart #par defaut, = #sender_canonical_maps = hash:/etc/postfix/canonical # Adresses changees #relocated_maps = hash:/etc/postfix/relocated # Boite pour receptionner tous les utilisateurs inconnus #luser_relay = spam # Liste de base de donnees contenant les adresses locales permettant de rejeter les messages aux utilisateurs inconnus # (sera nulle pour recuperer les courriels vers les utilisateurs inconnus) #par defaut, = proxy:unix:passwd.byname $alias_maps #local_recipient_maps = # MAILING-LIST nommee xx # dans le fichier /etc/aliases : # xx: user1@domain1 user2@domain2 etc. # owner-xx: admin@domain # Utiliser ou non l'alias xx-owner comme adresse d'enveloppe d'expedition #par defaut, = yes #owner_request_special = # Utiliser l'adresse relle de l'admin au lieu de xx-owner #par defaut, = no #expand_owner_alias = ~~~ #### Section : paramètres de la file d'attente ~~~ ########################################### # Section : parametres de la file d'attente ########################################### # Lorsqu'un message n'a pas ete delivre, Postfix adjoint une marque indiquant le moment ou la prochaine tentaive pourra avoir lieu # Delai au-dela duquel les messages non delivres seront renvoyes a l'expediteur #par defaut, = 5d #maximal_queue_lifetime = # Intervalle de temps ou postfix examinera la file # Il examine notamment la file deferred pour voir si de NOUVEAUX messages sont arrives # Il faut aussi que la marque indique qu'ils soient prets #par defaut, = 1000s #queue_run_delay = # A chaque echec, le delai de la prochaine distribution double, avec les restrictions suivantes : # Delai minimal #par defaut, = 1000s #minimal_backoff_time = # Delai maximal #par defaut, = 4000s #maximal_backoff_time = # Si maxproc est vide (master.cf), nombre maximal est : #par defaut, = 100 #default_process_limit = # Nombre maximal de destinataires stockes en memoire par qmgr pour un transport particulier #par defaut, = 10000 #default_recipient_limit = # Nombre limitant de messages envoyes simultanement INITIALEMENT pour une destination particuliere # (forcement majoree par maxproc du master.cf ou $default_process_limit) #par defaut, = 5 #initial_destination_concurrency = # Une fois ces messages distribues, si il reste des messages dans la file d'attente pour cette destination # particuliere, postfix augmente le nombre de tentative tant qu'il ne detecte pas de probleme avec # la destination, avec la limite suivante : #par defaut, = 20 #default_destination_concurrency_limit = # Cette limite peut etre differente selon le type de transport utilise : #par defaut, = $default_destination_concurrency_limit #lmtp_destination_concurrency_limit = #par defaut, = 2 #local_destination_concurrency_limit = #par defaut, = $default_destination_concurrency_limit #relay_destination_concurrency_limit = #par defaut, = $default_destination_concurrency_limit #smtp_destination_concurrency_limit = #par defaut, = $default_destination_concurrency_limit #virtual_destination_concurrency_limit = # On peut aussi limiter le nombre maximum de destinataire pour un meme message # Si le nombre de destinataire depasse la limite, postfix divise en groupe d'adresses plus petites et envoie des copies distinctes du message #par defaut, = 10000 #default_destination_recipient_limit = #par defaut, = $default_destination_recipient_limit #lmtp_destination_recipient_limit = #par defaut, = 1 #local_destination_recipient_limit = #par defaut, = 20000 #qmgr_message_recipient_limit = #par defaut, = $default_destination_recipient_limit #relay_destination_recipient_limit = #par defaut, = $default_destination_recipient_limit #smtp_destination_recipient_limit = #par defaut, = 1000 #smtpd_recipient_limit = #par defaut, = $default_destination_recipient_limit #virtual_destination_recipient_limit = # Nombre maximum de destinataires pour un transport lorsque priorite superieure de transport #par defaut, = 1000 #default_extra_recipient_limit = # Types d'incidents a rapporter # resource : message non delivre pour probleme de ressource # software : message non delivre pour probleme de logiciels # policy : envoie le transcription smtp d'un message rejete par restrictions # protocol : envoie toute transcription smtp erronee # delay : envoie les entetes de messages differes # bounce : envoie les entetes de tous les message renvoyes # 2bounce : envoie les entetes de tous les messages renvoyes non delivres #par defaut, = resource, software notify_classes = resource, software, bounce, 2bounce, delay, policy, protocol # A qui les reporter ? #Pour delay #par defaut, = postmaster delay_notice_recipient = delay #Pour policy, protocol, resource, software #par defaut, = postmaster error_notice_recipient = error #Pour bounce #par defaut, = postmaster bounce_notice_recipient = 1bounce #Pour 2bounce #par defaut, = postmaster 2bounce_notice_recipient = 2bounce ~~~ #### Section : restrictions ~~~ ######################## # Section : restrictions ######################## # Restrictions au depart de la conversation #par defaut, = smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_client_access hash:/etc/postfix/acces_client # Restrictions au niveau de la commande HELO/EHLO #par defaut, = smtpd_helo_restrictions = reject_invalid_hostname # Restrictions au niveau de la commande MAIL FROM #par defaut, = smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/acces_expediteur # Restrictions au niveau de la commande MAIL FROM #par defaut, = permit_mynetworks, reject_unauth_destination smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination # Attendre la commande 'RCPT TO' avant d'evaluer les restrictions ? # (peut poser pb avec certains clients et permet d'avoir renseignements suppl) #par defaut, = yes #smtpd_delay_reject = # Definition des plages IP appartenant a mynetworks #par defaut, toutes les plages d'adresses IPv4 (et IPv6) des interfaces mynetworks = 127.0.0.0/8,[::1]/128,10.0.0.0/16 # Exiger la commande HELO/EHLO #par defaut, = no smtpd_helo_required = yes # Exiger syntaxe conforme dans les commandes MAIL FROM ou RCPT TO #par defaut, = no #strict_rfc821_envelopes = # Rejeter le courrier provenant d'une adresse inexistante ? #par defaut, = no #smtpd_reject_unlisted_sender = # Rejeter le courrier a destination d'une adresse inexistante ? #par defaut, = yes #smtpd_reject_unlisted_recipient = ~~~ #### Utilisation avec un annuaire LDAP Les bases de données d'utilisateurs et de leurs paramètres peuvent être stockés dans une base de données externe. On peut ainsi utiliser une base de donnée ou un annuaire LDAP. Dans le cas de Postfix, on peut l'utiliser avec MySQL ou OpenLDAP. Dans le fichier main.cf de Postfix, on utilisera une configuration type : ~~~ alias_maps = [autres bases] ldap:blabla blabla_server_host = [serveur ldap] blabla_search_base = [dn de base] blabla_result_attribute = [type de champs à chercher] ~~~ Dans l'annuaire LDAP on a notamment des champs ressemblant à : ~~~ dn: uid=nnom,[dn de base] objectClass: inetOrgPerson objectClass: inetLocalMailRecipient objectClass: posixAccount sn: Nom givenName: Prenom cn: Nom Prenom displayName: Nom Prenom mailLocalAddress: pnom@example.com uid: nnom userPassword: **** uidNumber: 1006 gidNumber: 1006 homeDirectory: /chemin_boite/ ~~~ Prenons un exemple d'une configuration de comptes virtuels. La configuration de Postfix peut être : ~~~ virtual_mailbox_domains = virtual.example.com virtual_mailbox_base = / virtual_mailbox_maps = ldap:ldapaliases2 ldapaliases2_server_host = localhost ldapaliases2_search_base = ou=Virtualmail,ou=Mail,dc=example,dc=com ldapaliases2_bind = yes ldapaliases2_bind_dn = cn=Manager,ou=Virtualmail,ou=Mail,dc=example,dc=com ldapaliases2_bind_pw = ****** ldapaliases2_query_filter = (mailLocalAddress=%s) ldapaliases2_result_attribute = homeDirectory ~~~ Au niveau de l'annuaire LDAP : ~~~ dn: uid=mvegas,ou=Onlymail,dc=example,dc=com objectClass: inetOrgPerson objectClass: inetLocalMailRecipient objectClass: posixAccount sn: Vegas givenName: Mister cn: Virtual Mister displayName: Mister Vegas mailLocalAddress: mvegas@example.com uid: mvegas userPassword: **** uidNumber: 1006 gidNumber: 1006 homeDirectory: /home/vmail/virtual.example.com/mvegas/ ~~~ Quelques remarques : Il faut qu'il y ait les permissions sur le homeDirectory. Dans ce cas, les répertoires seront créés automatiquement lors du premier mail reçu. Vous pouvez obtenir des messages de ce genre : ~~~ warning: dict_ldap_connect: Unable to bind to server ldap://localhost:389 as : 2 (Protocol error) ~~~ Il faut alors ajouter au fichier _slapd.conf_ : `allow bind_v2` ### SSL/TLS Il est désormais fortement conseiller d'activer le chiffrement SSL/TLS entre les serveurs SMTP pour éviter de faire circuler en clair les informations (identifiants, contenu des messages) et s'assurer que l'on s'adresse au bon serveur. #### Activation SSL/TLS au niveau serveur SMTP (smtpd) Activer SSL/TLS au niveau serveur SMTP permet la réception d'emails depuis des clients SMTP capables d'envoyer en SSL/TLS. Il faut générer une clé privée et un certificat, voir [HowtoSSL](). On peut ensuite activer via le fichier `/etc/postfix/main.cf` : ~~~ smtpd_tls_security_level = may smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 smtpd_tls_protocols=!SSLv2,!SSLv3 smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache smtpd_tls_loglevel = 1 smtpd_tls_key_file = /etc/ssl/private/smtp.example.com.key smtpd_tls_cert_file = /etc/ssl/certs/smtp.example.com.crt smtpd_tls_CAfile = /etc/ssl/certs/GandiStandardSSLCA2.pem ~~~ > *Note 1* : la désactivation des protocoles SSLv2 et SSLv3 est désormais par défaut, mais on préfère garder cette option > *Note 2* : Pour Debian 7 et 8, on conseille d'ajouter également : > >~~~ >smtpd_tls_mandatory_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL >smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL >smtpd_tls_mandatory_ciphers = medium >~~~ Pour l'envoi d'emails depuis des clients SMTP authentifiés (*smtpd_sasl_auth_enable=yes*), on active en général le port TCP/587 (appelé _SMTP Submission_) qui n'accepte que des connexions chiffrées (*smtpd_tls_security_level=encrypt*) et le port TCP/465 (appelé _SMTPS_) qui n'accepte que des connexions SMTP over TLS (*smtpd_tls_wrappermode=yes*). Ces activations se font en décommentant les lignes appropriées dans `/etc/postfix/master.cf` : ~~~ submission inet n - - - - smtpd -o smtpd_tls_security_level=encrypt -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING smtps inet n - - - - smtpd -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o milter_macro_daemon_name=ORIGINATING ~~~ Dans le cas d'utilisation de [Let's Encrypt](HowtoLetsEncrypt) voici un exemple de configuration à utiliser : ~~~ smtpd_tls_key_file = /etc/letsencrypt/live/smtp.example.com/privkey.pem smtpd_tls_cert_file = /etc/letsencrypt/live/smtp.example.com/fullchain.pem ~~~ On peut ensuite vérifier l’activation de SSL/TLS au niveau serveur en obtenant le message `STARTTLS` dans une session SMTP : ~~~ $ telnet bugs.debian.org 25 Trying 209.87.16.39... Connected to bugs.debian.org. Escape character is '^]'. 220 buxtehude.debian.org EHLO example.com 250-buxtehude.debian.org Hello example.com [80.12.63.254] 250-SIZE 104857600 250-8BITMIME 250-STARTTLS 250 HELP QUIT 221 buxtehude.debian.org closing connection Connection closed by foreign host. ~~~ On peut également utiliser une connexion chiffrée avec un serveur SMTP via la commande : ~~~ $ openssl s_client -CApath /etc/ssl/certs -connect smtp.example.com:25 -crlf -starttls smtp ~~~ #### Activation SSL/TLS au niveau client SMTP (smtp) Activer SSL/TLS au niveau client SMTP permet d'envoyer des emails vers des serveurs SMTP capables de recevoir en SSL/TLS. On conseille d'activer cela par défaut via le fichier `/etc/postfix/main.cf` : ~~~ smtp_tls_security_level = may smtp_tls_mandatory_protocols=!SSLv2,!SSLv3 smtp_tls_protocols=!SSLv2,!SSLv3 smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache smtp_tls_loglevel = 1 ~~~ > *Note* : la désactivation des protocoles SSLv2 et SSLv3 est désormais par défaut, mais on préfère garder cette option ### Authentification SMTP Cette solution est décrite dans la RFC 2554 : SMTP Service Extension for Authentication. Il faut néanmoins prendre garde, car cette possibilité fait baisser le niveau de sécurité de votre service. En effet, tout repose désormais sur les paramètres d'authentification et, outre des moyens sociaux, il faut veiller à ce que ces paramètres ne soient pas interceptés, c'est-à-dire ne circulent pas en clair sur des canaux non sécurisés. Il sera donc prudent de rajouter une couche de chiffrement, ou alors d'exclure certains types d'authentification comme les types PLAIN ou LOGIN. Un mécanisme d'authentification souvent utilisé est SASL (Simple Authentication and Security Layer), librairie développée par le projet Cyrus. La lecture du document Cyrus SASL for System Administrators donnera des élements pour installer et configurer conrrectement une authentification basée sur la librairie Cyrus. L'installation se fera à partir des sources ou de paquets (sasl2-bin libsasl2 libsasl2-modules). Certains modules sont optionnels et permettent d'utiliser diverses méthodes d'authentification (libsasl2-modules-gssapi-heimdal libsasl2-modules-kerberos-heimdal). Sous Debian Sarge, on installera le paqut postfix-tls qui contient notamment les extensions SASL pour Postfix. Plusieurs bases d'authentification sont possibles selon les configurations : * *shadow* : authentification basée sur le fichier _/etc/shadow_ * *pam* utilise directement les librairies PAM (on peut donc par exemple utiliser LDAP ou RADIUS) * *pwcheck* : authentification basée sur le deamon pwcheck utilisant aussi le fichier /etc/shadow (précision pour Debian Sarge : saslauthd est dans le paquet cyrus-common) * *saslauthd* : authentification basée sur le deamon saslauthd qui est plus flexible que pwcheck et peut utiliser PAM (mais aussi shadow, ldap, kerberos, etc,.) (précision pour Debian Sarge : saslauthd est dans le paquet sasl2-bin) La configuration s'effectue dans dans _/etc/default/saslauthd_ : ~~~ START=yes MECHANISMS="pam" OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd" ~~~ Et ajouter l'utilisateur `postfix` au groupe `sasl`. On vérifie la validité des utilisateurs par : ~~~ $ testsaslauthd -u username -p password ~~~ Note : attention, sous Debian Sarge, _testsaslauth_ ne tient apparemment pas compte du mécanisme passé en paramètre de saslauthd, c'est OK depuis Etch saslauthd utilise le fichier pam.d/smtp (ou pam.d/other) dans ce cas (quelques modifications sont nécessaires si Postfix est chrooté, voir section CHROOT) * *auxprop* (ou sasldb pour SASL version 1) : utilisation de /etc/sasldb(2) C'est l'authentification utilisée par défaut par Postfix (si aucun paramètre pwcheck_method n'est précisé dans le smtpd.conf) Commandes : sasldblistusers(2), saslpasswd(2) Note : possibilité d'utiliser une base de données avec l'option auxprop_plugin: sql (quelques modifications sont nécessaires si Postfix est chrooté, voir section CHROOT) Si vous utilisez une authentification non disponible, vous obtiendrez probablement : ~~~ warning: SASL authentication problem: unknown password verifier ~~~ Plusieurs possibilités de type d'authentification : NTLM, LOGIN, PLAIN, DIGEST-MD5, CRAM-MD5, KERBEROS4, GSSAPI, etc. Nous devons maintenant configurer postfix afin qu'il utilise SASL. Voir Postfix SMTP Authentification. Nous ajoutons les paramètres suivants : ~~~ smtpd_sasl_auth_enable = yes smtpd_recipient_restrictions = permit_sasl_authenticated, reject ~~~ Un fichier _smtpd.conf_ contiendra la méthode d'authentification et les types disponibles : ~~~ pwcheck_method: [choix_methode] mech_list: [choix_type] ~~~ Note concernant Debian Sarge : le paquet authsasld ne permet que les types PLAIN et LOGIN. Si l'on autorise un autre type, il cherchera le fichier /etc/sasldb2 (a priori, le paquet n'a pas été compilé avec les options --enable-cram --enable-digest). Exemple, authentification en PLAIN : ~~~ EHLO [hostname] AUTH PLAIN [mon_auth] ~~~ On obtient [mon_auth] ainsi : ~~~ $ printf 'username\0username\0password' | openssl base64 ~~~ Deuxième exemple, authentification en LOGIN : ~~~ EHLO [hostname] AUTH LOGIN [mon_login] [mon_password] ~~~ On obtient [mon_login] et [mon_password] ainsi : ~~~ $ printf 'username' | openssl base64 $ printf 'password' | openssl base64 ~~~ Pour en savoir plus, lisez Authentification SASL avec Postfix On peut aussi restreindre au niveau de Postfix les types d'authentification possibles : ~~~ smtpd_sasl_security_options = noanonymous, noplaintext ~~~ #### Authentification client SMTP Postfix, lorsqu'il communique avec d'autres serveurs en tant que client, peut avoir besoin de s'authentifier. On peut donc lui passer des paramètres d'authentifications pour certains serveurs : ~~~ smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd ~~~ Le fichier sasl_passwd contiendra : ~~~ foo.com username:password bar.com username ~~~ On peut choisir des options pour le mode compte, par exemple les types d'authentification autorisés : ~~~ smtp_sasl_security_options = noplaintext ~~~ ### Gestion du chroot de Postfix Enfermer Postfix dans un chroot permet de restreindre les accès à d'autres applications en cas de faille de sécurité. Cette protection s'indique au fichier master.cf. Par défaut, cette protection est activée sous Debian. Le répertoire de chroot se situe dans _/var/spool/postfix_ L'utilisation de chroot impose quelques modifications, notamment si l'on utilise l'authentification SMTP : * saslauthd Pour SASL avec la méthode saslauthd, il faut préciser la directive suivante dans le fichier _/etc/default/saslauthd_ : ~~~ OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd" ~~~ Note : avant Etch, il était nécessaire de réaliser un hack de ce type : ~~~ # mkdir /var/spool/postfix/var ; mkdir /var/spool/postfix/var/run # mv /var/run/saslauthd/ /var/spool/postfix/var/run/ # chown -R postfix /var/spool/postfix/var/run/saslauthd # ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd ~~~ Ne pas oublier de mettre des droits de lecture sur les répertoires _/var/spool/postfix/var/_ et _/var/spool/postfix/var/run/_ afin d'autoriser l'utilisateur _postfix_. L'utilisateur _postfix_ sera ajouté au groupe _sasl_ si nécessaire (si le répertoire saslauthd appartient à _root:sasl_). Sans ces changements, on obtiendra un message : ~~~ warning: SASL authentication failure: cannot connect to saslauthd server: Permission denied ~~~ * auxprop Pour SASL avec la méthode auxprop (ou sasldb) : ~~~ # mv /etc/sasldb2 /var/spool/postfix/etc/sasldb2 # ln -s /var/spool/postfix/etc/sasldb2 /etc/sasldb2 ~~~ * resolv.conf Le fichier _/etc/resolv.conf_ est copié dans _/var/spool/postfix/etc/resolv.conf_. Il faut le tenir synchronisé en cas de modification (notamment en cas d'installation sur un réseau différent du réseau final). ### Antispam Voir [/HowtoMail/Antispam](). ## Administration ### Logs Postfix envoie une trace de ses actions à _Syslog_ avec la facility *LOG_MAIL*. On retrouve donc les fichiers de journalisation définis dans le fichier `/etc/rsyslog.conf` : ~~~ mail.* -/var/log/mail.log mail.info -/var/log/mail.info mail.warn -/var/log/mail.warn mail.err /var/log/mail.err ~~~ *Note* : ce sont les adresses email d'enveloppe affichées dans les logs Postfix L'indication **delays=a/b/c/d** dans les logs est utile pour avoir des informations sur le temps d'envoi d'un mail : ~~~ a=time before queue manager, including message transmission; b=time in queue manager; c=connection setup time including DNS, HELO and TLS; d=message transmission time. ~~~ ### File d'attente Postfix utilise différentes files d'attente (ou queues). Les files d'attente principales sont _incoming_, _active_ et _deferred_ : ~~~ incoming : première étape pour tous les nouveaux messages (après un passage par cleanup) active : messages en cours de livraison (provenant principalement d'incoming ou deferred) deferred : messages non délivrés lors du premier essai ~~~ Il existe aussi d'autres files d'attente, qui servent beaucoup moins fréquemment : _corrupt_ (messages invalides) et _hold_ (messages mis de côté). Ces files d'attente sont des répertoires situés dans `/var/spool/postfix`dans lesquels chaque message est stocké dans un fichier (sur une seule ligne), avec une arborescence de 16 répertoires (0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F) pour optimiser lorsqu'un grand nombre de messages est dans une file d'attente. On peut gérer ces files d'attente grâce à des commandes d'administration. #### Lecture et analyse de la file d'attente `mailq` (ou `sendmail -bp`) liste toutes les files d'attente. Cela nous donne pour chaque message : * Queue ID * Taille du message * Date d'arrivée dans la file d'attente * Expéditeur * Éventuelle raison de non-livraison (entre parenthèses) * Destinataires(s) Voici dans quel ordre sont listés les messages : * Messages de la queue _active_ (une étoile figure à côté du Queue ID) * Messages de la queue _deferred_ * Messages de la queue _hold_ (un point d'exclamation figure à côté du queue ID) **Afficher le contenu d'un message :** ~~~ # postcat -vq ~~~ **Afficher seulement les mails IDs (utile pour les scripts) :** ~~~ # mailq | sed -E -n 's/^([[:alnum:]]+)[[:blank:]].*/\1/gp' ~~~ Exemple d'usage : ~~~bash keyword="blabla" ids=$(mailq | sed -E -n 's/^([[:alnum:]]+)[[:blank:]].*/\1/gp') for id in $ids; do mail_content=$() if postcat -q $id | grep -q $keyword; then echo "$id contains $keyword" # Faire quelque chose (voir la section suivante "Opérations sur la file d'attente") fi done ~~~ **Exclure les mails en cours d'envoi de l'affichage de la file d'attente :** ~~~ # mailq | sed -E '/v[[:alnum:]]+\*[[:blank:]]/,+2d' ~~~ **Compter le nombre d'e-mails par adresse expéditrice dans la `mailq` :** ~~~bash # mailq | awk '$1 ~ /^[0-9A-F]+$/ { a[$NF]++ } END { for (i in a) printf "%d %s\n", a[i], i }' | sort -n ~~~ **Obtenir la liste les expéditeurs triés par ordre croissant du nombre d’e-mails en attente d’envoi :** ~~~ # mailq | awk '/^[0-9A-F]+[*!]? /{a[$NF]++}END{for(i in a)print a[i],i | "sort -n"}' ~~~ *Note* : le `BEGIN { RS = "" }` est nécessaire car la sortie de mailq peut être sur plusieurs lignes, et le `tr -d '*!'` permet de ne pas prendre les messages en « hold ». **Lister les messages dans la file d'attente _deffered_ :** ~~~ # qshape deferred T 5 10 20 40 80 160 320 640 1280 1280+ TOTAL 78 0 0 0 0 1 0 0 0 0 77 gmail.fr 11 0 0 0 0 0 0 0 0 0 11 homail.fr 3 0 0 0 0 0 0 0 0 0 3 yaoo.fr 2 0 0 0 0 0 0 0 0 0 2 yahou.fr 2 0 0 0 0 0 0 0 0 0 2 oange.fr 2 0 0 0 0 0 0 0 0 0 2 hotmai.fr 2 0 0 0 0 0 0 0 0 0 2 wanado.fr 2 0 0 0 0 0 0 0 0 0 2 orangr.fr 1 0 0 0 0 0 0 0 0 0 1 prange.fr 1 0 0 0 0 0 0 0 0 0 1 ornage.fr 1 0 0 0 0 0 0 0 0 0 1 # Affichage par sender # qshape -s deferred ~~~ #### Opérations sur la file d'attente **Suppressions :** ~~~ ## Supprimer un message (ou tous) des files d'attente : # postsuper -d ## Supprimer tous les messages de la queue deferred # postsuper -d ALL deferred ## Supprimer tous les messages des files d'attente : # postsuper -d ALL # mailq -q ~~~ /!\\ Attention, `postsuper -d ALL` et `mailq -q` réactivent immédiatement l'ensemble des messages en file d'attente, il faut donc les utiliser avec modération, surtout sur les serveurs avec des files d'attentes chargées. **Divers :** ~~~ ## Libérer un message (ou tous) en « hold » # postsuper -H # postsuper -H ALL # Refaire passer un message (ou tous) par les process de livraison # postsuper -r # postsuper -r ALL ## Purger des fichiers temporaires (en cas de crash par exemple) # postsuper -p ## Réparer/vérifier l'arborescence des files d'attente # postsuper -s ~~~ La commande `postsuper -r` est pratique dans les cas où l'on a modifié des alias ou des ré-écritures, elle va déposer les messages concerné dans la queue _maildrop_ et lui attribuer un nouveau . Attention, cela ne va pas provoquer un envoi immédiat car le traitement des files d'attente est différé. Si l'on veut un ré-envoi immédiat d'un message : **Hold :** ~~~ ## Placer en « hold » un message (ou tous) # postsuper -h # postsuper -h ALL ## Placer en « hold » tous les messages de la queue deferred # postsuper -h ALL deferred ~~~ **Traitement par lot via un pré-filtrage avec Awk :** On pourra utiliser ces commandes sur des ensembles de messages via des scripts du type : ~~~ # mailq | tail -n +2 | awk 'BEGIN { RS = "" } /user@example\.com/ { print $1 }' | tr -d '*!' | postsuper -h - # mailq | tail -n +2 | awk 'BEGIN { RS = "" } /example\.com/ { print $1 }' | tr -d '*!' | postsuper -d - # mailq | awk '/^[0-9A-Z]+/&&/sender@example\.com$/{print $1}' | tr -d '*!' | postsuper -h - # mailq | awk '/^[0-9A-Z]+/&&/example\.com$/{print $1}' | tr -d '*!' | postsuper -d - # mailq > mailq.log ; for var in $(grep mailq.log | cut -b '1-12'); do postsuper -d $var; done ## Supprimer les e-mails envoyés par someone@some.where # mailq | awk '/^[0-9A-F]+[!*]? /&&/someone@some\.where$/{gsub("[!*]", "", $1); print $1 | "postsuper -d -"}' ## Supprimer les courriels envoyé vers @example.com # mailq | tail -n +2 | awk 'BEGIN { RS = "" } /@example\.com$/ { r = $1; gsub(/[!*]/, "", r); print r }' | postsuper -d - ~~~ Supprimer les mails correspondant à ce type de ligne : ~~~ 6B28125849 3039 Fri Sep 25 07:27:53 MAILER-DAEMON (host mx2.foo.com[1.2.3.4] said: 452 Too many incoming emails for this account (in reply to RCPT TO command)) mail.example.com # mailq | awk '/^[0-9A-F]+/&&/MAILER-DAEMON$/{id=$1} /mail@example.com$/{print id}' | postsuper -d - ~~~ ### Notifications Postfix envoie des notifications à ajuster avec l'option `notify_classes`. On peut ainsi ajuster cette option ainsi : ~~~ notify_classes = resource, software, bounce, 2bounce, delay delay_notice_recipient = delay error_notice_recipient = error bounce_notice_recipient = 1bounce 2bounce_notice_recipient = 2bounce ~~~ Puis ajuster les alias via `/etc/alias` : ~~~ error: localadmin 1bounce: postmaster 2bounce: postmaster delay: alert0@example.com ~~~ /!\\ Attention, pour un serveur recevant pas mal de messages, cela peut générer pas mal de notifications. Si nécessaire, ajuster ainsi pour avoir un minimum d'alertes : ~~~ notify_classes = resource, software error_notice_recipient = error ~~~ ## Plomberie Postfix est découpé en plusieurs processus (qmgr, pickup, smtp, smtpd, bounce, cleanup, error, etc.) contrôlé par un processus nommé `master`. Chaque processus est défini dans le fichier de configuration `master.cf`. Sur un serveur inactif, vous verrez au minimum les processus suivants : ~~~ |-master,432636 -l -t unix -u | |-qmgr,5036 -l -t unix -u-u -c | `-pickup,9162 -l -t unix -u -c ~~~ Sur un serveur actif, vous verrez de nombreux processus, par exemple : ~~~ |-master,2576 | |-scache,13334 -l -t unix -u | |-qmgr,22888 -l -t fifo -u | |-anvil,22891 -l -t unix -u | |-smtp,25261 -t unix -u | |-smtp,26204 -t unix -u | |-trivial-rewrite,26596 -n rewrite -t unix -u | |-smtp,26629 -t unix -u | |-pickup,27010 -l -t fifo -u | |-smtp,27102 -t unix -u | |-smtp,27976 -t unix -u | |-proxymap,28383 -t unix -u | |-smtp,29967 -t unix -u | |-smtp,29968 -t unix -u | |-smtp,29969 -t unix -u | |-bounce,29970 -z -t unix -u | |-bounce,30351 -z -n defer -t unix -u | |-bounce,30352 -z -n defer -t unix -u | |-bounce,30354 -z -n defer -t unix -u | |-bounce,30355 -z -n defer -t unix -u | |-cleanup,30364 -z -t unix -u | |-cleanup,30365 -z -t unix -u | |-smtpd,30366 -n smtp -t inet -u -o stress= -s 2 | |-error,30367 -n retry -t unix -u | |-error,30368 -n retry -t unix -u | |-error,30369 -n retry -t unix -u | `-smtpd,30374 -n smtp -t inet -u -o stress= -s 2 ~~~ Voici un schéma qui illustre la communication entre les processus/files d'attente/tables : Architecture de Postfix * Le processus **bounce** gère les messages de non-livraison qui sont stockés dans les répertoires `/var/spool/postfix/bounce/*`, `/var/spool/postfix/defer/*` ou encore `/var/spool/postfix/trace/*` selon les types de message. ### Changer les templates de bounce Par exemple pour mettre un message personnalisé (et en Français) des DSN du type « successful delivery ». Installer le paquet `postfix-doc`, copier le fichier `bounce.cf.default` dans `/etc/postfix/bounce.cf`, éditer le fichier comme voulu et ajouter la directive `bounce_template_file = /etc/postfix/bounce.cf` à postfix. ``` # apt install postfix-doc # install -m 644 /usr/share/doc/postfix-doc/examples/bounce.cf.default /etc/postfix/bounce.cf # vim /etc/postfix/bounce.cf # echo "bounce_template_file = /etc/postfix/bounce.cf" >> /etc/postfix/main.cf # systemctl reload postfix ``` ## Monitoring La surveillance régulière des fichiers de journalisation ainsi que des files d'attente s'avère nécessaire, éventuellement à l'aide d'outils permettant de générer des statistiques, des courbes, etc. On peut ainsi citer l'outil **mailgraph** qui trace des courbes _rrdtool_ à partir du fichier de journalisation, ou encore **Munin** qui trace des courbes selon l'état des files d'attente. ### mailgraph ~~~ # apt install mailgraph ~~~ [mailgraph](http://mailgraph.schweikert.ch/) fait tourner un démon Perl qui analyse `/var/log/mail.log`, on peut ensuite visualiser des courbes RRDtool via un script CGI `/usr/lib/cgi-bin/mailgraph.cgi`. Pour diverses raisons, si l'on ne veut pas avoir de module CGI on pourra utiliser un script Shell à placer en crontab : ~~~{.bash} #!/bin/sh MAILGRAPH_PATH=/usr/lib/cgi-bin/mailgraph.cgi # Debian MAILGRAPH_DIR=/var/www/mailgraph umask 022 mkdir -p $MAILGRAPH_DIR $MAILGRAPH_PATH | sed '1,2d ; s/mailgraph.cgi?//' > $MAILGRAPH_DIR/index.html for i in 0-n 0-e 1-n 1-e 2-n 2-e 3-n 3-e; do QUERY_STRING=$i $MAILGRAPH_PATH | sed '1,3d' > $MAILGRAPH_DIR/$i done ~~~ ### Munin Par défaut, on trouve des plugins intéressants, notamment *postfix_mailqueue* pour l'évolution des files d'attente. Pour activer les plugins Postfix pour Munin : ~~~ # cd /etc/munin/plugins # ln -s /usr/share/munin/plugins/postfix_mailqueue # ln -s /usr/share/munin/plugins/postfix_mailstats # ln -s /usr/share/munin/plugins/postfix_mailvolume ~~~ ### Nagios Voici des checks standards pour vérifier que Postfix répond en SMTP et surveiller sa file d'attente : ~~~ $ /usr/lib/nagios/plugins/check_smtp -H localhost $ /usr/lib/nagios/plugins/check_mailq -M postfix -w 42 -c 1337 ~~~ ### log2mail Pour être alerté en cas d'erreurs graves, voici une config pour log2mail : ~~~ file = /var/log/mail.log pattern = "fatal:" mailto = alert@example.com pattern = "panic:" mailto = alert@example.com pattern = "No such file or directory" mailto = alert@example.com pattern = "table lookup problem" mailto = alert@example.com pattern = "warning: connect to Milter service" mailto = alert@example.com pattern = "451 4.7.1 Service unavailable - try again later" mailto = alert@example.com ~~~ ### pflogsumm C'est un petit outil pour afficher des stats sur les logs mails. Plutôt pratique, il évite de « grepper » à la main `mail.log`. ~~~ pflogsumm /var/log/mail.log [/var/log/mail.log.1 [...]] >> stats_mail.out ~~~ ## Délivrabilité La _délivrabilité_ est un concept visant à s'assurer qu'un email envoyé va bien atteindre son destinataire. Voici un check-up pour s'assurer d'avoir une bonne _délivrabilité_ : * Reverse DNS configuré vers un enregistrement valide pointant lui-même vers l'adresse IP du serveur mail * IPv6 correctement configuré (avec reverse DNS) ou desactivé * Utiliser une adresse de retour valide (expéditeur d'enveloppe ou **Return-Path**) et traiter les retours régulièrement voire dynamiquement en cas de gros volume * Configurer SPF * Configurer DKIM * Configurer DMARC * Nettoyer ses entêtes, notamment des informations locales (IP RFC1918, enregistrements DNS locaux, etc.) * S'enregistrer auprès de * S'enregistrer auprès de (payant, environ 20$/domaine/an) * Pour Hotmail/Outlook/Microsoft/Office365, faire un ticket support depuis [sender.office.com](https://sender.office.com/) et ce formulaire pour autoriser IPv4. * Payer pour améliorer sa délivrabilité auprès de Yahoo/Microsoft/etc. (payant en fonction du volume et très cher...) * Régler son rythme d'envoi, notamment vers Orange, Free, etc. * Vérifier son contenu via des outils comme _SpamAssassin_ * Vérifier la réputation via * Vérifier via Postmaster tools de Google en cas de problème de Spam pour Google/Gmail * Vérifier via en cas de problème de Spam pour Microsoft/Hotmail/Live ### SPF [SPF](https://fr.wikipedia.org/wiki/Sender_Policy_Framework) est une norme pour vérifier l'adresse IP expéditrice d'un email. La vérification se fait en utilisant le nom de domaine de l'expéditeur d'enveloppe et en récupérant un enregistrement DNS qui va lister les adresses IP autorisées. Voici un exemple d'enregistrement DNS autorisant des adresses IP pour une adresse en `@example.com` ~~~ @ IN TXT "v=spf1 a mx ptr ip4:192.0.2.142 ip4:192.0.2.0/24 ip6:2001:db8::/32 ~all" ~~~ Voici un exemple d'enregistrement DNS autorisant l'envoi de n'importe où : ~~~ @ IN TXT "v=spf1 a mx ptr +all" ~~~ On peut utiliser un `include:` vers un autre enregistrement TXT, pratique pour la gestion ou éviter d'avoir des enregistrements TXT [dépassant 255 caractères](https://kb.isc.org/docs/aa-00356). Voici un exemple, les deux chaines de caractères seront concaténées donc il ne faut pas oublier qu'au moins une des deux chaine doit contenir une espace libre : ~~~ @ IN TXT "v=spf1 a mx ptr ip4:192.0.2.142 ip4:192.0.2.0/24" " ip6:2001:db8::/32 ~all" ~~~ Chez Evolix, on utilise ainsi `include:spf.protection.evolix.net`. Si vous utilisez [Mailchimp](https://mailchimp.com/developer/transactional/docs/authentication-delivery/) vous devez ajouter `include:spf.mandrillapp.com` par exemple. #### Vérification SPF Pour vérifier les enregistrements SPF des emails puis rejeter les emails invalides et marquer le résultat de la vérification via un entête `Received-SPF` nous utilisons [policyd-spf](https://manned.org/man/debian/policyd-spf) : ~~~ # apt install postfix-policyd-spf-python # cp /usr/share/doc/postfix-policyd-spf-python/policyd-spf.conf.commented /etc/postfix-policyd-spf-python/policyd-spf.conf ~~~ On ajoutera dans `/etc/postfix/master.cf` : ~~~ policyd-spf unix - n n - 0 spawn user=policyd-spf argv=/usr/bin/policyd-spf ~~~ et `/etc/postfix/main.cf` : ~~~ smtpd_recipient_restrictions = ... reject_unauth_destination check_policy_service unix:private/policyd-spf ... policyd-spf_time_limit = 3600 ~~~ Voici les paramètres intéressants pour `/etc/postfix-policyd-spf-python/policyd-spf.conf` : ~~~ defaultSeedOnly = 0 # Mode simulation, aucun rejet, seulement la description de l'action dans les logs. Mail_From_reject = Fail # Rejete les mails si le check SPF échoue. Mail_From_reject = Softfail # Rejete les mails si le check SPF échoue même en « soft » (utilisation de ~all par exemple), non recommandé. Reject_Not_Pass_Domains = aol.com,hotmail.com # Transoforme un ~all en -all pour des domaines en particuliers. ~~~ Voir [policy-spf.conf(5)](https://manned.org/man/debian/policyd-spf.conf). Cela ajoutera l'entête suivant aux emails : ~~~ Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=192.0.2.1; helo=mail.example.com; envelope-from=jdoe@example.com; receiver= ~~~ ou en cas d'échec : ~~~ Received-SPF: Softfail (mailfrom) identity=mailfrom; client-ip=192.0.2.1; helo=mail.example.com; envelope-from=jdoe@example.com; receiver= ~~~ Note : `receiver=` est une anonymisation pour des raisons de confidentialité, cf l'option par défaut `Hide_Receiver = Yes` Cet entête pourra notamment être utilisé par des filtres, SpamAssassin, etc. > *Note* : attention, pour les emails locaux, cela n'ajoutera pas l'entête `Received-SPF` ce qui peut poser des soucis avec les outils s'appuyant dessus, notamment SpamAssassin ou OpenDMARC. #### Utilitaire `spfquery` Pour vérifier manuellement un enregistremnt SPF vous pouvez utiliser `spfquery` fourni par le paquet du même nom. La commande necessite 3 arguments et s'utilise comme suit : ~~~ $ spfquery -ip=31.170.8.17 -sender=example@evolix.fr -helo=evolix.fr pass spfquery: domain of evolix.fr designates 31.170.8.17 as permitted sender Received-SPF: pass (spfquery: domain of evolix.fr designates 31.170.8.17 as permitted sender) client-ip=31.170.8.17; envelope-from=example@evolix.fr; helo=evolix.fr; ~~~ #### Utilisaire `spf` L'utilitaire [`spf`](https://github.com/jschauma/spf/) permet aussi d'avoir une vision synthétique sur la configuration SPF d'un domaine. Écrit en Perl il est facile à installer et fonctionne presque partout. ~~~ $ spf netmeister.org netmeister.org: policy: a -all valid pass: a (1 name): netmeister.org a (2 IPs): 166.84.7.99 2001:470:30:84:e276:63ff:fe72:3900 All others: fail SPF record for domain 'netmeister.org': valid Total counts: Total number of DNS lookups : 1 pass: Total # of a directives : 1 Total # of ip4 addresses : 1 Total # of ip6 addresses : 1 All others: fail ~~~ ### DKIM [DKIM](HowtoOpenDKIM) est une norme pour ajouter une signature cryptographique dans les entêtes d'un email envoyé. La signature se fait à partir à de l'expéditeur d'entête (`From:` d'un email), des entêtes au choix (sujet, date, etc.) et le corps du message. Cela utilise aussi une clé publique stockée dans un enregistrement DNS TXT. Voir ### DMARC [DMARC](https://fr.wikipedia.org/wiki/DMARC) est une spécification qui vient en complément de DKIM et SPF. Cela permet de spécifier aux serveurs de messagerie comment traiter les emails reçus non conformes aux vérifications SPF et/ou DKIM. Cela permet également de récupérer des informations voire des emails complets si ils ne sont pas conformes. Encore une fois, cela se fait avec un enregistrement DNS TXT. Voici un exemple d'enregistrement DNS basique : ~~~ _dmarc IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@example.com" ~~~ On pourra spécifier : * `p=none` si l'on ne veut pas que les emails non conformes soient rejetés * `p=reject` si l'on veut que les emails non conformes soient rejetés (rarement utilisé) * `p=quarantine` si l'on veut que les emails non conformes soient mis de côté (dans une sous-boîte Spam en général) Attention, si vous spécifiez `rua=mailto:dmarc@example.com` vous recevrez pas mal de rapports `Report domain` de Google, Outlook, etc. vous notifiant des emails non conformes. Les rapports incluent un fichier XML, on peut le lire via des outils comme [mxtoolbox](https://mxtoolbox.com/DmarcReportAnalyzer.aspx) ou [easydmarc](https://easydmarc.com/tools/dmarc-aggregated-reports). Voici un exemple d'un enregistrement DNS plus avancé : ~~~ _dmarc IN TXT "v=DMARC1;p=reject;rua=mailto:dmarc+aggr@example.com;ruf=mailto:dmarc+forensic@example.com;fo=1;adkim=r;aspf=r;sp=none;pct=100" ~~~ #### Vérification DMARC Pour vérifier la politique des emails nous utilisons [OpenDMARC](https://github.com/trusteddomainproject/OpenDMARC). OpenDMARC s'appuie sur [DKIM](HowtoOpenDKIM) qui ajoute l'entête `Authentication-Results`, il faut donc au préalable avoir installé et configuré [OpenDKIM](HowtoOpenDKIM). OpenDKIM s'appuye également sur l'entête `Received-SPF` mais il peut également faire la vérification SPF lui-même. On installe : ~~~ # apt install opendmarc # systemctl enable opendmarc # systemctl start opendmarc ~~~ On configure via `/etc/opendmarc.conf` : ~~~ AuthservID mail.example.com PidFile /var/run/opendmarc/opendmarc.pid PublicSuffixList /usr/share/publicsuffix Socket inet:8893@localhost #Socket local:/var/run/opendmarc/opendmarc.sock Syslog true UMask 0002 UserID opendmarc IgnoreHosts /etc/opendmarc/ignore.hosts SPFSelfValidate true IgnoreAuthenticatedClients true ~~~ Par défaut, OpenDMARC se contente de vérifier et d'ajouter l'entête `Authentication-Results` (AR). Si l'on veut que les emails avec une politique DMARC invalide soit rejeté (mais c'est rare car `p=reject` est rarement utilisé), on peut mettre l'option : ~~~ RejectFailures true ~~~ Voir [opendmarc.conf(5)](https://manned.org/man/debian/opendmarc.conf). Et il faut ajouter un fichier `/etc/opendmarc/ignore.hosts` pour ignorer les emails locaux : ~~~ # mkdir /etc/opendmarc # touch /etc/opendmarc/ignore.hosts # chown -R opendmarc:opendmarc /etc/opendmarc # cat /etc/opendmarc/ignore.hosts 127.0.0.0/8 ::1/128 localhost localhost.localdomain 192.168.0.0/16 192.0.2.0/24 ~~~ Et l'on ajoute un milter à la suite de celui pour [OpenDKIM](HowtoOpenDKIM) : ~~~ non_smtpd_milters = inet:127.0.0.1:8891 inet:127.0.0.1:8893 smtpd_milters = inet:127.0.0.1:8891 inet:127.0.0.1:8893 in_flow_delay = 0s ~~~ Cela ajoutera un 2e entête `Authentication-Results` (AR) en plus de celui d'OpenDKIM : ~~~ Authentication-Results: antispam.example.com; dmarc=pass (p=none dis=none) header.from=example.com ~~~ ou en cas d'échec : ~~~ Authentication-Results: antispam.example.com; dmarc=fail (p=none dis=none) header.from=example.com ~~~ Cet entête pourra notamment être utilisé par des filtres, SpamAssassin, etc. ### Contacts des principaux fournisseurs d'email En cas de souci de _délivrabilité_ vers un domaine particulier, on est amené à contacter son responsable. En théorie l'adresse email `postmaster@` permet cela. En pratique pour les principaux fournisseurs d'emails, voici comment les contacter : * Free : * Orange : * Hotmail/Outlook/Microsoft : * Yahoo : * La Poste : * GMAIL : (NE REPONDENT JAMAIS !!!) ## Postcreen *Postscreen* est un démon léger destiné à faire des tests préliminaires avant de passer un message entrant à Postfix… ou de le rejeter ! Voir ## FAQ ### Envoyer un mail de test en CLI ~~~ $ telnet 127.0.0.1 25 HELO example.com MAIL FROM: RCPT TO: DATA From: To: Foo Subject: test Ceci est un test . ~~~ ### Récupérer expéditeur et destinataire dans mail.log Pour récupérer à la fois l'adresse expéditeur et destinataire dans les logs : ~~~ # grep "blocked using FBLW15" /var/log/mail.log | cut -d " " -f 6 | tr -d ':' \ | while read msgid; do grep $msgid /var/log/mail.log |grep " postfix/" \ | grep -E '(from|to)=<'|awk -F ' ' '{ print $1,$2,$3,$7 }' |tr -d ','; echo; done ~~~ ### Taille maximum d'un message Par défaut, la taille d'un message est limitée à 10 Mo, cela se modifie avec le paramètre `message_size_limit`. Attention, lorsqu'une pièce jointe est dans un format binaire (exemples : JPG, PDF, etc.), les emails sont traduits en caractères texte (conversion [uuencode](https://fr.wikipedia.org/wiki/Uuencode)) ce qui provoque une augmentation de la taille jusqu'à 40%. Voici par exemple le paramètre que l'on conseille de mettre si l'on veut autoriser les messages jusqu'à 20 Mo : ~~~ message_size_limit = 25600000 ~~~ Attention, la taille par défaut de la mailbox est de 50 Mo (`mailbox_size_limit = 51200000`). Si vous définissez `message_size_limit` > `mailbox_size_limit` (sauf si la taille est illimitée avec `mailbox_size_limit = 0`), Postfix bloquera les mails dans la queue (avec un `*`). ### SMTPUTF8 SMTPUTF8 est une extension pour support l'UTF8 dans les entêtes de messages. En effet, de façon standard tous les entêtes de messages doivent avoir un encoding spécial pour les caratères non ASCII. Il peut arriver que cela pose des problèmes, notamment avec des clients SMTP qui gèrent mal cet encoding. À partir de Debian 9, on peut alors activer l'option `smtputf8_enable = yes` dans Postfix. Et Postfix annoncera qu'il supporte cette extension : ~~~ $ nc 127.0.0.1 25 220 smtp.example.com ESMTP mail server EHLO foo.bar 250-smtp.example.com 250-PIPELINING 250-SIZE 51200000 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8 ~~~ Pour plus de détails, lire ### Relai vers Mailjet selon l'expéditeur Voir leur documentation : ### .forward Voir aussi : [/HowtoMail/Roundcube#plugin-vacation]() De façon similaire aux fichiers `.htaccess` pour Apache, un utilisateur UNIX peut créer un fichier `.forward` à la racine de son home-directory pour faire passer tous ses emails reçus dans une moulinette : renvoi automatique vers une autre adresse, traitement via Procmail, envoi d'un message d'absence, etc. Attention, cela ne fonctionne que pour Postfix en mode local, cela ne fonctionne pas en mode virtual. Pour ré-envoyer tous les emails vers une autre adresse `jdoe@example.com` on mettra simplement : ~~~ $ cat ~/.forward jdoe@example.com ~~~ Pour envoyer tous les emails vers une autre adresse MAIS garder une copie sur sa boîte `foo` : ~~~ $ whoami foo $ cat ~/.forward \foo,jdoe@example.com ~~~ Pour faire traiter tous ses emails reçus par le logiciel Procmail : ~~~ $ cat ~/.forward "| IFS=' ' && exec /usr/bin/procmail -f- || exit 75" ~~~ Pour envoyer un message d'absence en gardant une copie sur sa boîte `foo` : ~~~ $ cat ~/.forward \foo,"|/usr/bin/vacation foo" ~~~ ### vacation Voir aussi : [/HowtoMail/Roundcube#plugin-vacation]() ~~~ # apt install vacation ~~~ Le programme `vacation` permet d'envoyer des messages d'absence SANS renvoyer des messages aux adresses déjà prévenues et SANS envoyer de message d'absence quand le mail reçu est une copie cachée. **ATTENTION :** vacation n'envoie PAS de message d'absence si la destination n'est pas le compte UNIX. Par exemple si l'on a un compte `jdoe` et que l'on reçoit un email sur `john.doe@example.com` aucun message d'absence ne sera renvoyé. Il faut alors préciser un alias avec l'option `-a` : ~~~ /usr/bin/vacation -a john.doe -a jdoe ~~~ Le message d'absence en lui-même se trouve dans `~/.vacation.msg`, on conseille notamment de préciser le `Content-Type` et d'éviter les accents dans le sujet : ~~~ $ cat ~/.vacation.msg From: John Doe Subject: John Doe / Example - Absence Content-Type: text/plain; charset=UTF-8 Je suis en congé parental, veuillez joindre mon collègue. ~~~ On peut lister les adresses qui ont reçu un message d'absence ainsi : ~~~ $ vacation -l ~~~ ### Restreindre selon le From ~~~ check_recipient_access hash:/etc/postfix/protected_users, smtpd_restriction_classes = onlylocal onlylocal = check_sender_access hash:/etc/postfix/onlylocal, reject /etc/postfix/protected_users : service.intra@ onlylocal ~~~ ### Transporter les mails vers un autre serveur et/ou port On s'appuye sur la directive `transport_maps` : ~~~ transport_maps = hash:$config_directory/transport ~~~ On pourra alors éditer le fichier `/etc/postfix/transport` : ~~~ outlook.com smtp:[gw.example.com] ~~~ Ainsi les emails vers `@outlook.com` seront déviés et envoyés en SMTP vers les adresses IP correspondantes à `gw.example.com`. ### Date et Maildir Le format _Maildir_ s'appuye sur les dates du système de fichiers. On peut ainsi par exemple rechercher les emails entre le 18 mai 2016 et 11 octobre 2016 ainsi : ~~~ $ find $HOME/Maildir/.foo/ -type f -newermt 2016-05-18 ! -newermt 2016-09-11 ~~~ ### warning: service "smtp" (25) has reached its process limit "100" En cas de message d'erreur du type : ~~~ postfix/master: warning: service "smtp" (25) has reached its process limit "100": new clients may experience noticeable delays postfix/master: warning: to avoid this condition, increase the process count in master.cf or reduce the service time per client postfix/master: warning: see http://www.postfix.org/STRESS_README.html for examples of stress-adapting configuration settings ~~~ Vous pouvez augmenter le paramètre `maxproc` ainsi dans le `master.cf` : ~~~ # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ========================================================================== smtp inet n - y - 1000 smtpd ~~~ ou alors de façon plus globale le paramètre `default_process_limit` : ~~~ default_process_limit = 500 ~~~ ### Header Checks