From c90e09d125209db4e99b4acef7654cf010939640 Mon Sep 17 00:00:00 2001 From: Thomas Preisner Date: Sat, 28 Dec 2024 00:40:32 +0100 Subject: [PATCH] Add configuration option to alias entire domains and respective tests --- mailsystem/default.nix | 16 ++++++++++++++++ mailsystem/postfix.nix | 20 +++++++++++++++++++- tests/aliases.nix | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/mailsystem/default.nix b/mailsystem/default.nix index 1ac270e..af2913c 100644 --- a/mailsystem/default.nix +++ b/mailsystem/default.nix @@ -127,6 +127,22 @@ in { default = {}; }; + virtualDomainAliases = lib.mkOption { + type = with lib.types; attrsOf str; + example = { + "@aliasdomain.com" = "@domain.com"; + }; + description = '' + Virtual aliasing of domains. A virtual alias `"@aliasdomain.com" = "@domain.com"` + means that all mail directed at `aliasdomain.com` are forwarded to `domain.com`. + This also entails, that any account or alias of `domain.com` is partially valid + for `aliasdomain.com`. For example, `user@domain.com` can receive mails at + `user@aliasdomain.com`. However, if `user@domain.com` shall be able to dispatch + mails using `user@aliasdomain.com`, an explicit alias needs to be configured. + ''; + default = {}; + }; + extraVirtualAliases = lib.mkOption { type = let account = lib.mkOptionType { diff --git a/mailsystem/postfix.nix b/mailsystem/postfix.nix index f0afb8d..3328aca 100644 --- a/mailsystem/postfix.nix +++ b/mailsystem/postfix.nix @@ -28,9 +28,18 @@ with (import ./common.nix {inherit config;}); let map (from: {"${from}" = to;}) (value.aliases ++ lib.singleton name)) cfg.accounts)); + virtual_domain_aliases = let + alias_domains = + lib.concatMapAttrs (src: dst: { + "@${src}" = "@${dst}"; + }) + cfg.virtualDomainAliases; + in + attrsToLookupTable alias_domains; + extra_virtual_aliases = attrsToLookupTable cfg.extraVirtualAliases; - all_virtual_aliases = mergeLookupTables [account_virtual_aliases extra_virtual_aliases]; + all_virtual_aliases = mergeLookupTables [account_virtual_aliases virtual_domain_aliases extra_virtual_aliases]; aliases_file = let content = lookupTableToString all_virtual_aliases; @@ -65,6 +74,15 @@ with (import ./common.nix {inherit config;}); let tls_exclude_ciphers = "MD5, DES, ADH, RC4, PSD, SRP, 3DES, eNULL, aNULL"; in { config = lib.mkIf cfg.enable { + assertions = + lib.mapAttrsToList ( + src: dst: { + assertion = (builtins.elem src cfg.domains) && (builtins.elem dst cfg.domains); + message = "Both aliased domain (${src}) and actual domain (${dst}) need to be managed by the mailserver."; + } + ) + cfg.virtualDomainAliases; + services.postfix = { enable = true; hostname = "${cfg.reverseFqdn}"; diff --git a/tests/aliases.nix b/tests/aliases.nix index e35124a..cd3aae3 100644 --- a/tests/aliases.nix +++ b/tests/aliases.nix @@ -48,8 +48,11 @@ in environment.systemPackages = with pkgs; [netcat]; mailsystem = { fqdn = "mail.example.com"; - domains = ["example.com" "otherdomain.com"]; + domains = ["example.com" "aliased.com" "otherdomain.com"]; accounts = mkAccounts accounts; + virtualDomainAliases = { + "aliased.com" = "example.com"; + }; extraVirtualAliases = { "extra-alias@example.com" = accounts."extra-alias".address; }; @@ -191,5 +194,37 @@ in client.execute("${cleanupMail}") # fetchmail returns EXIT_CODE 0 when it retrieves mail client.succeed("${recvMail "extra-alias"} >&2") + + with subtest("receiving mail on aliased domain using normal account"): + client.succeed("${sendMail "normal" "" "user2@aliased.com" '' + Subject: aliasedDomain with normal account + + Hello User2, + this is mail is sent to you by using your address @example.org. + ''}") + server.wait_until_fails('${pendingPostqueue}') + client.execute("${cleanupMail}") + # fetchmail returns EXIT_CODE 0 when it retrieves mail + client.succeed("${recvMail "normal2"} >&2") + + with subtest("receiving mail on aliased domain using catchall-account"): + client.succeed("${sendMail "normal" "" "somerandomaddress@aliased.com" '' + Subject: aliasedDomain using catchall-account + + Hello Catchall-User, + this is mail is sent to you by using an address without any user-account behind it for neither @example.com nor @aliased.com. + ''}") + server.wait_until_fails('${pendingPostqueue}') + client.execute("${cleanupMail}") + # fetchmail returns EXIT_CODE 0 when it retrieves mail + client.succeed("${recvMail "catchall"} >&2") + + with subtest("sending mail from aliased domain fails"): + client.fail("${sendMail "normal" "user1@aliased.com" accounts."normal2".address '' + Subject: aliasedDomain + + Hello User2, + this mail should not be dispatched to you as I'm using "my" address @aliased.com. + ''}") ''; }