email: add module
This adds a general module infrastructure for configuring email accounts. The intent is to specify high level information such as IMAP and SMTP hostnames and login information so that more specific program and service modules do not have to duplicate options for specifying accounts. It is allowed for modules to inject further options within this namespace where relevant. For example, an MUA may wish add an option to add per-account filter rules. Co-authored-by: Matthieu Coudron <mattator@gmail.com>
This commit is contained in:
parent
299e01722f
commit
34bb9b5766
323
modules/accounts/email.nix
Normal file
323
modules/accounts/email.nix
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.accounts.email;
|
||||||
|
|
||||||
|
tlsModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to enable TLS/SSL.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
useStartTls = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether to use STARTTLS.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
certificatesFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to file containing certificate authorities that should
|
||||||
|
be used to validate the connection authenticity. If
|
||||||
|
<literal>null</literal> then the system default is used.
|
||||||
|
Note, if set then the system default may still be accepted.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
imapModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
host = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "imap.example.org";
|
||||||
|
description = ''
|
||||||
|
Hostname of IMAP server.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.nullOr types.ints.positive;
|
||||||
|
default = null;
|
||||||
|
example = 993;
|
||||||
|
description = ''
|
||||||
|
The port on which the IMAP server listens. If
|
||||||
|
<literal>null</literal> then the default port is used.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tls = mkOption {
|
||||||
|
type = tlsModule;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Configuration for secure connections.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
smtpModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
host = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "smtp.example.org";
|
||||||
|
description = ''
|
||||||
|
Hostname of SMTP server.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
port = mkOption {
|
||||||
|
type = types.nullOr types.ints.positive;
|
||||||
|
default = null;
|
||||||
|
example = 465;
|
||||||
|
description = ''
|
||||||
|
The port on which the SMTP server listens. If
|
||||||
|
<literal>null</literal> then the default port is used.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
tls = mkOption {
|
||||||
|
type = tlsModule;
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Configuration for secure connections.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
maildirModule = types.submodule ({ config, ... }: {
|
||||||
|
options = {
|
||||||
|
path = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Path to maildir directory where mail for this account is
|
||||||
|
stored. This is relative to the base maildir path.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
absPath = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
default = "${cfg.maildirBasePath}/${config.path}";
|
||||||
|
description = ''
|
||||||
|
A convenience option whose value is the absolute path of
|
||||||
|
this maildir.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
# gpgModule = types.submodule {
|
||||||
|
# };
|
||||||
|
|
||||||
|
mailAccount = types.submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
Unique identifier of the account. This is set to the
|
||||||
|
attribute name of the account configuration.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
primary = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether this is the primary account. Only one account may be
|
||||||
|
set as primary.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
flavor = mkOption {
|
||||||
|
type = types.enum [ "plain" "runbox.com" ];
|
||||||
|
default = "plain";
|
||||||
|
description = ''
|
||||||
|
Some email providers have peculiar behavior that require
|
||||||
|
special treatment. This option is therefore intended to
|
||||||
|
indicate the nature of the provider.
|
||||||
|
</para><para>
|
||||||
|
When this indicates a specific provider then, for example,
|
||||||
|
the IMAP and SMTP server configuration may be set
|
||||||
|
automatically.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
type = types.strMatching ".*@.*";
|
||||||
|
example = "jane.doe@example.org";
|
||||||
|
description = "The email address of this account.";
|
||||||
|
};
|
||||||
|
|
||||||
|
realName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
example = "Jane Doe";
|
||||||
|
description = "Name displayed when sending mails.";
|
||||||
|
};
|
||||||
|
|
||||||
|
userName = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The server username of this account. This will be used as
|
||||||
|
the SMTP and IMAP user name.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordCommand = mkOption {
|
||||||
|
type = types.nullOr (types.either types.str (types.listOf types.str));
|
||||||
|
default = null;
|
||||||
|
apply = p: if isString p then splitString " " p else p;
|
||||||
|
example = "secret-tool lookup email me@example.org";
|
||||||
|
description = ''
|
||||||
|
A command, which when run writes the account password on
|
||||||
|
standard output.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
folders = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
inbox = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Inbox";
|
||||||
|
description = ''
|
||||||
|
Relative path of the inbox mail.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sent = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = "Sent";
|
||||||
|
description = ''
|
||||||
|
Relative path of the sent mail folder.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
drafts = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Drafts";
|
||||||
|
description = ''
|
||||||
|
Relative path of the drafts mail folder.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
trash = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "Trash";
|
||||||
|
description = ''
|
||||||
|
Relative path of the deleted mail folder.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = {};
|
||||||
|
description = ''
|
||||||
|
Standard email folders.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
imap = mkOption {
|
||||||
|
type = types.nullOr imapModule;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The IMAP configuration to use for this account.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
smtp = mkOption {
|
||||||
|
type = types.nullOr smtpModule;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
The SMTP configuration to use for this account.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
maildir = mkOption {
|
||||||
|
type = types.nullOr maildirModule;
|
||||||
|
defaultText = { path = "\${name}"; };
|
||||||
|
description = ''
|
||||||
|
Maildir configuration for this account.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkMerge [
|
||||||
|
{
|
||||||
|
name = name;
|
||||||
|
maildir = mkOptionDefault { path = "${name}"; };
|
||||||
|
}
|
||||||
|
|
||||||
|
(mkIf (config.flavor == "runbox.com") {
|
||||||
|
imap = {
|
||||||
|
host = "mail.runbox.com";
|
||||||
|
};
|
||||||
|
|
||||||
|
smtp = {
|
||||||
|
host = "mail.runbox.com";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options.accounts.email = {
|
||||||
|
maildirBasePath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "${config.home.homeDirectory}/Maildir";
|
||||||
|
defaultText = "$HOME/Maildir";
|
||||||
|
apply = p:
|
||||||
|
if hasPrefix "/" p
|
||||||
|
then p
|
||||||
|
else "${config.home.homeDirectory}/${p}";
|
||||||
|
description = ''
|
||||||
|
The base directory for account maildir directories. May be a
|
||||||
|
relative path, in which case it is relative the home
|
||||||
|
directory.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
accounts = mkOption {
|
||||||
|
type = types.attrsOf mailAccount;
|
||||||
|
default = {};
|
||||||
|
description = "List of email accounts.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (cfg.accounts != {}) {
|
||||||
|
assertions = [
|
||||||
|
(
|
||||||
|
let
|
||||||
|
primaries =
|
||||||
|
catAttrs "name"
|
||||||
|
(filter (a: a.primary)
|
||||||
|
(attrValues cfg.accounts));
|
||||||
|
in
|
||||||
|
{
|
||||||
|
assertion = length primaries == 1;
|
||||||
|
message =
|
||||||
|
"Must have exactly one primary mail account but found "
|
||||||
|
+ toString (length primaries)
|
||||||
|
+ optionalString (length primaries > 1)
|
||||||
|
(", namely " + concatStringsSep ", " primaries);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
|
@ -672,6 +672,24 @@ in
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time = "2018-07-01T14:33:15+00:00";
|
||||||
|
message = ''
|
||||||
|
A new module is available: 'accounts.email'.
|
||||||
|
|
||||||
|
As the name suggests, this new module offers a number of
|
||||||
|
options for configuring email accounts. This, for example,
|
||||||
|
includes the email address and owner's real name but also
|
||||||
|
server settings for IMAP and SMTP.
|
||||||
|
|
||||||
|
The intent is to have a central location for account
|
||||||
|
specific configuration that other modules can use.
|
||||||
|
|
||||||
|
Note, this module is still somewhat experimental and its
|
||||||
|
structure should not be seen as final. Feedback is greatly
|
||||||
|
appreciated, both positive and negative.
|
||||||
|
'';
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ with lib;
|
||||||
let
|
let
|
||||||
|
|
||||||
modules = [
|
modules = [
|
||||||
|
./accounts/email.nix
|
||||||
./files.nix
|
./files.nix
|
||||||
./home-environment.nix
|
./home-environment.nix
|
||||||
./manual.nix
|
./manual.nix
|
||||||
|
|
Loading…
Reference in a new issue