{ config, lib, pkgs, ... }: with lib; let cfg = config.programs.notmuch; mkIniKeyValue = key: value: let tweakVal = v: if isString v then v else if isList v then concatMapStringsSep ";" tweakVal v else if isBool v then toJSON v else toString v; in "${key}=${tweakVal value}"; notmuchIni = recursiveUpdate { database = { path = config.accounts.email.maildirBasePath; }; new = { ignore = cfg.new.ignore; tags = cfg.new.tags; }; user = let accounts = filter (a: a.notmuch.enable) (attrValues config.accounts.email.accounts); primary = filter (a: a.primary) accounts; secondaries = filter (a: !a.primary) accounts; in { name = catAttrs "realName" primary; primary_email = catAttrs "address" primary; other_email = catAttrs "address" secondaries; }; search = { exclude_tags = [ "deleted" "spam" ]; }; } cfg.extraConfig; in { options = { programs.notmuch = { enable = mkEnableOption "Notmuch mail indexer"; new = mkOption { type = types.submodule { options = { ignore = mkOption { type = types.listOf types.str; default = []; description = '' A list to specify files and directories that will not be searched for messages by notmuch new. ''; }; tags = mkOption { type = types.listOf types.str; default = [ "unread" "inbox" ]; example = [ "new" ]; description = '' A list of tags that will be added to all messages incorporated by notmuch new. ''; }; }; }; default = {}; description = '' Options related to email processing performed by notmuch new. ''; }; extraConfig = mkOption { type = types.attrsOf (types.attrsOf types.str); default = { maildir = { synchronize_flags = "true"; }; }; description = '' Options that should be appended to the notmuch configuration file. ''; }; hooks = { preNew = mkOption { type = types.lines; default = ""; example = "mbsync --all"; description = '' Bash statements run before scanning or importing new messages into the database. ''; }; postNew = mkOption { type = types.lines; default = ""; example = '' notmuch tag +nixos -- tag:new and from:nixos1@discoursemail.com ''; description = '' Bash statements run after new messages have been imported into the database and initial tags have been applied. ''; }; postInsert = mkOption { type = types.lines; default = ""; description = '' Bash statements run after a message has been inserted into the database and initial tags have been applied. ''; }; }; }; }; config = mkIf cfg.enable { assertions = [ { assertion = notmuchIni.user.name != []; message = "notmuch: Must have a user name set."; } { assertion = notmuchIni.user.primary_email != []; message = "notmuch: Must have a user primary email address set."; } ]; home.packages = [ pkgs.notmuch ]; home.sessionVariables = { NOTMUCH_CONFIG = "${config.xdg.configHome}/notmuch/notmuchrc"; NMBGIT = "${config.xdg.dataHome}/notmuch/nmbug"; }; xdg.configFile."notmuch/notmuchrc".text = let toIni = generators.toINI { mkKeyValue = mkIniKeyValue; }; in "# Generated by Home Manager.\n\n" + toIni notmuchIni; home.file = let hook = name: cmds: { target = "${notmuchIni.database.path}/.notmuch/hooks/${name}"; source = pkgs.writeScript name '' #!${pkgs.stdenv.shell} export PATH="${pkgs.notmuch}/bin''${PATH:+:}$PATH" export NOTMUCH_CONFIG="${config.xdg.configHome}/notmuch/notmuchrc" export NMBGIT="${config.xdg.dataHome}/notmuch/nmbug" ${cmds} ''; executable = true; }; in optional (cfg.hooks.preNew != "") (hook "pre-new" cfg.hooks.preNew) ++ optional (cfg.hooks.postNew != "") (hook "post-new" cfg.hooks.postNew) ++ optional (cfg.hooks.postInsert != "") (hook "post-insert" cfg.hooks.postInsert); }; }