1 { config, lib, pkgs, ... }:
7 concatMapLines = f: l: lib.concatStringsSep "\n" (map f l);
9 cfg = config.services.mlmmj;
10 stateDir = "/var/lib/mlmmj";
11 spoolDir = "/var/spool/mlmmj";
12 listDir = domain: list: "${spoolDir}/${domain}/${list}";
13 listCtl = domain: list: "${listDir domain list}/control";
14 transport = domain: list: "${domain}--${list}@local.list.mlmmj mlmmj:${domain}/${list}";
15 virtual = domain: list: "${list}@${domain} ${domain}--${list}@local.list.mlmmj";
16 alias = domain: list: "${list}: \"|${pkgs.mlmmj}/bin/mlmmj-receive -L ${listDir domain list}/\"";
17 subjectPrefix = list: "[${list}]";
18 listAddress = domain: list: "${list}@${domain}";
19 customHeaders = domain: list: [ "List-Id: ${list}" "Reply-To: ${list}@${domain}" ];
20 footer = domain: list: "-- \nTo unsubscribe send a mail to ${list}+unsubscribe@${domain}";
22 let ctlDir = listCtl d l; in
24 for DIR in incoming queue queue/discarded archive text subconf unsubconf \
25 bounce control moderation subscribers.d digesters.d requeue \
28 mkdir -p '${listDir d l}'/"$DIR"
30 ${pkgs.coreutils}/bin/mkdir -p ${ctlDir}
31 echo ${listAddress d l} > '${ctlDir}/listaddress'
32 [ ! -e ${ctlDir}/customheaders ] && \
33 echo "${lib.concatStringsSep "\n" (customHeaders d l)}" > '${ctlDir}/customheaders'
34 [ ! -e ${ctlDir}/footer ] && \
35 echo ${footer d l} > '${ctlDir}/footer'
36 [ ! -e ${ctlDir}/prefix ] && \
37 echo ${subjectPrefix l} > '${ctlDir}/prefix'
39 customHeaderOptions = {
43 value = lib.mkOption {
48 mailingListConfig = config: {
50 use_template = lib.mkDefault config.useTemplate;
51 recursive = lib.mkDefault config.recursive;
52 process_children_only = lib.mkDefault config.processChildrenOnly;
69 description = "Enable mlmmj";
75 description = "mailinglist local user";
81 description = "mailinglist local group";
84 listDomain = mkOption {
86 default = "localhost";
87 description = "Set the mailing list domain";
90 mailLists = mkOption {
91 type = types.listOf types.str;
93 description = "The collection of hosted maillists";
96 maillists = lib.mkOption {
97 type = types.attrsOf (types.submodule (domain: {
99 type = types.attrsOf (types.submodule (list: {
101 customHeaders = lib.mkOption {
102 type = types.listOf customHeaderOptions;
104 "List-Id: ${list.name}"
105 "Reply-To: ${list.name}@${domain.name}"
107 description = "Custom headers.";
109 footer = lib.mkOption {
111 default = "-- \nTo unsubscribe send a mail to ${list.name}+unsubscribe@${domain.name}";
112 description = "Text to be added as a footer to the mails' body.";
114 lang = lib.mkOption {
115 type = types.enum ["ast" "cs" "de" "en" "fi" "fr" "gr" "it" "pt" "sk" "zh-cn"];
117 description = "Language of the templates.";
119 subjectPrefix = lib.mkOption {
121 default = "[${list.name}]";
122 description = "String added as a prefix to the Subject header.";
125 config = mailingListConfig config;
130 description = "Mailing-lists.";
133 maintInterval = mkOption {
137 Time interval between mlmmj-maintd runs, see
138 <citerefentry><refentrytitle>systemd.time</refentrytitle>
139 <manvolnum>7</manvolnum></citerefentry> for format information.
147 description = "Configure postfix to use mlmmj as a transport";
155 ###### implementation
157 config = mkIf cfg.enable {
159 users.users.${cfg.user} = {
160 description = "mlmmj user";
163 uid = config.ids.uids.mlmmj;
165 useDefaultShell = true;
168 users.groups.${cfg.group} = {
169 gid = config.ids.gids.mlmmj;
172 services.postfix = mkIf cfg.postfix.enable {
174 recipientDelimiter= "+";
175 masterConfig.mlmmj = {
184 "user=${cfg.user}:${cfg.group}"
185 "argv=${pkgs.mlmmj}/bin/mlmmj-receive"
188 "${spoolDir}/$nexthop"
192 extraAliases = lib.concatMapStringsSep "\n" (alias cfg.listDomain) cfg.mailLists;
195 propagate_unmatched_extensions = ["virtual"];
196 mlmmj_destination_recipient_limit = "1";
199 virtual = lib.concatMapStringsSep "\n" (virtual cfg.listDomain) cfg.mailLists;
200 transport = lib.concatMapStringsSep "\n" (transport cfg.listDomain) cfg.mailLists;
203 environment.systemPackages = [ pkgs.mlmmj ];
205 system.activationScripts.mlmmj = ''
206 ${pkgs.coreutils}/bin/mkdir -p ${stateDir} ${spoolDir}/${cfg.listDomain}
207 ${lib.concatMapStringsSep "\n" (createList cfg.listDomain) cfg.mailLists}
208 ${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${spoolDir}
211 systemd.services.mlmmj-maintd = {
212 description = "mlmmj maintenance daemon";
216 ExecStart = "${pkgs.mlmmj}/bin/mlmmj-maintd -F -d ${spoolDir}/${cfg.listDomain}";
220 systemd.timers.mlmmj-maintd = {
221 description = "mlmmj maintenance timer";
222 timerConfig.OnUnitActiveSec = cfg.maintInterval;
223 wantedBy = [ "timers.target" ];