diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..59564548
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "roles/re2o-mail-server/templates/re2o-services/mail-server/mail-aliases"]
+	path = roles/re2o-mail-server/templates/re2o-services/mail-server/mail-aliases
+	url = https://gitlab.crans.org/nounous/mail-aliases
diff --git a/network.yml b/network.yml
index b96909f2..de78097f 100644
--- a/network.yml
+++ b/network.yml
@@ -68,3 +68,27 @@
   roles:
     - quagga-ipv6
 
+# Deploy postfix on mail servers
+- hosts: titanic.adm.crans.org
+  vars:
+    postfix:
+      primary: false
+      secondary: true
+      public: true
+      dkim: true
+      mailman: false
+      titanic: true
+  roles:
+    - postfix
+
+- hosts: sputnik.adm.crans.org
+  vars:
+    postfix:
+      primary: false
+      secondary: true
+      public: true
+      dkim: true
+      mailman: false
+      titanic: false
+  roles:
+    - postfix
diff --git a/re2o.yml b/re2o.yml
index 0cc43d65..219375f0 100644
--- a/re2o.yml
+++ b/re2o.yml
@@ -76,3 +76,8 @@
 - hosts: routeur.adm.crans.org
   roles:
     - re2o-firewall-routeur
+
+# Deploy re2o mail-server on MTA and MDA
+- hosts: titanic.adm.crans.org,sputnik.adm.crans.org
+  roles:
+    - re2o-mail-server
diff --git a/roles/postfix/tasks/main.yml b/roles/postfix/tasks/main.yml
new file mode 100644
index 00000000..aa39d54b
--- /dev/null
+++ b/roles/postfix/tasks/main.yml
@@ -0,0 +1,28 @@
+---
+- name: Install postfix
+  apt:
+    update_cache: true
+    name:
+      - postfix
+  register: apt_result
+  retries: 3
+  until: apt_result is succeeded
+
+- name: Deploy postfix configuration
+  template:
+    src: postfix/{{ item }}.j2
+    dest: /etc/postfix/{{ item }}
+    mode: 0644
+    owner: root
+    group: root
+  loop:
+    - main.cf
+    - master.cf
+    - transport
+    - mime_header_checks
+    - recipient_access
+    - sender_login_maps
+    - postscreen_access.cidr
+    - sasl/smtpd.conf
+    - canonical
+#   - virtual
diff --git a/roles/postfix/templates/postfix/canonical.j2 b/roles/postfix/templates/postfix/canonical.j2
new file mode 100644
index 00000000..c0cfd082
--- /dev/null
+++ b/roles/postfix/templates/postfix/canonical.j2
@@ -0,0 +1,6 @@
+# {{ ansible_managed }}
+# Fichier fournissant des méthodes pour traduire certaines adresses
+
+/^(.*)@localhost(\.crans\.org)?$/   ${1}@crans.org
+/^(.*)@{{ ansible_hostname }}.adm.crans.org$/   ${1}@crans.org
+/^(.*)@{{ ansible_hostname }}.crans.org$/       ${1}@crans.org
diff --git a/roles/postfix/templates/postfix/main.cf.j2 b/roles/postfix/templates/postfix/main.cf.j2
new file mode 100644
index 00000000..d4b299c4
--- /dev/null
+++ b/roles/postfix/templates/postfix/main.cf.j2
@@ -0,0 +1,250 @@
+# {{ ansible_managed }}
+# Fichier de configuration principal de postfix.
+
+# +------------------+
+# | Variables utiles |
+# +------------------+
+
+# Definition par securite (sinon il utilise gethostname)
+myhostname = {{ ansible_hostname }}.crans.org
+mydomain = crans.org
+# Origine des mails
+myorigin = crans.org
+# Reseaux locaux
+mynetworks = 127.0.0.0/8, [::1]/128
+{% if postfix.primary or postfix.secondary %}
+             138.231.136.0/21, 185.230.79.0/24, 185.230.77.0/24, 185.230.76.0/24, 185.230.78.0/24, 10.53.0.0/19, 10.54.0.0/19, [2a0c:700:0:1::]/64, [2a0c:700:0:22::]/64, [2a0c:700:0:21::]/64, [2a0c:700:0:23::]/64, [2a0c:700:0:24::]/64, 10.231.136.0/24, [2a0c:700:0:2::]/64
+{% else %}
+             10.231.136.0/24, [2a0c:700:0:2::]/64
+{% endif %}
+# Destinations acceptees
+mydestination = {{ ansible_hostname }}, $myhostname, localhost, localhost.$mydomain
+{% if postfix.primary or not postfix.secondary %}
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
+{% endif %}
+# Domaine relaye par ce MX
+relay_domains = $mydestination
+{% if postfix.mailman %}
+                lists.$mydomain
+{% endif %}
+{% if postfix.secondary %}
+                $mydomain, crans.ens-cachan.fr, clubs.ens-cachan.fr, install-party.ens-cachan.fr, crans.fr, crans.eu
+{% endif %}
+{% if postfix.public %}
+                lists.$mydomain
+{% endif %}
+{% if postfix.mailman %}
+relay_recipient_maps =
+    hash:/var/local/re2o-services/mail-server/generated/virtual
+    hash:/var/lib/mailman/data/virtual-mailman
+mailman_destination_recipient_limit = 1
+{% endif %}
+# Etre notifie ou non de l'arrive de nouveaux mails
+{% if postfix.primary or postfix.secondary %}
+biff = no
+{% else %}
+biff = yes
+{% endif %}
+# Pour pouvoir tester sans tout casser, on active les soft bounces.
+# Ca permet aux mails de ne pas etre bounces en cas d'erreur, mais
+# a la place, de renvoyer une erreur non permanente. En production
+# il faut enlever ca.
+soft_bounce = no
+
+smtpd_reject_unlisted_sender = yes
+{% if not postfix.primary and not postfix.secondary %}
+# On delivre dans des maildir
+mail_spool_directory = /home/mail/
+{% endif %}
+# +--------+
+# | Divers |
+# +--------+
+# Delais pour les warnings
+delay_warning_time = 24h
+# Esthetisme
+smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
+# Par ou passer (notement pour la distrtibution des adresse
+# locales par le serveur des adherents)
+transport_maps = hash:/etc/postfix/transport
+# Une infinite d'adresses mail par personne
+recipient_delimiter = +
+# +-----------------+
+# | Bases d'adresse |
+# +-----------------+
+# Les fichiers d'alias (pour newaliases)
+alias_database = hash:/var/local/re2o-services/mail-server/generated/aliases
+alias_maps = $alias_database
+# On prend aussi en compte les utilisateurs de /etc/passwd
+local_recipient_maps = $alias_maps unix:passwd.byname
+# Les anciennes ML @crans.org, @crans.ens-cachan.fr -> @lists.crans.org
+virtual_alias_maps = hash:/var/local/re2o-services/mail-server/generated/virtual
+
+# +-------------+
+# | TLS et SASL |
+# +-------------+
+
+# TLS pour la reception
+smtpd_use_tls=yes
+smtpd_tls_security_level=may
+smtpd_tls_cert_file=/etc/ssl/certs/smtp.pem
+smtpd_tls_key_file=/etc/ssl/private/smtp.pem
+smtpd_tls_loglevel=0
+smtpd_tls_received_header=yes
+
+# On utilise aussi TLS pour envoyer les mails
+smtp_use_tls=yes
+smtp_tls_security_level=may
+smtp_tls_loglevel=1
+smtp_tls_cert_file=
+smtp_tls_key_file=
+smtp_tls_CApath=/etc/ssl/certs/
+
+
+# On cache les sessions TLS car elles sont couteuses.
+smtpd_tls_session_cache_database=btree:/var/lib/postfix/smtpd_tls_session_cache
+smtp_tls_session_cache_database=btree:/var/lib/postfix/smtp_tls_session_cache
+
+tls_random_source=dev:/dev/urandom
+
+# Auth que si tls pour eviter des pass en clair sur le reseau
+smtpd_tls_auth_only=yes
+# Authentification SASL pour relayer du mail
+smtpd_sasl_auth_enable=yes
+
+# +--------------------------+
+# | Filtrages et limitations |
+# +--------------------------+
+
+{% if postfix.public %}
+smtpd_helo_required = yes
+smtpd_helo_restrictions = permit_mynetworks
+                          reject_invalid_helo_hostname
+                          reject_non_fqdn_helo_hostname
+{% endif %}
+## Limitation des messages envoyés par minute
+# On n'ignore que les messages venant d'adresses "protégées"
+smtpd_client_event_limit_exceptions = local_networks
+                                      10.231.136.0/24, [2a0c:700:0:2::]/64
+ # we remove the smtpd_access_maps, so that crans.org in the recipient_access does not capture subdomains
+parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,permit_mx_backup_networks,qmqpd_authorized_clients,relay_domains
+
+# On limite à 10 messages par minute
+smtpd_client_message_rate_limit = 10
+
+{% if postfix.public %}
+smtpd_sender_login_maps = hash:/etc/postfix/sender_login_maps
+{% endif %}
+## Filtrage au MAIL FROM
+smtpd_sender_restrictions = permit_mynetworks
+{% if postfix.public %}
+# Si pas authentifié pour un domaine de smtpd_sender_login_maps
+# on dégage. Si authentifié, on envoit même si c'est du spoof
+# interne.
+                            reject_unauthenticated_sender_login_mismatch
+{% endif %}
+                            reject_non_fqdn_sender
+                            reject_unknown_sender_domain
+
+## Dit à postfix de jeter toute socket vers un serveur de policy après une
+## utilisation. Il en recrée donc une nouvelle, ce qui permet d'éviter
+## qu'un service de policy droppant silencieusement ses sockets ralentisse
+## postfix. C'est un palliatif en attendant de corriger ratelimit/policy
+smtpd_policy_service_request_limit = 1
+## Filtrage au RCPT TO
+smtpd_recipient_restrictions =
+{% if postfix.primary %}
+# Test avec policyd-rate-limit pour limiter le nombre de mails par utilisateur SASL
+                               check_policy_service unix:ratelimit/policy
+{% endif %}
+# permet si le client est dans le reseau local
+                               permit_mynetworks
+# rejette les recipients sans nom de domaine totalement qualifie
+                               reject_non_fqdn_recipient
+{% if postfix.public %}
+# permet si le client est authentifie
+                               permit_sasl_authenticated
+{% endif %}
+# rejette les destinations non locales
+                               reject_unauth_destination
+{% if postfix.public %}
+# accepte si on est sur un destinaire en @crans
+                               check_recipient_access hash:/etc/postfix/recipient_access
+# pour les @lists.crans.org, accepte si la greylist est d'accord
+                               check_policy_service inet:127.0.0.1:2501
+{% endif %}
+# jette le reste
+
+{% if postfix.primary %}
+#smtpd_end_of_data_restrictions=check_policy_service inet:127.0.0.1:10031
+{% endif %}
+# Tailles maximales : 20Mo pour les msgs et 75 pour les mbox
+message_size_limit = 20971520
+mailbox_size_limit = 78643000
+# Obligation de specifier le nom de domaine complet
+{% if postfix.secondary %}
+append_dot_mydomain = yes
+{% else %}
+append_dot_mydomain = no
+{% endif %}
+#Ajout de cyrus pour l'authentification SMTP
+smtpd_sasl_type = cyrus
+# Pieces jointes
+mime_header_checks = regexp:/etc/postfix/mime_header_checks
+# Transport slow
+slow_destination_recipient_limit = 20
+slow_destination_concurrency_limit = 2
+{% if postfix.dkim %}
+
+# Filtrage mail
+milter_protocol = 2
+milter_default_action = accept
+smtpd_milters = inet:localhost:12301
+non_smtpd_milters = inet:localhost:12301
+
+{% endif %}
+{% if postfix.titanic %}
+relayhost = [soyouz.adm.crans.org]:25
+{% endif %}
+{% if postfix.primary or postfix.secondary %}
+# PostScreen configuration
+# Access List
+postscreen_access_list = cidr:/etc/postfix/postscreen_access.cidr
+## Tu es blacklisté ? VTFF
+postscreen_blacklist_action = drop
+
+# Bannière d'accueil multi valuée
+postscreen_greet_banner = Bienvenue au crans, veuillez patienter quelques secondes.
+## On droppe.
+postscreen_greet_action = drop
+# RBL, le retour
+postscreen_dnsbl_sites =
+    zen.spamhaus.org*2
+    dnsbl.inps.de*2
+    b.barracudacentral.org*2
+    dnsbl-2.uceprotect.net*2
+    bl.spameatingmonkey.net
+    bl.spamcop.net
+    dnsbl.sorbs.net
+    psbl.surriel.com
+    bl.mailspike.net
+    swl.spamhaus.org*-2
+    list.dnswl.org=127.[0..255].[0..255].0*-1
+    list.dnswl.org=127.[0..255].[0..255].1*-2
+    list.dnswl.org=127.[0..255].[0..255].[2..255]*-3
+
+# Score >= 4 ? Bye bye
+postscreen_dnsbl_threshold = 4
+postscreen_dnsbl_action = enforce
+
+## Désactivé, pour éviter le fake greylisting de postscreen.
+## Décommenter en cas de spam trop important.
+## Filtre utilisé par postfix, mis en amont via postscreen
+#postscreen_non_smtp_command_enable = yes
+#postscreen_non_smtp_command_action = enforce
+#
+#postscreen_bare_newline_enable = yes
+#postscreen_bare_newline_action = enforce
+#
+#postscreen_pipelining_enable = yes
+#postscreen_pipelining_action = enforce
+{% endif %}
diff --git a/roles/postfix/templates/postfix/master.cf.j2 b/roles/postfix/templates/postfix/master.cf.j2
new file mode 100644
index 00000000..f979e4fa
--- /dev/null
+++ b/roles/postfix/templates/postfix/master.cf.j2
@@ -0,0 +1,143 @@
+# {{ ansible_managed }}
+# Fichier de configuration des démons de postfix.
+
+# +------------------------+
+# | Utils pour le template |
+# +------------------------+
+# Postfix master process configuration file.  Each line describes how
+# a mailer component program should be run. The fields that make up
+# each line are described below. A "-" field value requests that a
+# default value be used for that field.
+#
+# Service: any name that is valid for the specified transport type
+# (the next field).  With INET transports, a service is specified as
+# host:port.  The host part (and colon) may be omitted. Either host
+# or port may be given in symbolic form or in numeric form. Examples
+# for the SMTP server:  localhost:smtp receives mail via the loopback
+# interface only; 10025 receives mail on port 10025.
+#
+# Transport type: "inet" for Internet sockets, "unix" for UNIX-domain
+# sockets, "fifo" for named pipes.
+#
+# Private: whether or not access is restricted to the mail system.
+# Default is private service.  Internet (inet) sockets can't be private.
+#
+# Unprivileged: whether the service runs with root privileges or as
+# the owner of the Postfix system (the owner name is controlled by the
+# mail_owner configuration variable in the main.cf file).
+#
+# Chroot: whether or not the service runs chrooted to the mail queue
+# directory (pathname is controlled by the queue_directory configuration
+# variable in the main.cf file). Presently, all Postfix daemons can run
+# chrooted, except for the pipe, virtual and local delivery daemons.
+# The files in the examples/chroot-setup subdirectory describe how
+# to set up a Postfix chroot environment for your type of machine.
+#
+# Wakeup time: automatically wake up the named service after the
+# specified number of seconds. A ? at the end of the wakeup time
+# field requests that wake up events be sent only to services that
+# are actually being used.  Specify 0 for no wakeup. Presently, only
+# the pickup, queue manager and flush daemons need a wakeup timer.
+#
+# Max procs: the maximum number of processes that may execute this
+# service simultaneously. Default is to use a globally configurable
+# limit (the default_process_limit configuration parameter in main.cf).
+# Specify 0 for no process count limit.
+#
+# Command + args: the command to be executed. The command name is
+# relative to the Postfix program directory (pathname is controlled by
+# the program_directory configuration variable). Adding one or more
+# -v options turns on verbose logging for that service; adding a -D
+# option enables symbolic debugging (see the debugger_command variable
+# in the main.cf configuration file). See individual command man pages
+# for specific command-line options, if any.
+#
+# In order to use the "uucp" message tranport below, set up entries
+# in the transport table.
+#
+# In order to use the "cyrus" message transport below, configure it
+# in main.cf as the mailbox_transport.
+#
+# SPECIFY ONLY PROGRAMS THAT ARE WRITTEN TO RUN AS POSTFIX DAEMONS.
+# ALL DAEMONS SPECIFIED HERE MUST SPEAK A POSTFIX-INTERNAL PROTOCOL.
+#
+# DO NOT CHANGE THE ZERO PROCESS LIMIT FOR CLEANUP/BOUNCE/DEFER OR
+# POSTFIX WILL BECOME STUCK UP UNDER HEAVY LOAD
+#
+# DO NOT CHANGE THE ONE PROCESS LIMIT FOR PICKUP/QMGR OR POSTFIX WILL
+# DELIVER MAIL MULTIPLE TIMES.
+#
+# DO NOT SHARE THE POSTFIX QUEUE BETWEEN MULTIPLE POSTFIX INSTANCES.
+#
+# ==========================================================================
+# service type  private unpriv  chroot  wakeup  maxproc command + args
+#               (yes)   (yes)   (yes)   (never) (50)
+# ==========================================================================
+{% if postfix.primary or postfix.secondary %}
+smtp      inet  n       -       -       -       1       postscreen
+smtpd     pass  -       -       -       -       -       smtpd
+{% else %}
+smtp      inet  n       -       -       -       -       smtpd
+{% endif %}
+{% if postfix.primary or postfix.secondary %}
+dnsblog   unix  -       -       -       -       0       dnsblog
+{% endif %}
+{% if postfix.primary %}
+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
+{% endif %}
+#628      inet  n       -       -       -       -       qmqpd
+pickup    fifo  n       -       -       60      1       pickup
+cleanup   unix  n       -       -       -       0       cleanup
+qmgr      fifo  n       -       -       300     1       qmgr
+rewrite   unix  -       -       -       -       -       trivial-rewrite
+bounce    unix  -       -       -       -       0       bounce
+defer     unix  -       -       -       -       0       bounce
+trace     unix  -       -       -       -       0       bounce
+verify    unix  -       -       -       -       1       verify
+flush     unix  n       -       -       1000?   0       flush
+proxymap  unix  -       -       n       -       -       proxymap
+smtp      unix  -       -       -       -       -       smtp
+relay     unix  -       -       -       -       -       smtp
+{% if postfix.primary %}
+  -o fallback_relay=
+{% endif %}
+showq     unix n   -   -   -   -   showq
+error     unix -   -   -   -   -   error
+retry     unix  -       -       -       -       -       error
+discard   unix  -       -       -       -       -       discard
+local    unix  -   n   n   -   -   local
+virtual      unix  -   n   n   -   -   virtual
+lmtp     unix  -   -   n   -   5   lmtp
+anvil     unix  -       -       -       -       1       anvil
+scache   unix  -   -   -   -   1   scache
+slow      unix  -   -   n   -   1   smtp
+#
+# Interfaces to non-Postfix software. Be sure to examine the manual
+# pages of the non-Postfix software to find out what options it wants.
+# The Cyrus deliver program has changed incompatibly.
+#
+cyrus    unix  -   n   n   -   -   pipe
+  flags=R user=cyrus argv=/usr/sbin/cyrdeliver -e -m $${extension} $${user}
+uucp     unix  -   n   n   -   -   pipe
+  flags=Fqhu user=uucp argv=uux -r -n -z -a$$sender - $$nexthop!rmail ($$recipient)
+ifmail    unix  -       n       n       -       -       pipe
+  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $$nexthop ($$recipient)
+bsmtp     unix  -       n       n       -       -       pipe
+  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -d -t$$nexthop -f$$sender $$recipient
+scalemail-backend unix -   n   n   -   2   pipe
+  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store $${nexthop} $${user} $${extension}
+# only used by postfix-tls
+tlsmgr    unix  -       -       n       300     1       tlsmgr
+{% if postfix.mailman %}
+mailman   unix  -       n       n       -       -       pipe
+      flags=FR user=list
+      argv=/var/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
+{% endif %}
diff --git a/roles/postfix/templates/postfix/mime_header_checks.j2 b/roles/postfix/templates/postfix/mime_header_checks.j2
new file mode 100644
index 00000000..c5e47193
--- /dev/null
+++ b/roles/postfix/templates/postfix/mime_header_checks.j2
@@ -0,0 +1,8 @@
+# {{ ansible_managed }}
+# Filtrage des fichiers envoyes en piece jointe.
+
+# La version hard (s'il n'y a pas d'antivirus, ou pour le dernier virus a la mode)
+/^[	 ]*(Content-Type:.*)?(Content-Disposition:.*)?(filename|name)=\"?(.*)\.(exe|com|pif|bat|scr|vbs|chm|cpl)\"?[	 ]*$/ REJECT Content blocked : possible Virus are rejected. Please change filename extension of attachement "$4.$5" and resend mail.
+
+# La version soft :
+#/^[	 ]*(Content-Type:.*)?(Content-Disposition:.*)?(filename|name)=\"?(.*)\.(com|pif|bat|scr|vbs|chm)\"?[	 ]*$/ REJECT Content blocked : possible Virus are rejected. Please change filename extension of attachement "$4.$5" and resend mail.
diff --git a/roles/postfix/templates/postfix/postscreen_access.cidr.j2 b/roles/postfix/templates/postfix/postscreen_access.cidr.j2
new file mode 100644
index 00000000..65a8c8c3
--- /dev/null
+++ b/roles/postfix/templates/postfix/postscreen_access.cidr.j2
@@ -0,0 +1,61 @@
+# {{ ansible_managed }}
+
+127.0.0.1                                 permit
+138.231.0.0/16                            permit
+185.230.76.0/22                           permit
+10.231.136.0/24                           permit
+82.225.39.54                              permit
+91.121.179.40                             permit
+46.105.102.188                            permit
+2a0c:700:0:1::/64                         permit
+2a0c:700:0:2::/64                         permit
+2a0c:700:0:21::/64                        permit
+2a0c:700:0:22::/64                        permit
+2a0c:700:0:23::/64                        permit
+2a0c:700:0:24::/64                        permit
+
+# ecommercant qui repmplace offrespourlespros, qui spammait le le 29/05/2015
+149.202.29.192/28                         reject
+37.187.141.230                            reject
+2001:41d0:a:4ce6::/64                     reject
+# gboxyw.net (reverse wasnh.net) le 05/11/2015, devenu vorange.net, vous le sentez le spam qui vient ?
+37.187.132.105                            reject
+92.222.109.0/27                           reject
+
+# mail.alkar.net spam le 26/06/2016
+195.248.191.95                            reject
+
+# mail.testfast.eu spam en juin 2016
+176.20.27.0/24                            reject
+
+# Spam depuis des adresses en .ua
+91.194.84.10                              reject
+213.186.200.70                            reject
+185.117.89.15                             reject
+62.141.42.44                              reject
+# installio.co.ua
+217.79.181.5                              reject
+
+# Scam
+180.137.106.59                            reject
+169.255.7.5                               reject
+110.159.122.90                            reject
+37.104.198.10                             reject
+46.62.146.206                             reject
+
+# Spam alcoolisme 16/09/2018
+46.249.59.89                              reject
+
+# Spam "Pastoral shit"
+198.84.107.98                             reject
+198.84.74.66                              reject
+104.168.178.132                           reject
+104.168.178.156                           reject
+158.69.253.33                             reject
+
+# Spam overdue payment
+193.56.28.114                             reject
+
+# Non, nous ne voulons pas traiter l'alcoolisme à l'insu du patient.
+94.242.206.15                             reject
+91.188.222.33                             reject
diff --git a/roles/postfix/templates/postfix/recipient_access.j2 b/roles/postfix/templates/postfix/recipient_access.j2
new file mode 100644
index 00000000..90613c97
--- /dev/null
+++ b/roles/postfix/templates/postfix/recipient_access.j2
@@ -0,0 +1,4 @@
+crans@crans.fr REJECT Le Crans se fiche du basket. Veuillez supprimer l'adresse crans@crans.fr de votre carnet.
+crans.org OK
+crans.fr OK
+crans.eu OK
diff --git a/roles/postfix/templates/postfix/sasl/smtpd.conf.j2 b/roles/postfix/templates/postfix/sasl/smtpd.conf.j2
new file mode 100644
index 00000000..18d73088
--- /dev/null
+++ b/roles/postfix/templates/postfix/sasl/smtpd.conf.j2
@@ -0,0 +1,2 @@
+pwcheck_method: saslauthd
+mech_list: plain login
diff --git a/roles/postfix/templates/postfix/sender_login_maps.j2 b/roles/postfix/templates/postfix/sender_login_maps.j2
new file mode 100644
index 00000000..fa11fa88
--- /dev/null
+++ b/roles/postfix/templates/postfix/sender_login_maps.j2
@@ -0,0 +1,3 @@
+@crans.org root
+@crans.fr root
+@crans.eu root
diff --git a/roles/postfix/templates/postfix/transport.j2 b/roles/postfix/templates/postfix/transport.j2
new file mode 100644
index 00000000..2e44b92a
--- /dev/null
+++ b/roles/postfix/templates/postfix/transport.j2
@@ -0,0 +1,27 @@
+# {{ ansible_managed }}
+# Transport des mails
+
+{% if postfix.mailman %}
+# Les mailing-listes sont delivrees localement
+lists.crans.org              mailman:
+{% else %}
+lists.crans.org              smtp:[lists.adm.crans.org]
+{% endif %}
+{% if postfix.primary or postfix.secondary %}
+# C'est le serveur des adherents qui fait les livraisons des
+# adresses clubs et adherents
+crans.org                    smtp:[users.adm.crans.org]
+crans.ens-cachan.fr          smtp:[users.adm.crans.org]
+install-party.ens-cachan.fr  smtp:[users.adm.crans.org]
+clubs.ens-cachan.fr          smtp:[users.adm.crans.org]
+crans.eu                     smtp:[users.adm.crans.org]
+crans.fr                     smtp:[users.adm.crans.org]
+{% endif %}
+# SMTP relous
+wanadoo.com slow:
+wanadoo.fr slow:
+orange.com slow:
+orange.fr slow:
+ens-cachan.fr slow:
+free.fr slow:
+laposte.net slow:
diff --git a/roles/re2o-mail-server/tasks/main.yml b/roles/re2o-mail-server/tasks/main.yml
new file mode 100644
index 00000000..ee287e68
--- /dev/null
+++ b/roles/re2o-mail-server/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+- name: Create re2o-mail-server directory
+  file:
+    path: /var/local/re2o-services/mail-server
+    state: directory
+    mode: '2775'
+    owner: root
+    group: nounou
+
+- name: Set ACL for re2o-mail-server directory
+  acl:
+    path: /var/local/re2o-services/mail-server
+    default: yes
+    entity: nounou
+    etype: group
+    permissions: rwx
+    state: query
+
+- name: Clone re2o-mail-server repository
+  git:
+    repo: 'http://gitlab.adm.crans.org/nounous/re2o-mail-server.git'
+    dest: /var/local/re2o-services/mail-server
+    version: crans
+    umask: '002'
+
+- name: Create symbolic link to configuration
+  file:
+    src: /var/local/re2o-services/config.ini
+    dest: /var/local/re2o-services/mail-server/config.ini
+    owner: root
+    group: root
+    state: link
+
+- name: Deploy cron for re2o-mail-server
+  template:
+    src: cron.d/re2o-services-mail-server.j2
+    dest: /etc/cron.d/re2o-services-mail-server
+
+- name: Deploy local aliases
+  template:
+    src: re2o-services/mail-server/mail-aliases/{{ item }}.j2
+    dest: /var/local/re2o-services/mail-server/{{ item }}_local
+  loop:
+    - aliases
+    - virtuals
diff --git a/roles/re2o-mail-server/templates/cron.d/re2o-services-mail-server.j2 b/roles/re2o-mail-server/templates/cron.d/re2o-services-mail-server.j2
new file mode 100644
index 00000000..c804b50a
--- /dev/null
+++ b/roles/re2o-mail-server/templates/cron.d/re2o-services-mail-server.j2
@@ -0,0 +1,2 @@
+# {{ ansible_managed }}
+*/5 * * * * root /usr/bin/python3 /var/local/re2o-services/mail-server/main.py
diff --git a/roles/re2o-mail-server/templates/re2o-services/mail-server/mail-aliases b/roles/re2o-mail-server/templates/re2o-services/mail-server/mail-aliases
new file mode 160000
index 00000000..3d365dae
--- /dev/null
+++ b/roles/re2o-mail-server/templates/re2o-services/mail-server/mail-aliases
@@ -0,0 +1 @@
+Subproject commit 3d365dae2c8b3c0b2e02e8d4b134a7b6796bf99b