Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

himalaya: adjust module for v1.0.0-beta #4839

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 93 additions & 162 deletions modules/programs/himalaya.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ let
# attrs util that removes entries containing a null value
compactAttrs = lib.filterAttrs (_: val: !isNull val);

# Needed for notmuch config, because the DB is here, and not in each account's dir
# needed for notmuch config, because the DB is here, and not in each
# account's dir
maildirBasePath = config.accounts.email.maildirBasePath;

# make a himalaya config from a home-manager email account config
# make encryption config based on the given home-manager email
# account TLS config
mkEncryptionConfig = tls:
if tls.useStartTls then
"start-tls"
else if tls.enable then
"tls"
else
"none";

# make a himalaya account config based on the given home-manager
# email account config
mkAccountConfig = _: account:
let
# Use notmuch if it's enabled, otherwise fallback to IMAP then maildir
# Maildir is always set, so there's no easy way to detect if it's being used
notmuchEnabled = account.notmuch.enable;
imapEnabled = !isNull account.imap && !notmuchEnabled;
maildirEnabled = !isNull account.maildir && !imapEnabled
Expand All @@ -25,7 +35,7 @@ let
email = account.address;
display-name = account.realName;
default = account.primary;
folder-aliases = {
folder.alias = {
inbox = account.folders.inbox;
sent = account.folders.sent;
drafts = account.folders.drafts;
Expand All @@ -43,202 +53,107 @@ let

imapConfig = lib.optionalAttrs imapEnabled (compactAttrs {
backend = "imap";
imap-host = account.imap.host;
imap-port = account.imap.port;
imap-ssl = account.imap.tls.enable;
imap-starttls = account.imap.tls.useStartTls;
imap-login = account.userName;
imap-auth = "passwd";
imap-passwd.cmd = builtins.concatStringsSep " " account.passwordCommand;
imap.host = account.imap.host;
imap.port = account.imap.port;
imap.encryption = mkEncryptionConfig account.imap.tls;
imap.login = account.userName;
imap.passwd.cmd = builtins.concatStringsSep " " account.passwordCommand;
});

maildirConfig = lib.optionalAttrs maildirEnabled (compactAttrs {
backend = "maildir";
maildir-root-dir = account.maildir.absPath;
maildir.root-dir = account.maildir.absPath;
});

notmuchConfig = lib.optionalAttrs notmuchEnabled (compactAttrs {
backend = "notmuch";
notmuch-db-path = maildirBasePath;
notmuch.database-path = maildirBasePath;
});

smtpConfig = lib.optionalAttrs (!isNull account.smtp) (compactAttrs {
sender = "smtp";
smtp-host = account.smtp.host;
smtp-port = account.smtp.port;
smtp-ssl = account.smtp.tls.enable;
smtp-starttls = account.smtp.tls.useStartTls;
smtp-login = account.userName;
smtp-auth = "passwd";
smtp-passwd.cmd = builtins.concatStringsSep " " account.passwordCommand;
message.send.backend = "smtp";
smtp.host = account.smtp.host;
smtp.port = account.smtp.port;
smtp.encryption = mkEncryptionConfig account.smtp.tls;
smtp.login = account.userName;
smtp.passwd.cmd = builtins.concatStringsSep " " account.passwordCommand;
});

sendmailConfig =
lib.optionalAttrs (isNull account.smtp && !isNull account.msmtp) {
sender = "sendmail";
sendmail-cmd = "${pkgs.msmtp}/bin/msmtp";
sendmail.cmd = "${pkgs.msmtp}/bin/msmtp";
};

config = globalConfig // signatureConfig // imapConfig // maildirConfig
// notmuchConfig // smtpConfig // sendmailConfig;
config = lib.attrsets.mergeAttrsList [
globalConfig
signatureConfig
imapConfig
maildirConfig
notmuchConfig
smtpConfig
sendmailConfig
];

in lib.recursiveUpdate config account.himalaya.settings;

# make a systemd service config from a name and a description
mkServiceConfig = name: desc:
let
inherit (config.services."himalaya-${name}") enable environment settings;
optionalArg = key:
if (key ? settings && !isNull settings."${key}") then
[ "--${key} ${settings."${key}"}" ]
else
[ ];
in {
"himalaya-${name}" = lib.mkIf enable {
Unit = {
Description = desc;
After = [ "network.target" ];
};
Install = { WantedBy = [ "default.target" ]; };
Service = {
ExecStart = lib.concatStringsSep " "
([ "${himalaya.package}/bin/himalaya" ] ++ optionalArg "account"
++ [ name ] ++ optionalArg "keepalive");
ExecSearchPath = "/bin";
Environment =
lib.mapAttrsToList (key: val: "${key}=${val}") environment;
Restart = "always";
RestartSec = 10;
};
};
};

in {
meta.maintainers = with lib.hm.maintainers; [ soywod toastal ];

options = {
programs.himalaya = {
enable = lib.mkEnableOption "the Himalaya email client";
enable = lib.mkEnableOption "the email client Himalaya CLI";
package = lib.mkPackageOption pkgs "himalaya" { };
settings = lib.mkOption {
type = lib.types.submodule { freeformType = tomlFormat.type; };
default = { };
description = ''
Himalaya global configuration.
See <https://pimalaya.org/himalaya/cli/configuration/global.html> for supported values.
Himalaya CLI global configuration.
See <https://pimalaya.org/himalaya/cli/latest/configuration/index.html#global-configuration> for supported values.
'';
};
};

services = {
himalaya-notify = {
enable = lib.mkEnableOption "the Himalaya new emails notifier service";

environment = lib.mkOption {
type = with lib.types; attrsOf str;
default = { };
example = lib.literalExpression ''
{
"PASSWORD_STORE_DIR" = "~/.password-store";
}
'';
description = ''
Extra environment variables to be exported in the service.
'';
};

settings = {
account = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
example = "gmail";
description = ''
Name of the account the notifier should be started for. If
no account is given, the default one is used.
'';
};
services.himalaya-watch = {
enable = lib.mkEnableOption
"the email client Himalaya CLI envelopes watcher service";

keepalive = lib.mkOption {
type = with lib.types; nullOr int;
default = null;
example = "500";
description = ''
Notifier lifetime of the IDLE session (in seconds).
'';
};
};
environment = lib.mkOption {
type = with lib.types; attrsOf str;
default = { };
example = lib.literalExpression ''
{
"PASSWORD_STORE_DIR" = "~/.password-store";
}
'';
description = ''
Extra environment variables to be exported in the service.
'';
};

himalaya-watch = {
enable =
lib.mkEnableOption "the Himalaya folder changes watcher service";

environment = lib.mkOption {
type = with lib.types; attrsOf str;
default = { };
example = lib.literalExpression ''
{
"PASSWORD_STORE_DIR" = "~/.password-store";
}
'';
description = ''
Extra environment variables to be exported in the service.
'';
};

settings = {
account = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
example = "gmail";
description = ''
Name of the account the watcher should be started for. If
no account is given, the default one is used.
'';
};

keepalive = lib.mkOption {
type = with lib.types; nullOr int;
default = null;
example = "500";
description = ''
Watcher lifetime of the IDLE session (in seconds).
'';
};
};
settings.account = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
example = "personal";
description = ''
Name of the account the watcher should be started for.
If no account is given, the default one is used.
'';
};
};

accounts.email.accounts = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule {
options.himalaya = {
enable = lib.mkEnableOption "Himalaya for this email account";

# TODO: remove me for the next release
backend = lib.mkOption {
type = with lib.types; nullOr str;
default = null;
description = ''
Specifying {option}`accounts.email.accounts.*.himalaya.backend` is deprecated,
set {option}`accounts.email.accounts.*.himalaya.settings.backend` instead.
'';
};

# TODO: remove me for the next release
sender = lib.mkOption {
type = with lib.types; nullOr str;
description = ''
Specifying {option}`accounts.email.accounts.*.himalaya.sender` is deprecated,
set {option}'accounts.email.accounts.*.himalaya.settings.sender' instead.
'';
};
enable = lib.mkEnableOption
"the email client Himalaya CLI for this email account";

settings = lib.mkOption {
type = lib.types.submodule { freeformType = tomlFormat.type; };
default = { };
description = ''
Himalaya configuration for this email account.
See <https://pimalaya.org/himalaya/cli/configuration/account.html> for supported values.
Himalaya CLI configuration for this email account.
See <https://pimalaya.org/himalaya/cli/latest/configuration/index.html#account-configuration> for supported values.
'';
};
};
Expand All @@ -256,15 +171,31 @@ in {
globalConfig = compactAttrs himalaya.settings;
allConfig = globalConfig // accountsConfig;
in tomlFormat.generate "himalaya-config.toml" allConfig;

systemd.user.services = { }
// mkServiceConfig "notify" "Himalaya new emails notifier service"
// mkServiceConfig "watch" "Himalaya folder changes watcher service";

# TODO: remove me for the next release
warnings = (lib.optional ("backend" ? himalaya && !isNull himalaya.backend)
"Specifying 'accounts.email.accounts.*.himalaya.backend' is deprecated, set 'accounts.email.accounts.*.himalaya.settings.backend' instead")
++ (lib.optional ("sender" ? himalaya && !isNull himalaya.sender)
"Specifying 'accounts.email.accounts.*.himalaya.sender' is deprecated, set 'accounts.email.accounts.*.himalaya.settings.sender' instead.");
systemd.user.services = let
inherit (config.services.himalaya-watch) enable environment settings;
optionalArg = key:
if (key ? settings && !isNull settings."${key}") then
[ "--${key} ${settings."${key}"}" ]
else
[ ];
in {
himalaya-watch = lib.mkIf enable {
Unit = {
Description = "Email client Himalaya CLI envelopes watcher service";
After = [ "network.target" ];
};
Install = { WantedBy = [ "default.target" ]; };
Service = {
ExecStart = lib.concatStringsSep " "
([ "${himalaya.package}/bin/himalaya" "envelopes" "watch" ]
++ optionalArg "account");
ExecSearchPath = "/bin";
Environment =
lib.mapAttrsToList (key: val: "${key}=${val}") environment;
Restart = "always";
RestartSec = 10;
};
};
};
};
}
34 changes: 18 additions & 16 deletions tests/modules/programs/himalaya/basic-expected.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,30 @@ backend = "imap"
default = true
display-name = "H. M. Test"
email = "[email protected]"
imap-auth = "passwd"
imap-host = "imap.example.com"
imap-login = "home.manager"
imap-port = 993
imap-ssl = true
imap-starttls = false
sender = "smtp"
smtp-auth = "passwd"
smtp-host = "smtp.example.com"
smtp-login = "home.manager"
smtp-port = 465
smtp-ssl = true
smtp-starttls = false

["[email protected]".folder-aliases]
["[email protected]".folder.alias]
drafts = "Drafts"
inbox = "Inbox"
sent = "Sent"
trash = "Trash"

["[email protected]".imap-passwd]
["[email protected]".imap]
encryption = "tls"
host = "imap.example.com"
login = "home.manager"
port = 993

["[email protected]".imap.passwd]
cmd = "password-command"

["[email protected]".smtp-passwd]
["[email protected]".message.send]
backend = "smtp"

["[email protected]".smtp]
encryption = "tls"
host = "smtp.example.com"
login = "home.manager"
port = 465

["[email protected]".smtp.passwd]
cmd = "password-command"
2 changes: 0 additions & 2 deletions tests/modules/programs/himalaya/basic.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ with lib;
imap.port = 993;
smtp.port = 465;
himalaya.enable = true;
himalaya.backend = test.asserts.warnings.expected;
himalaya.sender = test.asserts.warnings.expected;
};
};

Expand Down
7 changes: 1 addition & 6 deletions tests/modules/programs/himalaya/default.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
{
himalaya-basic = ./basic.nix;
himalaya-imap-smtp = ./imap-smtp.nix;
himalaya-maildir-sendmail = ./maildir-sendmail.nix;
himalaya-notmuch-sendmail = ./notmuch-sendmail.nix;
}
{ himalaya-basic = ./basic.nix; }
Loading
Loading