1 { config, lib, pkgs, ... }:
6 services.nullmailer = {
7 enable = lib.mkOption {
10 description = "Whether to enable nullmailer daemon.";
15 default = "nullmailer";
17 User to use to run nullmailer-send.
21 group = lib.mkOption {
23 default = "nullmailer";
25 Group to use to run nullmailer-send.
29 setSendmail = lib.mkOption {
30 type = lib.types.bool;
32 description = "Whether to set the system sendmail to nullmailer's.";
35 remotesFile = lib.mkOption {
36 type = lib.types.nullOr lib.types.str;
39 Path to the `remotes` control file. This file contains a
40 list of remote servers to which to send each message.
42 See `man 8 nullmailer-send` for syntax and available
48 adminaddr = lib.mkOption {
49 type = lib.types.nullOr lib.types.str;
52 If set, all recipients to users at either "localhost" (the literal string)
53 or the canonical host name (from the me control attribute) are remapped to this address.
54 This is provided to allow local daemons to be able to send email to
55 "somebody@localhost" and have it go somewhere sensible instead of being bounced
56 by your relay host. To send to multiple addresses,
57 put them all on one line separated by a comma.
61 allmailfrom = lib.mkOption {
62 type = lib.types.nullOr lib.types.str;
65 If set, content will override the envelope sender on all messages.
69 defaultdomain = lib.mkOption {
70 type = lib.types.nullOr lib.types.str;
73 The content of this attribute is appended to any host name that
74 does not contain a period (except localhost), including defaulthost
75 and idhost. Defaults to the value of the me attribute, if it exists,
76 otherwise the literal name defauldomain.
80 defaulthost = lib.mkOption {
81 type = lib.types.nullOr lib.types.str;
84 The content of this attribute is appended to any address that
85 is missing a host name. Defaults to the value of the me control
86 attribute, if it exists, otherwise the literal name defaulthost.
90 doublebounceto = lib.mkOption {
91 type = lib.types.nullOr lib.types.str;
94 If the original sender was empty (the original message was a
95 delivery status or disposition notification), the double bounce
96 is sent to the address in this attribute.
100 helohost = lib.mkOption {
101 type = lib.types.nullOr lib.types.str;
104 Sets the environment variable $HELOHOST which is used by the
105 SMTP protocol module to set the parameter given to the HELO command.
106 Defaults to the value of the me configuration attribute.
110 idhost = lib.mkOption {
111 type = lib.types.nullOr lib.types.str;
114 The content of this attribute is used when building the message-id
115 string for the message. Defaults to the canonicalized value of defaulthost.
119 maxpause = lib.mkOption {
120 type = with lib.types; nullOr (oneOf [ str int ]);
123 The maximum time to pause between successive queue runs, in seconds.
124 Defaults to 24 hours (86400).
129 type = lib.types.nullOr lib.types.str;
132 The fully-qualifiled host name of the computer running nullmailer.
133 Defaults to the literal name me.
137 pausetime = lib.mkOption {
138 type = with lib.types; nullOr (oneOf [ str int ]);
141 The minimum time to pause between successive queue runs when there
142 are messages in the queue, in seconds. Defaults to 1 minute (60).
143 Each time this timeout is reached, the timeout is doubled to a
144 maximum of maxpause. After new messages are injected, the timeout
145 is reset. If this is set to 0, nullmailer-send will exit
146 immediately after going through the queue once (one-shot mode).
150 remotes = lib.mkOption {
151 type = lib.types.nullOr lib.types.str;
154 A list of remote servers to which to send each message. Each line
155 contains a remote host name or address followed by an optional
156 protocol string, separated by white space.
158 See `man 8 nullmailer-send` for syntax and available
161 WARNING: This is stored world-readable in the nix store. If you need
162 to specify any secret credentials here, consider using the
163 `remotesFile` option instead.
167 sendtimeout = lib.mkOption {
168 type = with lib.types; nullOr (oneOf [ str int ]);
171 The time to wait for a remote module listed above to complete sending
172 a message before killing it and trying again, in seconds.
173 Defaults to 1 hour (3600). If this is set to 0, nullmailer-send
174 will wait forever for messages to complete sending.
182 cfg = config.services.nullmailer;
183 in lib.mkIf cfg.enable {
186 { assertion = cfg.config.remotes == null || cfg.remotesFile == null;
187 message = "Only one of `remotesFile` or `config.remotes` may be used at a time.";
192 systemPackages = [ pkgs.nullmailer ];
194 validAttrs = lib.mapAttrs (_: toString) (lib.filterAttrs (_: value: value != null) cfg.config);
196 (lib.foldl' (as: name: as // { "nullmailer/${name}".text = validAttrs.${name}; }) {} (lib.attrNames validAttrs))
197 // lib.optionalAttrs (cfg.remotesFile != null) { "nullmailer/remotes".source = cfg.remotesFile; };
201 users.${cfg.user} = {
202 description = "Nullmailer relay-only mta user";
207 groups.${cfg.group} = { };
210 systemd.tmpfiles.rules = [
211 "d /var/spool/nullmailer - ${cfg.user} ${cfg.group} - -"
212 "d /var/spool/nullmailer/failed 770 ${cfg.user} ${cfg.group} - -"
213 "d /var/spool/nullmailer/queue 770 ${cfg.user} ${cfg.group} - -"
214 "d /var/spool/nullmailer/tmp 770 ${cfg.user} ${cfg.group} - -"
217 systemd.services.nullmailer = {
218 description = "nullmailer";
219 wantedBy = [ "multi-user.target" ];
220 after = [ "network.target" ];
223 rm -f /var/spool/nullmailer/trigger && mkfifo -m 660 /var/spool/nullmailer/trigger
229 ExecStart = "${pkgs.nullmailer}/bin/nullmailer-send";
234 services.mail.sendmailSetuidWrapper = lib.mkIf cfg.setSendmail {
235 program = "sendmail";
236 source = "${pkgs.nullmailer}/bin/sendmail";