home-manager/modules/programs/aerc-accounts.nix

234 lines
7 KiB
Nix
Raw Normal View History

{ config, lib, pkgs, confSections, confSection, ... }:
with lib;
let
mapAttrNames = f: attr:
listToAttrs (attrValues (mapAttrs (k: v: {
name = f k;
value = v;
}) attr));
2023-02-28 20:16:41 +00:00
addAccountName = name: k: "${k}:account=${name}";
2023-02-28 20:16:41 +00:00
oauth2Params = mkOption {
type = with types;
nullOr (submodule {
options = {
token_endpoint = mkOption {
type = nullOr str;
default = null;
description = "The OAuth2 token endpoint.";
2023-02-28 20:16:41 +00:00
};
client_id = mkOption {
type = nullOr str;
default = null;
description = "The OAuth2 client identifier.";
2023-02-28 20:16:41 +00:00
};
client_secret = mkOption {
type = nullOr str;
default = null;
description = "The OAuth2 client secret.";
2023-02-28 20:16:41 +00:00
};
scope = mkOption {
type = nullOr str;
default = null;
description = "The OAuth2 requested scope.";
2023-02-28 20:16:41 +00:00
};
};
});
default = null;
example = { token_endpoint = "<token_endpoint>"; };
description = ''
2023-02-28 20:16:41 +00:00
Sets the oauth2 params if authentication mechanism oauthbearer or
xoauth2 is used.
See {manpage}`aerc-imap(5)`.
2023-02-28 20:16:41 +00:00
'';
};
in {
type = mkOption {
type = types.attrsOf (types.submodule {
options.aerc = {
enable = mkEnableOption "aerc";
extraAccounts = mkOption {
type = confSection;
default = { };
example =
literalExpression ''{ source = "maildir://~/Maildir/example"; }'';
description = ''
aerc: add assertion to limit per-account extraConfig to UI config (#4196) * aerc: fix per-account extraConfig section names The aerc configuration file `aerc.conf` can contain 10 different sections, but only the UI section supports what the aerc manual calls contextual configuration. This works by appending to the section heading either `:account=name` or `:folder=bar`. The aerc-accounts module, however, applied `mkAccountConfig` to each section heading declared in `config.accounts.email.accounts.<name>.aerc.extraConfig.*`. This means home-manager will generate files with `[general:account=default]` and the options will not be recognized by aerc. To address this, and since it doesn't make sense for other sections to only be under a single account's scope, an assertion has been added to confirm that only sectons that support contextual config (i.e., only the UI section) is declared. This also addresses confusions like declaring `accounts.email.accounts.*.aerc.extraConfig.general.unsafe-accounts-conf = true` and triggering a warning message because `programs.aerc.extraConfig.general.unsafe-accounts-conf` was unset. This commit also updated documentation throughout the aerc modules to be in line with this change, and fixed minor typos/formatting therein. Co-authored-by: Genevieve <genevieve@sunlashed.garden> * aerc: make assertion plaintext and add test case This commit adds a test case to check both the warning on unset `unsafe-accounts-conf = true` when aerc accounts are configured with Nix, and the new assertion when per-account configuration contains unsupported subsections (i.e. general). It also fixes minor formatting issues and typos.
2023-07-14 18:34:28 +00:00
Extra config added to the configuration section for this account in
{file}`$HOME/.config/aerc/accounts.conf`.
See {manpage}`aerc-accounts(5)`.
'';
};
extraBinds = mkOption {
type = confSections;
default = { };
example = literalExpression
''{ messages = { d = ":move ''${folder.trash}<Enter>"; }; }'';
description = ''
Extra bindings specific to this account, added to
{file}`$HOME/.config/aerc/binds.conf`.
See {manpage}`aerc-binds(5)`.
'';
};
extraConfig = mkOption {
type = confSections;
default = { };
aerc: add assertion to limit per-account extraConfig to UI config (#4196) * aerc: fix per-account extraConfig section names The aerc configuration file `aerc.conf` can contain 10 different sections, but only the UI section supports what the aerc manual calls contextual configuration. This works by appending to the section heading either `:account=name` or `:folder=bar`. The aerc-accounts module, however, applied `mkAccountConfig` to each section heading declared in `config.accounts.email.accounts.<name>.aerc.extraConfig.*`. This means home-manager will generate files with `[general:account=default]` and the options will not be recognized by aerc. To address this, and since it doesn't make sense for other sections to only be under a single account's scope, an assertion has been added to confirm that only sectons that support contextual config (i.e., only the UI section) is declared. This also addresses confusions like declaring `accounts.email.accounts.*.aerc.extraConfig.general.unsafe-accounts-conf = true` and triggering a warning message because `programs.aerc.extraConfig.general.unsafe-accounts-conf` was unset. This commit also updated documentation throughout the aerc modules to be in line with this change, and fixed minor typos/formatting therein. Co-authored-by: Genevieve <genevieve@sunlashed.garden> * aerc: make assertion plaintext and add test case This commit adds a test case to check both the warning on unset `unsafe-accounts-conf = true` when aerc accounts are configured with Nix, and the new assertion when per-account configuration contains unsupported subsections (i.e. general). It also fixes minor formatting issues and typos.
2023-07-14 18:34:28 +00:00
example = literalExpression "{ ui = { sidebar-width = 25; }; }";
description = ''
Config specific to this account, added to {file}`$HOME/.config/aerc/aerc.conf`.
aerc: add assertion to limit per-account extraConfig to UI config (#4196) * aerc: fix per-account extraConfig section names The aerc configuration file `aerc.conf` can contain 10 different sections, but only the UI section supports what the aerc manual calls contextual configuration. This works by appending to the section heading either `:account=name` or `:folder=bar`. The aerc-accounts module, however, applied `mkAccountConfig` to each section heading declared in `config.accounts.email.accounts.<name>.aerc.extraConfig.*`. This means home-manager will generate files with `[general:account=default]` and the options will not be recognized by aerc. To address this, and since it doesn't make sense for other sections to only be under a single account's scope, an assertion has been added to confirm that only sectons that support contextual config (i.e., only the UI section) is declared. This also addresses confusions like declaring `accounts.email.accounts.*.aerc.extraConfig.general.unsafe-accounts-conf = true` and triggering a warning message because `programs.aerc.extraConfig.general.unsafe-accounts-conf` was unset. This commit also updated documentation throughout the aerc modules to be in line with this change, and fixed minor typos/formatting therein. Co-authored-by: Genevieve <genevieve@sunlashed.garden> * aerc: make assertion plaintext and add test case This commit adds a test case to check both the warning on unset `unsafe-accounts-conf = true` when aerc accounts are configured with Nix, and the new assertion when per-account configuration contains unsupported subsections (i.e. general). It also fixes minor formatting issues and typos.
2023-07-14 18:34:28 +00:00
Aerc only supports per-account UI configuration.
For other sections of {file}`$HOME/.config/aerc/aerc.conf`,
use `programs.aerc.extraConfig`.
See {manpage}`aerc-config(5)`.
2023-02-28 20:16:41 +00:00
'';
};
imapAuth = mkOption {
type = with types; nullOr (enum [ "oauthbearer" "xoauth2" ]);
default = null;
example = "auth";
description = ''
2023-02-28 20:16:41 +00:00
Sets the authentication mechanism if imap is used as the incoming
method.
See {manpage}`aerc-imap(5)`.
'';
};
2023-02-28 20:16:41 +00:00
imapOauth2Params = oauth2Params;
smtpAuth = mkOption {
2023-02-27 21:32:12 +00:00
type = with types;
nullOr (enum [ "none" "plain" "login" "oauthbearer" "xoauth2" ]);
default = "plain";
example = "auth";
description = ''
Sets the authentication mechanism if smtp is used as the outgoing
method.
See {manpage}`aerc-smtp(5)`.
'';
};
2023-02-28 20:16:41 +00:00
smtpOauth2Params = oauth2Params;
};
});
};
mkAccount = name: account:
let
nullOrMap = f: v: if v == null then v else f v;
optPort = port: if port != null then ":${toString port}" else "";
optAttr = k: v:
if v != null && v != [ ] && v != "" then { ${k} = v; } else { };
optPwCmd = k: p:
optAttr "${k}-cred-cmd" (nullOrMap (concatStringsSep " ") p);
2023-02-28 20:16:41 +00:00
useOauth = auth: builtins.elem auth [ "oauthbearer" "xoauth2" ];
oauthParams = { auth, params }:
if useOauth auth && params != null && params != { } then
"?" + builtins.concatStringsSep "&" lib.attrsets.mapAttrsToList
(k: v: k + "=" + lib.strings.escapeURL v) params
else
"";
mkConfig = {
maildir = cfg: {
source =
"maildir://${config.accounts.email.maildirBasePath}/${cfg.maildir.path}";
};
imap = { userName, imap, passwordCommand, aerc, ... }@cfg:
let
2023-02-28 20:16:41 +00:00
loginMethod' =
if cfg.aerc.imapAuth != null then "+${cfg.aerc.imapAuth}" else "";
oauthParams' = oauthParams {
auth = cfg.aerc.imapAuth;
params = cfg.aerc.imapOauth2Params;
};
protocol = if imap.tls.enable then
2023-02-28 20:16:41 +00:00
if imap.tls.useStartTls then "imap" else "imaps${loginMethod'}"
else
"imap+insecure";
port' = optPort imap.port;
in {
2023-02-28 20:16:41 +00:00
source =
"${protocol}://${userName}@${imap.host}${port'}${oauthParams'}";
} // optPwCmd "source" passwordCommand;
smtp = { userName, smtp, passwordCommand, ... }@cfg:
let
loginMethod' =
if cfg.aerc.smtpAuth != null then "+${cfg.aerc.smtpAuth}" else "";
2023-02-28 20:16:41 +00:00
oauthParams' = oauthParams {
auth = cfg.aerc.smtpAuth;
params = cfg.aerc.smtpOauth2Params;
};
protocol = if smtp.tls.enable then
if smtp.tls.useStartTls then
"smtp${loginMethod'}"
else
"smtps${loginMethod'}"
else
"smtp+insecure${loginMethod'}";
port' = optPort smtp.port;
in {
2023-02-28 20:16:41 +00:00
outgoing =
"${protocol}://${userName}@${smtp.host}${port'}${oauthParams'}";
} // optPwCmd "outgoing" passwordCommand;
msmtp = cfg: {
outgoing = "msmtpq --read-envelope-from --read-recipients";
};
};
basicCfg = account:
{
from = "${account.realName} <${account.address}>";
} // (optAttr "copy-to" account.folders.sent)
// (optAttr "default" account.folders.inbox)
// (optAttr "postpone" account.folders.drafts)
// (optAttr "aliases" account.aliases);
sourceCfg = account:
if account.mbsync.enable || account.offlineimap.enable then
mkConfig.maildir account
else if account.imap != null then
mkConfig.imap account
else
{ };
outgoingCfg = account:
if account.msmtp.enable then
mkConfig.msmtp account
else if account.smtp != null then
mkConfig.smtp account
else
{ };
in (basicCfg account) // (sourceCfg account) // (outgoingCfg account)
// account.aerc.extraAccounts;
mkAccountConfig = name: account:
mapAttrNames (addAccountName name) account.aerc.extraConfig;
mkAccountBinds = name: account:
mapAttrNames (addAccountName name) account.aerc.extraBinds;
}