Files
home-manager/tests/modules/accounts/email-test-accounts.nix
2026-04-13 22:02:40 -05:00

124 lines
4.3 KiB
Nix

{ lib, options, ... }:
{
accounts.email = {
maildirBasePath = "Mail";
accounts = {
"hm@example.com" = {
primary = true;
address = "hm@example.com";
userName = "home.manager";
realName = "H. M. Test";
passwordCommand = "password-command";
imap.host = "imap.example.com";
smtp.host = "smtp.example.com";
};
hm-account = {
address = "hm@example.org";
userName = "home.manager.jr";
realName = "H. M. Test Jr.";
passwordCommand = "password-command 2";
imap.host = "imap.example.org";
smtp.host = "smtp.example.org";
smtp.tls.useStartTls = true;
};
# Account that throws an error if any interesting account attribute is
# accessed other than the `enable` attribute. This is a bit awkward as
# we can't throw just for accessing some submodules, as some get accessed
# just as part of merging config, but it ensures a disabled account is
# genuinely disabled.
disabled-account =
let
# This is intended for use in generating documentation, but it's
# useful here as a way to get a list of attributes that might be
# defined.
accountAttrOptions = options.accounts.email.accounts.type.nestedTypes.elemType.getSubOptions [ ];
throwOnAttrAccess =
baseName: builtins.mapAttrs (n: _v: throw "Unexpected access of ${baseName}.${n}");
# Don't want to do anything with these account attributes.
ignoredAttrNames = [
"_module"
"enable"
];
# These are submodules, which means the config attribute will be
# accessed even if subattributes aren't. This means we can't throw
# an error as soon as one of these is accessed, and instead need to
# throw errors if an attribute of this submodule is accessed.
submoduleAttrNames = [
"aerc"
"alot"
"astroid"
"getmail"
"himalaya"
"imapnotify"
"lieer"
"mbsync"
"meli"
"msmtp"
"mu"
"mujmap"
"neomutt"
"notmuch"
"offlineimap"
"thunderbird"
];
# Other attributes should never be accessed if the account is
# disabled, so throw an error if they are.
baseAttrThrows = throwOnAttrAccess "accounts.email.accounts.disabled-account" (
removeAttrs accountAttrOptions (ignoredAttrNames ++ submoduleAttrNames)
);
submoduleToAttrThrows =
name:
let
submoduleAttrOptions = builtins.getAttr name accountAttrOptions;
# Some submodules have sub-submodules, and they need the same
# special handling.
#
# Ideally this would be some recursive function to avoid
# repeating the code, potentially using introspection to workout
# which options are submodules, but that's complicated and
# unnecessary for now.
subSubmoduleAttrNames =
if name == "lieer" then
[ "sync" ]
else if name == "mbsync" then
[ "extraConfig" ]
else if name == "msmtp" then
[ "tls" ]
else if name == "notmuch" then
[ "neomutt" ]
else if name == "offlineimap" then
[ "extraConfig" ]
else
[ ];
subSubmoduleThrows = lib.genAttrs subSubmoduleAttrNames (
n:
throwOnAttrAccess "accounts.email.accounts.disabled-account.${name}.${n}" (
builtins.getAttr n submoduleAttrOptions
)
);
baseThrows = throwOnAttrAccess "accounts.email.accounts.disabled-account.${name}" (
removeAttrs submoduleAttrOptions subSubmoduleAttrNames
);
in
baseThrows // subSubmoduleThrows;
submoduleAttrThrows = lib.genAttrs submoduleAttrNames submoduleToAttrThrows;
in
lib.mergeAttrsList [
baseAttrThrows
submoduleAttrThrows
{ enable = false; }
];
};
};
}