{ config, lib, pkgs, ... }: with lib; let cfg = config.programs.getmail; retrieverModule = types.submodule ({config,...}: { options = { type = mkOption { type = types.enum [ "SimplePOP3Retriever" "SimplePOP3SSLRetriever" "SimpleIMAPRetriever" "SimpleIMAPSSLRetriever" ]; default = "SimpleIMAPSSLRetriever"; description = "Type of the retriever."; }; server = mkOption { type = types.string; default = ""; description = "The remote server."; }; username = mkOption { type = types.string; default = ""; description = "The server username."; }; password = mkOption { type = types.nullOr types.string; default = null; description = '' The server password. Note that the passwords are stored clear in the nix store, so it is recommended to not use this field, but instead either leave empty or use passwordCommand instead. ''; }; passwordCommand = mkOption { type = types.nullOr (types.listOf types.string); default = null; example = ["${pkgs.gnupg}/bin/gpg" "--decrypt" "file.gpg"]; description = '' The server password. With this the password is retrieved with the given command. The list value is given escaped to the implementation. ''; }; mailboxes = mkOption { type = types.listOf types.string; default = []; description = "A list of mailboxes"; }; }; }); destinationModule = types.submodule ({config,...}: { options = { type = mkOption { type = types.enum [ "MDA_external" "Maildir" ]; default = "Maildir"; description = "Destination type."; }; path = mkOption { type = types.string; default = "$HOME/Mail"; example = "${pkgs.procmail}/bin/procmail"; description = '' The destination path. For Maildir it's the file path and for MDA_external it's the destination application. ''; }; }; }); optionsModule = types.submodule ({config,...}: { options = { delete = mkOption { type = types.bool; default = false; description = '' Enable if you want to delete read messages from the server. Most users should either enable delete or disable readAll. ''; }; readAll = mkOption { type = types.bool; default = true; description = '' Enable if you want to fetch all, even the read messages from the server. Most users should either enable delete or disable readAll. ''; }; }; }); in { options = { programs.getmail = { enable = mkEnableOption "Enable getmail"; retriever = mkOption { type = retrieverModule; default = {}; description = "The server section."; }; destination = mkOption { type = destinationModule; default = {}; description = "The destination section."; }; options = mkOption { type = optionsModule; default = {}; description = "The options section."; }; frequency = mkOption { type = types.string; default = "*:0/15"; example = "hourly"; description = '' The refresh frequency. Check man systemd.time for more information on the syntax. ''; }; }; }; config = mkIf cfg.enable { home.file.".getmail/getmailrc".text = let quoted = x: "\"${escape ["\""] x}\""; passwordCommand = concatStringsSep ", " (map quoted cfg.retriever.passwordCommand); password = if cfg.retriever.passwordCommand != null then "password_command = (${passwordCommand})" else optionalString (cfg.retriever.password != null) "password = \"${quoted cfg.retriever.password}\""; mailboxInner = concatStringsSep ", " ( map quoted cfg.retriever.mailboxes); mailboxes = "(${mailboxInner})"; in '' [retriever] type = ${cfg.retriever.type} server = ${cfg.retriever.server} username = ${cfg.retriever.username} ${password} mailboxes = ${mailboxes} [destination] type = ${cfg.destination.type} path = ${cfg.destination.path} [options] delete = ${toString cfg.options.delete} read_all = ${toString cfg.options.readAll} ''; systemd.user.services.getmail = { Unit = { Description = "getmail email fetcher"; PartOf = ["network-online.target"]; }; Service = { Type = "simple"; ExecStart = "${pkgs.getmail}/bin/getmail"; }; }; systemd.user.timers.getmail = { Unit = { Description = "getmail email fetcher"; }; Timer = { OnCalendar = "${cfg.frequency}"; Unit = "getmail.service"; }; Install = { WantedBy = [ "timers.target" ]; }; }; }; }