From 44ee9bc826770df1ab83c7e93f77fdaddd37523a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Fri, 19 Apr 2024 11:38:48 +0200 Subject: [PATCH 1/5] himalaya: improve service --- modules/programs/himalaya.nix | 53 +++++++++++++---------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index 2d216c3dc..04a277019 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -130,16 +130,6 @@ in { Extra environment variables to be exported in the service. ''; }; - - 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 { @@ -171,31 +161,26 @@ in { globalConfig = compactAttrs himalaya.settings; allConfig = globalConfig // { accounts = accountsConfig; }; in tomlFormat.generate "himalaya-config.toml" allConfig; - 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; + + systemd.user.services = + let inherit (config.services.himalaya-watch) enable environment; + in { + "himalaya-watch@" = lib.mkIf enable { + Unit = { + Description = "Email client Himalaya CLI envelopes watcher service"; + After = [ "network.target" ]; + }; + Install = { WantedBy = [ "default.target" ]; }; + Service = { + ExecStart = + "${himalaya.package}/bin/himalaya envelopes watch --account %I"; + ExecSearchPath = "/bin"; + Environment = + lib.mapAttrsToList (key: val: "${key}=${val}") environment; + Restart = "always"; + RestartSec = 10; + }; }; }; - }; }; } From 5f5a9d5cd23e6ff7f877ec66b498bb02585a72b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Fri, 19 Apr 2024 11:56:54 +0200 Subject: [PATCH 2/5] himalaya: make use of lib.getExe --- modules/programs/himalaya.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index 04a277019..563de0a53 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -82,7 +82,7 @@ let sendmailConfig = lib.optionalAttrs (isNull account.smtp && !isNull account.msmtp) { sender = "sendmail"; - sendmail.cmd = "${pkgs.msmtp}/bin/msmtp"; + sendmail.cmd = lib.getExe pkgs.msmtp; }; config = lib.attrsets.mergeAttrsList [ @@ -173,7 +173,7 @@ in { Install = { WantedBy = [ "default.target" ]; }; Service = { ExecStart = - "${himalaya.package}/bin/himalaya envelopes watch --account %I"; + "${lib.getExe himalaya.package} envelopes watch --account %I"; ExecSearchPath = "/bin"; Environment = lib.mapAttrsToList (key: val: "${key}=${val}") environment; From 2ae3dd460f60822434959a92e8e19c9f9b7efce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Sat, 20 Apr 2024 09:49:20 +0200 Subject: [PATCH 3/5] himalaya: add xdg desktop entry --- modules/programs/himalaya.nix | 60 +++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index 563de0a53..54e82972f 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -154,32 +154,44 @@ in { config = lib.mkIf himalaya.enable { home.packages = [ himalaya.package ]; - xdg.configFile."himalaya/config.toml".source = let - enabledAccounts = lib.filterAttrs (_: account: account.himalaya.enable) - config.accounts.email.accounts; - accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts; - globalConfig = compactAttrs himalaya.settings; - allConfig = globalConfig // { accounts = accountsConfig; }; - in tomlFormat.generate "himalaya-config.toml" allConfig; + xdg = { + configFile."himalaya/config.toml".source = let + enabledAccounts = lib.filterAttrs (_: account: account.himalaya.enable) + config.accounts.email.accounts; + accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts; + globalConfig = compactAttrs himalaya.settings; + allConfig = globalConfig // { accounts = accountsConfig; }; + in tomlFormat.generate "himalaya-config.toml" allConfig; - systemd.user.services = + desktopEntries.himalaya = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { + type = "Application"; + name = "himalaya"; + genericName = "Email Client"; + comment = "CLI to manage emails"; + terminal = true; + exec = "himalaya %u"; + categories = [ "Network" ]; + mimeType = [ "x-scheme-handler/mailto" "message/rfc822" ]; + settings = { Keywords = "email"; }; + }; + }; + + systemd.user.services."himalaya-watch@" = let inherit (config.services.himalaya-watch) enable environment; - 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.getExe himalaya.package} envelopes watch --account %I"; - ExecSearchPath = "/bin"; - Environment = - lib.mapAttrsToList (key: val: "${key}=${val}") environment; - Restart = "always"; - RestartSec = 10; - }; + in lib.mkIf enable { + Unit = { + Description = "Email client Himalaya CLI envelopes watcher service"; + After = [ "network.target" ]; + }; + Install = { WantedBy = [ "default.target" ]; }; + Service = { + ExecStart = + "${lib.getExe himalaya.package} envelopes watch --account %I"; + ExecSearchPath = "/bin"; + Environment = + lib.mapAttrsToList (key: val: "${key}=${val}") environment; + Restart = "always"; + RestartSec = 10; }; }; }; From e9068facd7bcfb99405d0e5e3b938f5e5ddc38e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Thu, 2 Jan 2025 08:25:14 +0100 Subject: [PATCH 4/5] himalaya: adjust package for released v1.0.0 --- modules/programs/himalaya.nix | 100 ++++++++++++++-------------------- 1 file changed, 40 insertions(+), 60 deletions(-) diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index 54e82972f..dd1926d6b 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -35,7 +35,7 @@ let email = account.address; display-name = account.realName; default = account.primary; - folder.alias = { + folder.aliases = { inbox = account.folders.inbox; sent = account.folders.sent; drafts = account.folders.drafts; @@ -46,43 +46,48 @@ let signatureConfig = lib.optionalAttrs (account.signature.showSignature == "append") { # TODO: signature cannot be attached yet - # https://todo.sr.ht/~soywod/pimalaya/27 + # https://github.com/pimalaya/himalaya/issues/534 signature = account.signature.text; signature-delim = account.signature.delimiter; }; imapConfig = lib.optionalAttrs imapEnabled (compactAttrs { - backend = "imap"; - 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; + backend.type = "imap"; + backend.host = account.imap.host; + backend.port = account.imap.port; + backend.encryption.type = mkEncryptionConfig account.imap.tls; + backend.login = account.userName; + backend.auth.type = "password"; + backend.auth.cmd = + builtins.concatStringsSep " " account.passwordCommand; }); maildirConfig = lib.optionalAttrs maildirEnabled (compactAttrs { - backend = "maildir"; - maildir.root-dir = account.maildir.absPath; + backend.type = "maildir"; + backend.root-dir = account.maildir.absPath; }); notmuchConfig = lib.optionalAttrs notmuchEnabled (compactAttrs { - backend = "notmuch"; - notmuch.database-path = maildirBasePath; + backend.type = "notmuch"; + backend.db-path = maildirBasePath; }); smtpConfig = lib.optionalAttrs (!isNull account.smtp) (compactAttrs { - 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; + message.send.backend.type = "smtp"; + message.send.backend.host = account.smtp.host; + message.send.backend.port = account.smtp.port; + message.send.backend.encryption.type = + mkEncryptionConfig account.smtp.tls; + message.send.backend.login = account.userName; + message.send.backend.auth.type = "password"; + message.send.backend.auth.cmd = + builtins.concatStringsSep " " account.passwordCommand; }); sendmailConfig = lib.optionalAttrs (isNull account.smtp && !isNull account.msmtp) { - sender = "sendmail"; - sendmail.cmd = lib.getExe pkgs.msmtp; + message.send.backend.type = "sendmail"; + message.send.backend.cmd = lib.getExe pkgs.msmtp; }; config = lib.attrsets.mergeAttrsList [ @@ -100,6 +105,18 @@ let in { meta.maintainers = with lib.hm.maintainers; [ soywod toastal ]; + imports = [ + (mkRemovedOptionModule [ "services" "himalaya-watch" "enable" ] '' + services.himalaya-watch has been removed. + + The watch feature moved away from Himalaya scope, and resides + now in its own project called Mirador. Once the v1 released, the + service will land back in nixpkgs and home-manager. + + See . + '') + ]; + options = { programs.himalaya = { enable = lib.mkEnableOption "the email client Himalaya CLI"; @@ -109,25 +126,7 @@ in { default = { }; description = '' Himalaya CLI global configuration. - See for supported values. - ''; - }; - }; - - services.himalaya-watch = { - enable = lib.mkEnableOption - "the email client Himalaya CLI envelopes 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. + See for supported values. ''; }; }; @@ -143,7 +142,7 @@ in { default = { }; description = '' Himalaya CLI configuration for this email account. - See for supported values. + See for supported values. ''; }; }; @@ -161,7 +160,7 @@ in { accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts; globalConfig = compactAttrs himalaya.settings; allConfig = globalConfig // { accounts = accountsConfig; }; - in tomlFormat.generate "himalaya-config.toml" allConfig; + in tomlFormat.generate "himalaya.config.toml" allConfig; desktopEntries.himalaya = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { type = "Application"; @@ -175,24 +174,5 @@ in { settings = { Keywords = "email"; }; }; }; - - systemd.user.services."himalaya-watch@" = - let inherit (config.services.himalaya-watch) enable environment; - in lib.mkIf enable { - Unit = { - Description = "Email client Himalaya CLI envelopes watcher service"; - After = [ "network.target" ]; - }; - Install = { WantedBy = [ "default.target" ]; }; - Service = { - ExecStart = - "${lib.getExe himalaya.package} envelopes watch --account %I"; - ExecSearchPath = "/bin"; - Environment = - lib.mapAttrsToList (key: val: "${key}=${val}") environment; - Restart = "always"; - RestartSec = 10; - }; - }; }; } From 15f7f9bc4e7aedcdd26e2f20fc4b46220ead584d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Fri, 24 Jan 2025 06:17:50 +0100 Subject: [PATCH 5/5] himalaya: fix tests --- modules/programs/himalaya.nix | 50 ++++++++++--------- .../programs/himalaya/basic-expected.toml | 37 +++++++------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/modules/programs/himalaya.nix b/modules/programs/himalaya.nix index dd1926d6b..2348e0f93 100644 --- a/modules/programs/himalaya.nix +++ b/modules/programs/himalaya.nix @@ -1,12 +1,14 @@ { config, lib, pkgs, ... }: +with lib; + let # aliases inherit (config.programs) himalaya; tomlFormat = pkgs.formats.toml { }; # attrs util that removes entries containing a null value - compactAttrs = lib.filterAttrs (_: val: !isNull val); + compactAttrs = filterAttrs (_: val: !isNull val); # needed for notmuch config, because the DB is here, and not in each # account's dir @@ -44,14 +46,14 @@ let }; signatureConfig = - lib.optionalAttrs (account.signature.showSignature == "append") { + optionalAttrs (account.signature.showSignature == "append") { # TODO: signature cannot be attached yet # https://github.com/pimalaya/himalaya/issues/534 signature = account.signature.text; signature-delim = account.signature.delimiter; }; - imapConfig = lib.optionalAttrs imapEnabled (compactAttrs { + imapConfig = optionalAttrs imapEnabled (compactAttrs { backend.type = "imap"; backend.host = account.imap.host; backend.port = account.imap.port; @@ -62,17 +64,17 @@ let builtins.concatStringsSep " " account.passwordCommand; }); - maildirConfig = lib.optionalAttrs maildirEnabled (compactAttrs { + maildirConfig = optionalAttrs maildirEnabled (compactAttrs { backend.type = "maildir"; backend.root-dir = account.maildir.absPath; }); - notmuchConfig = lib.optionalAttrs notmuchEnabled (compactAttrs { + notmuchConfig = optionalAttrs notmuchEnabled (compactAttrs { backend.type = "notmuch"; backend.db-path = maildirBasePath; }); - smtpConfig = lib.optionalAttrs (!isNull account.smtp) (compactAttrs { + smtpConfig = optionalAttrs (!isNull account.smtp) (compactAttrs { message.send.backend.type = "smtp"; message.send.backend.host = account.smtp.host; message.send.backend.port = account.smtp.port; @@ -85,12 +87,12 @@ let }); sendmailConfig = - lib.optionalAttrs (isNull account.smtp && !isNull account.msmtp) { + optionalAttrs (isNull account.smtp && !isNull account.msmtp) { message.send.backend.type = "sendmail"; - message.send.backend.cmd = lib.getExe pkgs.msmtp; + message.send.backend.cmd = getExe pkgs.msmtp; }; - config = lib.attrsets.mergeAttrsList [ + config = attrsets.mergeAttrsList [ globalConfig signatureConfig imapConfig @@ -100,10 +102,10 @@ let sendmailConfig ]; - in lib.recursiveUpdate config account.himalaya.settings; + in recursiveUpdate config account.himalaya.settings; in { - meta.maintainers = with lib.hm.maintainers; [ soywod toastal ]; + meta.maintainers = with hm.maintainers; [ soywod toastal ]; imports = [ (mkRemovedOptionModule [ "services" "himalaya-watch" "enable" ] '' @@ -119,10 +121,10 @@ in { options = { programs.himalaya = { - enable = lib.mkEnableOption "the email client Himalaya CLI"; - package = lib.mkPackageOption pkgs "himalaya" { }; - settings = lib.mkOption { - type = lib.types.submodule { freeformType = tomlFormat.type; }; + enable = mkEnableOption "the email client Himalaya CLI"; + package = mkPackageOption pkgs "himalaya" { }; + settings = mkOption { + type = types.submodule { freeformType = tomlFormat.type; }; default = { }; description = '' Himalaya CLI global configuration. @@ -131,14 +133,14 @@ in { }; }; - accounts.email.accounts = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule { + accounts.email.accounts = mkOption { + type = types.attrsOf (types.submodule { options.himalaya = { - enable = lib.mkEnableOption + enable = mkEnableOption "the email client Himalaya CLI for this email account"; - settings = lib.mkOption { - type = lib.types.submodule { freeformType = tomlFormat.type; }; + settings = mkOption { + type = types.submodule { freeformType = tomlFormat.type; }; default = { }; description = '' Himalaya CLI configuration for this email account. @@ -150,19 +152,19 @@ in { }; }; - config = lib.mkIf himalaya.enable { + config = mkIf himalaya.enable { home.packages = [ himalaya.package ]; xdg = { configFile."himalaya/config.toml".source = let - enabledAccounts = lib.filterAttrs (_: account: account.himalaya.enable) + enabledAccounts = filterAttrs (_: account: account.himalaya.enable) config.accounts.email.accounts; - accountsConfig = lib.mapAttrs mkAccountConfig enabledAccounts; + accountsConfig = mapAttrs mkAccountConfig enabledAccounts; globalConfig = compactAttrs himalaya.settings; allConfig = globalConfig // { accounts = accountsConfig; }; in tomlFormat.generate "himalaya.config.toml" allConfig; - desktopEntries.himalaya = lib.mkIf pkgs.stdenv.hostPlatform.isLinux { + desktopEntries.himalaya = mkIf pkgs.stdenv.hostPlatform.isLinux { type = "Application"; name = "himalaya"; genericName = "Email Client"; diff --git a/tests/modules/programs/himalaya/basic-expected.toml b/tests/modules/programs/himalaya/basic-expected.toml index 16c70c868..15e2e65bf 100644 --- a/tests/modules/programs/himalaya/basic-expected.toml +++ b/tests/modules/programs/himalaya/basic-expected.toml @@ -1,32 +1,33 @@ [accounts."hm@example.com"] -backend = "imap" default = true display-name = "H. M. Test" email = "hm@example.com" +[accounts."hm@example.com".backend] +host = "imap.example.com" +login = "home.manager" +port = 993 +type = "imap" +[accounts."hm@example.com".backend.auth] +cmd = "password-command" +type = "password" -[accounts."hm@example.com".folder.alias] +[accounts."hm@example.com".backend.encryption] +type = "tls" + +[accounts."hm@example.com".folder.aliases] drafts = "Drafts" inbox = "Inbox" sent = "Sent" trash = "Trash" -[accounts."hm@example.com".imap] -encryption = "tls" -host = "imap.example.com" -login = "home.manager" -port = 993 - -[accounts."hm@example.com".imap.passwd] -cmd = "password-command" - -[accounts."hm@example.com".message.send] -backend = "smtp" - -[accounts."hm@example.com".smtp] -encryption = "tls" +[accounts."hm@example.com".message.send.backend] host = "smtp.example.com" login = "home.manager" port = 465 - -[accounts."hm@example.com".smtp.passwd] +type = "smtp" +[accounts."hm@example.com".message.send.backend.auth] cmd = "password-command" +type = "password" + +[accounts."hm@example.com".message.send.backend.encryption] +type = "tls"