1 { lib, pkgs, config, nodes, name, ... }:
3 config = lib.mkIf config.myServices.mailBackup.enable {
4 security.acme.certs."mail" = config.myServices.certificates.certConfig // {
6 systemctl restart postfix.service
8 domain = config.hostEnv.fqdn;
10 zonesWithMx = builtins.filter (zone:
11 lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0
12 ) config.myEnv.dns.masterZones;
13 mxs = map (zone: "${config.myEnv.servers."${name}".mx.subdomain}.${zone.name}") zonesWithMx;
14 in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs);
18 dest = "postfix/mysql_alias_maps";
19 user = config.services.postfix.user;
20 group = config.services.postfix.group;
23 # We need to specify that option to trigger ssl connection
25 user = ${config.myEnv.mail.postfix.mysql.user}
26 password = ${config.myEnv.mail.postfix.mysql.password}
27 hosts = ${config.myEnv.mail.postfix.mysql.remoteHost}
28 dbname = ${config.myEnv.mail.postfix.mysql.database}
29 query = SELECT DISTINCT 1
32 ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s'))
37 FROM forwardings_blacklisted
40 SELECT 'devnull@immae.eu'
41 FROM forwardings_blacklisted
46 dest = "postfix/ldap_mailboxes";
47 user = config.services.postfix.user;
48 group = config.services.postfix.group;
51 server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636
52 search_base = ${config.myEnv.mail.dovecot.ldap.base}
53 query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter}
54 bind_dn = ${config.myEnv.mail.dovecot.ldap.dn}
55 bind_pw = ${config.myEnv.mail.dovecot.ldap.password}
56 result_attribute = immaePostfixAddress
62 dest = "postfix/sympa_mailbox_maps";
63 user = config.services.postfix.user;
64 group = config.services.postfix.group;
67 hosts = ${config.myEnv.mail.sympa.postgresql.host}
68 user = ${config.myEnv.mail.sympa.postgresql.user}
69 password = ${config.myEnv.mail.sympa.postgresql.password}
70 dbname = ${config.myEnv.mail.sympa.postgresql.database}
71 query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN (
72 CONCAT(name_list, '@', robot_list),
73 CONCAT(name_list, '-request@', robot_list),
74 CONCAT(name_list, '-editor@', robot_list),
75 CONCAT(name_list, '-unsubscribe@', robot_list),
76 CONCAT(name_list, '-owner@', robot_list),
77 CONCAT('sympa-request@', robot_list),
78 CONCAT('sympa-owner@', robot_list),
79 CONCAT('sympa@', robot_list),
80 CONCAT('listmaster@', robot_list),
81 CONCAT('bounce@', robot_list),
82 CONCAT('abuse-feedback-report@', robot_list)
87 dest = "postfix/ldap_ejabberd_users_immae_fr";
88 user = config.services.postfix.user;
89 group = config.services.postfix.group;
92 server_host = ldaps://${config.myEnv.jabber.ldap.host}:636
93 search_base = ${config.myEnv.jabber.ldap.base}
94 query_filter = ${config.myEnv.jabber.postfix_user_filter}
96 bind_dn = ${config.myEnv.jabber.ldap.dn}
97 bind_pw = ${config.myEnv.jabber.ldap.password}
98 result_attribute = immaeXmppUid
99 result_format = ejabberd@localhost
105 networking.firewall.allowedTCPPorts = [ 25 ];
107 users.users."${config.services.postfix.user}".extraGroups = [ "keys" ];
108 services.filesWatcher.postfix = {
111 config.secrets.fullPaths."postfix/mysql_alias_maps"
112 config.secrets.fullPaths."postfix/sympa_mailbox_maps"
113 config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"
114 config.secrets.fullPaths."postfix/ldap_mailboxes"
120 name = n: i: "relay_${n}_${toString i}";
121 pair = n: i: m: lib.attrsets.nameValuePair (name n i) (
123 then pkgs.writeText (name n i) m.content
126 pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps;
127 in lib.attrsets.filterAttrs (k: v: v != null) (
128 lib.attrsets.listToAttrs (lib.flatten (
129 lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains
132 relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) (
133 lib.attrsets.mapAttrs' (n: v:
134 lib.attrsets.nameValuePair "recipient_access_${n}" (
135 if lib.attrsets.hasAttr "relay_restrictions" v
136 then pkgs.writeText "recipient_access_${n}" v.relay_restrictions
139 ) config.myEnv.mail.postfix.backup_domains
143 cfg = config.myEnv.monitoring.email_check.eldiron;
144 address = "${cfg.mail_address}@${cfg.mail_domain}";
145 in pkgs.writeText "postfix-virtual" (
146 builtins.concatStringsSep "\n" (
148 lib.attrsets.mapAttrsToList (
149 n: v: lib.optionalString v.external ''
150 script_${n}@mail.immae.eu 1
152 ) config.myEnv.mail.scripts
157 recipient_maps // relay_restrictions // virtual_map;
159 ### postfix module overrides
160 readme_directory = "${pkgs.postfix}/share/postfix/doc";
161 smtp_tls_CAfile = lib.mkForce "";
162 smtp_tls_cert_file = lib.mkForce "";
163 smtp_tls_key_file = lib.mkForce "";
165 message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited"
166 mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts
167 alias_database = "\$alias_maps";
171 backups = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains);
172 virtual_domains = config.myEnv.mail.postfix.additional_mailbox_domains
173 ++ lib.remove null (lib.flatten (map
176 then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}"
179 (zone.withEmail or [])
181 config.myEnv.dns.masterZones
184 backups ++ virtual_domains;
185 relay_recipient_maps = let
186 backup_recipients = lib.flatten (lib.attrsets.mapAttrsToList (n: v:
187 lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps
188 ) config.myEnv.mail.postfix.backup_domains);
189 virtual_alias_maps = [
190 "hash:/etc/postfix/virtual"
191 "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}"
192 "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}"
194 virtual_mailbox_maps = [
195 "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}"
196 "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}"
199 backup_recipients ++ virtual_alias_maps ++ virtual_mailbox_maps;
200 smtpd_relay_restrictions = [
201 "defer_unauth_destination"
202 ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v:
203 if lib.attrsets.hasAttr "relay_restrictions" v
204 then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ]
206 ) config.myEnv.mail.postfix.backup_domains);
208 ### Additional smtpd configuration
209 smtpd_tls_received_header = "yes";
210 smtpd_tls_loglevel = "1";
212 ### Email sending configuration
213 smtp_tls_security_level = "may";
214 smtp_tls_loglevel = "1";
216 ### Force ip bind for smtp
217 smtp_bind_address = config.myEnv.servers."${name}".ips.main.ip4;
218 smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6;
221 "unix:${config.myServices.mail.milters.sockets.opendkim}"
222 "unix:${config.myServices.mail.milters.sockets.openarc}"
223 "unix:${config.myServices.mail.milters.sockets.opendmarc}"
228 enableSubmission = false;
229 destination = ["localhost"];
230 # This needs to reverse DNS
231 hostname = config.hostEnv.fqdn;
233 sslCert = "/var/lib/acme/mail/fullchain.pem";
234 sslKey = "/var/lib/acme/mail/key.pem";
235 recipientDelimiter = "+";