+++ /dev/null
-{ lib, pkgs, config, nodes, name, ... }:
-{
- config = lib.mkIf config.myServices.mailBackup.enable {
- security.acme.certs."mail" = config.myServices.certificates.certConfig // {
- postRun = ''
- systemctl restart postfix.service
- '';
- domain = config.hostEnv.fqdn;
- extraDomains = let
- zonesWithMx = builtins.filter (zone:
- lib.attrsets.hasAttr "withEmail" zone && lib.lists.length zone.withEmail > 0
- ) config.myEnv.dns.masterZones;
- mxs = map (zone: "${config.myEnv.servers."${name}".mx.subdomain}.${zone.name}") zonesWithMx;
- in builtins.listToAttrs (map (mx: lib.attrsets.nameValuePair mx null) mxs);
- };
- secrets.keys = {
- "postfix/mysql_alias_maps" = {
- user = config.services.postfix.user;
- group = config.services.postfix.group;
- permissions = "0440";
- text = ''
- # We need to specify that option to trigger ssl connection
- tls_ciphers = TLSv1.2
- user = ${config.myEnv.mail.postfix.mysql.user}
- password = ${config.myEnv.mail.postfix.mysql.password}
- hosts = ${config.myEnv.mail.postfix.mysql.remoteHost}
- dbname = ${config.myEnv.mail.postfix.mysql.database}
- query = SELECT DISTINCT 1
- FROM forwardings
- WHERE
- ((regex = 1 AND '%s' REGEXP CONCAT('^',source,'$') ) OR (regex = 0 AND source = '%s'))
- AND active = 1
- AND '%s' NOT IN
- (
- SELECT source
- FROM forwardings_blacklisted
- WHERE source = '%s'
- ) UNION
- SELECT 'devnull@immae.eu'
- FROM forwardings_blacklisted
- WHERE source = '%s'
- '';
- };
- "postfix/ldap_mailboxes" = {
- user = config.services.postfix.user;
- group = config.services.postfix.group;
- permissions = "0440";
- text = ''
- server_host = ldaps://${config.myEnv.mail.dovecot.ldap.host}:636
- search_base = ${config.myEnv.mail.dovecot.ldap.base}
- query_filter = ${config.myEnv.mail.dovecot.ldap.postfix_mailbox_filter}
- bind_dn = ${config.myEnv.mail.dovecot.ldap.dn}
- bind_pw = ${config.myEnv.mail.dovecot.ldap.password}
- result_attribute = immaePostfixAddress
- result_format = dummy
- version = 3
- '';
- };
- "postfix/sympa_mailbox_maps" = {
- user = config.services.postfix.user;
- group = config.services.postfix.group;
- permissions = "0440";
- text = ''
- hosts = ${config.myEnv.mail.sympa.postgresql.host}
- user = ${config.myEnv.mail.sympa.postgresql.user}
- password = ${config.myEnv.mail.sympa.postgresql.password}
- dbname = ${config.myEnv.mail.sympa.postgresql.database}
- query = SELECT DISTINCT 1 FROM list_table WHERE '%s' IN (
- CONCAT(name_list, '@', robot_list),
- CONCAT(name_list, '-request@', robot_list),
- CONCAT(name_list, '-editor@', robot_list),
- CONCAT(name_list, '-unsubscribe@', robot_list),
- CONCAT(name_list, '-owner@', robot_list),
- CONCAT('sympa-request@', robot_list),
- CONCAT('sympa-owner@', robot_list),
- CONCAT('sympa@', robot_list),
- CONCAT('listmaster@', robot_list),
- CONCAT('bounce@', robot_list),
- CONCAT('abuse-feedback-report@', robot_list)
- )
- '';
- };
- "postfix/ldap_ejabberd_users_immae_fr" = {
- user = config.services.postfix.user;
- group = config.services.postfix.group;
- permissions = "0440";
- text = ''
- server_host = ldaps://${config.myEnv.jabber.ldap.host}:636
- search_base = ${config.myEnv.jabber.ldap.base}
- query_filter = ${config.myEnv.jabber.postfix_user_filter}
- domain = immae.fr
- bind_dn = ${config.myEnv.jabber.ldap.dn}
- bind_pw = ${config.myEnv.jabber.ldap.password}
- result_attribute = immaeXmppUid
- result_format = ejabberd@localhost
- version = 3
- '';
- };
- };
-
- networking.firewall.allowedTCPPorts = [ 25 ];
-
- users.users."${config.services.postfix.user}".extraGroups = [ "keys" ];
- services.filesWatcher.postfix = {
- restart = true;
- paths = [
- config.secrets.fullPaths."postfix/mysql_alias_maps"
- config.secrets.fullPaths."postfix/sympa_mailbox_maps"
- config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"
- config.secrets.fullPaths."postfix/ldap_mailboxes"
- ];
- };
- services.postfix = {
- mapFiles = let
- recipient_maps = let
- name = n: i: "relay_${n}_${toString i}";
- pair = n: i: m: lib.attrsets.nameValuePair (name n i) (
- if m.type == "hash"
- then pkgs.writeText (name n i) m.content
- else null
- );
- pairs = n: v: lib.imap1 (i: m: pair n i m) v.recipient_maps;
- in lib.attrsets.filterAttrs (k: v: v != null) (
- lib.attrsets.listToAttrs (lib.flatten (
- lib.attrsets.mapAttrsToList pairs config.myEnv.mail.postfix.backup_domains
- ))
- );
- relay_restrictions = lib.attrsets.filterAttrs (k: v: v != null) (
- lib.attrsets.mapAttrs' (n: v:
- lib.attrsets.nameValuePair "recipient_access_${n}" (
- if lib.attrsets.hasAttr "relay_restrictions" v
- then pkgs.writeText "recipient_access_${n}" v.relay_restrictions
- else null
- )
- ) config.myEnv.mail.postfix.backup_domains
- );
- virtual_map = {
- virtual = let
- cfg = config.myEnv.monitoring.email_check.eldiron;
- address = "${cfg.mail_address}@${cfg.mail_domain}";
- in pkgs.writeText "postfix-virtual" (
- builtins.concatStringsSep "\n" (
- ["${address} 1"] ++
- lib.attrsets.mapAttrsToList (
- n: v: lib.optionalString v.external ''
- script_${n}@mail.immae.eu 1
- ''
- ) config.myEnv.mail.scripts
- )
- );
- };
- in
- recipient_maps // relay_restrictions // virtual_map;
- config = {
- ### postfix module overrides
- readme_directory = "${pkgs.postfix}/share/postfix/doc";
- smtp_tls_CAfile = lib.mkForce "";
- smtp_tls_cert_file = lib.mkForce "";
- smtp_tls_key_file = lib.mkForce "";
-
- message_size_limit = "1073741824"; # Don't put 0 here, it's not equivalent to "unlimited"
- mailbox_size_limit = "1073741825"; # Workaround, local delivered mails should all go through scripts
- alias_database = "\$alias_maps";
-
- ### Relay domains
- relay_domains = let
- backups = lib.flatten (lib.attrsets.mapAttrsToList (n: v: v.domains or []) config.myEnv.mail.postfix.backup_domains);
- virtual_domains = config.myEnv.mail.postfix.additional_mailbox_domains
- ++ lib.remove null (lib.flatten (map
- (zone: map
- (e: if e.receive
- then "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}"
- else null
- )
- (zone.withEmail or [])
- )
- config.myEnv.dns.masterZones
- ));
- in
- backups ++ virtual_domains;
- relay_recipient_maps = let
- backup_recipients = lib.flatten (lib.attrsets.mapAttrsToList (n: v:
- lib.imap1 (i: m: "${m.type}:/etc/postfix/relay_${n}_${toString i}") v.recipient_maps
- ) config.myEnv.mail.postfix.backup_domains);
- virtual_alias_maps = [
- "hash:/etc/postfix/virtual"
- "mysql:${config.secrets.fullPaths."postfix/mysql_alias_maps"}"
- "ldap:${config.secrets.fullPaths."postfix/ldap_ejabberd_users_immae_fr"}"
- ];
- virtual_mailbox_maps = [
- "ldap:${config.secrets.fullPaths."postfix/ldap_mailboxes"}"
- "pgsql:${config.secrets.fullPaths."postfix/sympa_mailbox_maps"}"
- ];
- in
- backup_recipients ++ virtual_alias_maps ++ virtual_mailbox_maps;
- smtpd_relay_restrictions = [
- "defer_unauth_destination"
- ] ++ lib.flatten (lib.attrsets.mapAttrsToList (n: v:
- if lib.attrsets.hasAttr "relay_restrictions" v
- then [ "check_recipient_access hash:/etc/postfix/recipient_access_${n}" ]
- else []
- ) config.myEnv.mail.postfix.backup_domains);
-
- ### Additional smtpd configuration
- smtpd_tls_received_header = "yes";
- smtpd_tls_loglevel = "1";
-
- ### Email sending configuration
- smtp_tls_security_level = "may";
- smtp_tls_loglevel = "1";
-
- ### Force ip bind for smtp
- smtp_bind_address = config.myEnv.servers."${name}".ips.main.ip4;
- smtp_bind_address6 = builtins.head config.myEnv.servers."${name}".ips.main.ip6;
-
- smtpd_milters = [
- "unix:${config.myServices.mail.milters.sockets.opendkim}"
- "unix:${config.myServices.mail.milters.sockets.openarc}"
- "unix:${config.myServices.mail.milters.sockets.opendmarc}"
- ];
- };
- enable = true;
- enableSmtp = true;
- enableSubmission = false;
- destination = ["localhost"];
- # This needs to reverse DNS
- hostname = config.hostEnv.fqdn;
- setSendmail = false;
- sslCert = "/var/lib/acme/mail/fullchain.pem";
- sslKey = "/var/lib/acme/mail/key.pem";
- recipientDelimiter = "+";
- };
- };
-}
-