mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 19:46:05 +01:00
accounts.email: add option to disable an account
Allow a user to disable an email account by setting `accounts.email.accounts.<name>.enable = false`. This is useful if someone wants to configure email accounts globally but only use them in certain circumstances. Everywhere email account configuration is used, check if the account is enabled before checking any attributes of the account.
This commit is contained in:
parent
07b994baed
commit
dbfcd3292d
22 changed files with 164 additions and 26 deletions
|
|
@ -9,6 +9,7 @@ let
|
|||
;
|
||||
|
||||
cfg = config.accounts.email;
|
||||
enabledAccounts = lib.filterAttrs (n: v: v.enable) cfg.accounts;
|
||||
|
||||
gpgModule = types.submodule {
|
||||
options = {
|
||||
|
|
@ -353,6 +354,16 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether this account is enabled. Potentially useful to allow
|
||||
setting email configuration globally then enabling or disabling on
|
||||
specific systems.
|
||||
'';
|
||||
};
|
||||
|
||||
flavor = mkOption {
|
||||
type = types.enum [
|
||||
"davmail"
|
||||
|
|
@ -669,11 +680,11 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.accounts != { }) {
|
||||
config = mkIf (enabledAccounts != { }) {
|
||||
assertions = [
|
||||
(
|
||||
let
|
||||
primaries = lib.catAttrs "name" (lib.filter (a: a.primary) (lib.attrValues cfg.accounts));
|
||||
primaries = lib.catAttrs "name" (lib.filter (a: a.primary) (lib.attrValues enabledAccounts));
|
||||
in
|
||||
{
|
||||
assertion = lib.length primaries == 1;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
time = "2024-12-08T17:22:13+00:00";
|
||||
condition =
|
||||
let
|
||||
usingMbsync = lib.any (a: a.mbsync.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
usingMbsync = lib.any (a: a.enable && a.mbsync.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
in
|
||||
usingMbsync;
|
||||
message = ''
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ let
|
|||
;
|
||||
};
|
||||
|
||||
aerc-accounts = attrsets.filterAttrs (_: v: v.aerc.enable) config.accounts.email.accounts;
|
||||
aerc-accounts = attrsets.filterAttrs (
|
||||
_: v: v.enable && v.aerc.enable
|
||||
) config.accounts.email.accounts;
|
||||
|
||||
configDir =
|
||||
if (pkgs.stdenv.isDarwin && !config.xdg.enable) then
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ let
|
|||
|
||||
cfg = config.programs.alot;
|
||||
|
||||
enabledAccounts = lib.filter (a: a.notmuch.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
enabledAccounts = lib.filter (a: a.enable && a.notmuch.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
# sorted: primary first
|
||||
alotAccounts = lib.sort (a: b: !(a.primary -> b.primary)) enabledAccounts;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ let
|
|||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
|
||||
astroidAccounts = lib.filterAttrs (n: v: v.astroid.enable) config.accounts.email.accounts;
|
||||
astroidAccounts = lib.filterAttrs (
|
||||
n: v: v.enable && v.astroid.enable
|
||||
) config.accounts.email.accounts;
|
||||
|
||||
boolOpt = b: if b then "true" else "false";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
...
|
||||
}:
|
||||
let
|
||||
accounts = lib.filter (a: a.getmail.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
accounts = lib.filter (a: a.enable && a.getmail.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
renderAccountConfig =
|
||||
account:
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ in
|
|||
{
|
||||
programs.git.iniContent =
|
||||
let
|
||||
hasSmtp = name: account: account.smtp != null;
|
||||
hasSmtp = name: account: account.enable && account.smtp != null;
|
||||
|
||||
genIdentity =
|
||||
name: account:
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ let
|
|||
mkAccountConfig =
|
||||
_: account:
|
||||
let
|
||||
notmuchEnabled = account.notmuch.enable;
|
||||
notmuchEnabled = account.enable && account.notmuch.enable;
|
||||
imapEnabled = !isNull account.imap && !notmuchEnabled;
|
||||
maildirEnabled = !isNull account.maildir && !imapEnabled && !notmuchEnabled;
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ in
|
|||
configFile."himalaya/config.toml".source =
|
||||
let
|
||||
enabledAccounts = lib.filterAttrs (
|
||||
_: account: account.himalaya.enable
|
||||
_: account: account.enable && account.himalaya.enable
|
||||
) config.accounts.email.accounts;
|
||||
accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts;
|
||||
globalConfig = compactAttrs himalaya.settings;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ let
|
|||
|
||||
cfg = config.programs.lieer;
|
||||
|
||||
lieerAccounts = lib.filter (a: a.lieer.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
lieerAccounts = lib.filter (a: a.enable && a.lieer.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
nonGmailAccounts = map (a: a.name) (lib.filter (a: a.flavor != "gmail.com") lieerAccounts);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ let
|
|||
cfg = config.programs.mbsync;
|
||||
|
||||
# Accounts for which mbsync is enabled.
|
||||
mbsyncAccounts = lib.filter (a: a.mbsync.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
mbsyncAccounts = lib.filter (a: a.enable && a.mbsync.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
# Given a SINGLE group's channels attribute set, return true if ANY of the channel's
|
||||
# patterns use the invalidOption attribute set value name.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ let
|
|||
tomlFormat = pkgs.formats.toml { };
|
||||
|
||||
enabledAccounts = lib.attrsets.filterAttrs (
|
||||
name: value: value.meli.enable or false
|
||||
name: value: value.enable && (value.meli.enable or false)
|
||||
) config.accounts.email.accounts;
|
||||
|
||||
meliAccounts = (lib.attrsets.mapAttrs (name: value: (mkMeliAccounts name value)) enabledAccounts);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ let
|
|||
|
||||
cfg = config.programs.msmtp;
|
||||
|
||||
msmtpAccounts = lib.filter (a: a.msmtp.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
msmtpAccounts = lib.filter (a: a.enable && a.msmtp.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
onOff = p: if p then "on" else "off";
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ let
|
|||
sortedAddresses =
|
||||
let
|
||||
# Set of email account sets where mu.enable = true.
|
||||
muAccounts = lib.filter (a: a.mu.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
muAccounts = lib.filter (a: a.enable && a.mu.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
addrs = map (a: a.address) muAccounts;
|
||||
# Construct list of lists containing email aliases, and flatten
|
||||
aliases = map (alias: alias.address or alias) (lib.flatten (map (a: a.aliases) muAccounts));
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ let
|
|||
|
||||
cfg = config.programs.mujmap;
|
||||
|
||||
mujmapAccounts = lib.filter (a: a.mujmap.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
mujmapAccounts = lib.filter (a: a.enable && a.mujmap.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
missingNotmuchAccounts = map (a: a.name) (
|
||||
lib.filter (a: !a.notmuch.enable && a.mujmap.notmuchSetupWarning) mujmapAccounts
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@ let
|
|||
|
||||
cfg = config.programs.neomutt;
|
||||
|
||||
neomuttAccountsCfg = filterAttrs (n: a: a.neomutt.enable) config.accounts.email.accounts;
|
||||
neomuttAccountsCfg = filterAttrs (
|
||||
n: a: a.enable && a.neomutt.enable
|
||||
) config.accounts.email.accounts;
|
||||
neomuttAccounts = attrValues neomuttAccountsCfg;
|
||||
|
||||
accountCommandNeeded = lib.any (
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ let
|
|||
|
||||
user =
|
||||
let
|
||||
accounts = filter (a: a.notmuch.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
accounts = filter (a: a.enable && a.notmuch.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
primary = filter (a: a.primary) accounts;
|
||||
secondaries = filter (a: !a.primary) accounts;
|
||||
in
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@ let
|
|||
|
||||
cfg = config.programs.offlineimap;
|
||||
|
||||
accounts = lib.filter (a: a.offlineimap.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
accounts = lib.filter (a: a.enable && a.offlineimap.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
toIni = lib.generators.toINI {
|
||||
mkKeyValue =
|
||||
|
|
|
|||
|
|
@ -32,16 +32,21 @@ let
|
|||
|
||||
moduleName = "programs.thunderbird";
|
||||
|
||||
filterEnabled = accounts: attrValues (lib.filterAttrs (_: a: a.thunderbird.enable) accounts);
|
||||
addId = map (a: a // { id = builtins.hashString "sha256" a.name; });
|
||||
|
||||
enabledEmailAccounts = filterEnabled config.accounts.email.accounts;
|
||||
enabledEmailAccounts = filter (a: a.enable && a.thunderbird.enable) (
|
||||
attrValues config.accounts.email.accounts
|
||||
);
|
||||
enabledEmailAccountsWithId = addId enabledEmailAccounts;
|
||||
|
||||
enabledCalendarAccounts = filterEnabled config.accounts.calendar.accounts;
|
||||
enabledCalendarAccounts = filter (a: a.thunderbird.enable) (
|
||||
attrValues config.accounts.calendar.accounts
|
||||
);
|
||||
enabledCalendarAccountsWithId = addId enabledCalendarAccounts;
|
||||
|
||||
enabledContactAccounts = filterEnabled config.accounts.contact.accounts;
|
||||
enabledContactAccounts = filter (a: a.thunderbird.enable) (
|
||||
attrValues config.accounts.contact.accounts
|
||||
);
|
||||
enabledContactAccountsWithId = addId enabledContactAccounts;
|
||||
|
||||
thunderbirdConfigPath = if isDarwin then "Library/Thunderbird" else ".thunderbird";
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ let
|
|||
|
||||
cfg = config.services.getmail;
|
||||
|
||||
accounts = lib.filter (a: a.getmail.enable) (lib.attrValues config.accounts.email.accounts);
|
||||
accounts = lib.filter (a: a.enable && a.getmail.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
# Note: The getmail service does not expect a path, but just the filename!
|
||||
renderConfigFilepath = a: if a.primary then "getmailrc" else "getmail${a.name}";
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ let
|
|||
|
||||
configName = account: "imapnotify-${safeName account.name}-config.json";
|
||||
|
||||
imapnotifyAccounts = lib.filter (a: a.imapnotify.enable) (
|
||||
imapnotifyAccounts = lib.filter (a: a.enable && a.imapnotify.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
let
|
||||
cfg = config.services.lieer;
|
||||
|
||||
syncAccounts = lib.filter (a: a.lieer.enable && a.lieer.sync.enable) (
|
||||
syncAccounts = lib.filter (a: a.enable && a.lieer.enable && a.lieer.sync.enable) (
|
||||
lib.attrValues config.accounts.email.accounts
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{ lib, options, ... }:
|
||||
{
|
||||
accounts.email = {
|
||||
maildirBasePath = "Mail";
|
||||
|
|
@ -22,6 +23,101 @@
|
|||
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; }
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue