1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6 cfg = config.programs.msmtp;
7
8in {
9 meta.maintainers = with maintainers; [ pacien ];
10
11 options = {
12 programs.msmtp = {
13 enable = mkEnableOption (lib.mdDoc "msmtp - an SMTP client");
14
15 setSendmail = mkOption {
16 type = types.bool;
17 default = true;
18 description = lib.mdDoc ''
19 Whether to set the system sendmail to msmtp's.
20 '';
21 };
22
23 defaults = mkOption {
24 type = types.attrs;
25 default = {};
26 example = {
27 aliases = "/etc/aliases";
28 port = 587;
29 tls = true;
30 };
31 description = lib.mdDoc ''
32 Default values applied to all accounts.
33 See msmtp(1) for the available options.
34 '';
35 };
36
37 accounts = mkOption {
38 type = with types; attrsOf attrs;
39 default = {};
40 example = {
41 "default" = {
42 host = "smtp.example";
43 auth = true;
44 user = "someone";
45 passwordeval = "cat /secrets/password.txt";
46 };
47 };
48 description = lib.mdDoc ''
49 Named accounts and their respective configurations.
50 The special name "default" allows a default account to be defined.
51 See msmtp(1) for the available options.
52
53 Use `programs.msmtp.extraConfig` instead of this attribute set-based
54 option if ordered account inheritance is needed.
55
56 It is advised to use the `passwordeval` setting to read the password
57 from a secret file to avoid having it written in the world-readable
58 nix store. The password file must end with a newline (`\n`).
59 '';
60 };
61
62 extraConfig = mkOption {
63 type = types.lines;
64 default = "";
65 description = lib.mdDoc ''
66 Extra lines to add to the msmtp configuration verbatim.
67 See msmtp(1) for the syntax and available options.
68 '';
69 };
70 };
71 };
72
73 config = mkIf cfg.enable {
74 environment.systemPackages = [ pkgs.msmtp ];
75
76 services.mail.sendmailSetuidWrapper = mkIf cfg.setSendmail {
77 program = "sendmail";
78 source = "${pkgs.msmtp}/bin/sendmail";
79 setuid = false;
80 setgid = false;
81 owner = "root";
82 group = "root";
83 };
84
85 environment.etc."msmtprc".text = let
86 mkValueString = v:
87 if v == true then "on"
88 else if v == false then "off"
89 else generators.mkValueStringDefault {} v;
90 mkKeyValueString = k: v: "${k} ${mkValueString v}";
91 mkInnerSectionString =
92 attrs: concatStringsSep "\n" (mapAttrsToList mkKeyValueString attrs);
93 mkAccountString = name: attrs: ''
94 account ${name}
95 ${mkInnerSectionString attrs}
96 '';
97 in ''
98 defaults
99 ${mkInnerSectionString cfg.defaults}
100
101 ${concatStringsSep "\n" (mapAttrsToList mkAccountString cfg.accounts)}
102
103 ${cfg.extraConfig}
104 '';
105 };
106}