From 7d2158a75b6ff294146444a6e1b51170d3f43010 Mon Sep 17 00:00:00 2001 From: Malfurious Date: Fri, 14 Jun 2024 23:21:59 -0400 Subject: mlmmj: Integration with postfix Incoming mail for an mlmmj list is caught by a virtual mapping and directed via virtual transport to the mlmmj system for processing. Outgoing mail is implicitly allowed since it originates from the localhost. The postfix entrypoint script now dynamically generates these mailing list mappings on startup from data in the mlmmj spool directory, so user configuration is minimal. In addition, the script will now sync the user's mailing list parameters into the spool directory, thus automatically creating new lists and deleting old ones. The list creation logic is implemented in a new script `make_list.sh`. This is made necessary as the mlmmj built in tooling for this must be run interactively, so we duplicate the logic. This is separate from `entrypoint.sh` mainly because we need to drop privileges to the mlmmj user while creating files. Signed-off-by: Malfurious --- Dockerfile | 1 + postfix/entrypoint.sh | 45 +++++++++++++++++++++++++++++++++++++-------- postfix/main.cf | 6 +++++- postfix/make_list.sh | 13 +++++++++++++ postfix/master.cf | 2 ++ 5 files changed, 58 insertions(+), 9 deletions(-) create mode 100755 postfix/make_list.sh diff --git a/Dockerfile b/Dockerfile index 55e2c07..55b4e01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,7 @@ RUN apt update \ mlmmj \ postfix \ postfix-pcre \ + sudo \ && apt clean # Install files diff --git a/postfix/entrypoint.sh b/postfix/entrypoint.sh index 46c06ab..afea241 100755 --- a/postfix/entrypoint.sh +++ b/postfix/entrypoint.sh @@ -1,18 +1,47 @@ #!/bin/sh -# Generate virtual mappings from user password file +users() { + sed 's/:.*$//g' /etc/userconfig/passwd +} + +## Generate virtual mappings from user password file # Incoming mail: "user@domain domain/user/" >vmailbox -# (The trailing slash indicates the directory is a maildir.) -sed 's/:.*$//g' /etc/postfix/vmailbox +# Outgoing mail: "user@domain user@domain" >vaddress +users | awk -F '@' '{printf "%s %s/%s/\n", $0, $2, $1}' >/etc/postfix/vmailbox +users | awk '{printf "%s %s\n", $0, $0}' >/etc/postfix/vaddress + +## Synchronize mailing list configuration directories +eul=$(ls /etc/userconfig/lists | sed '/ /d') # Ignore spaces and dotfiles +vsl=$(ls -A /var/spool/mlmmj) +added=$(printf '%s\n' "$vsl" "$vsl" "$eul" | sort | uniq -u) +removed=$(printf '%s\n' "$eul" "$eul" "$vsl" | sort | uniq -u) + +for list in $added; do + sudo -u mlmmj /etc/postfix/make_list.sh "$list" +done +for list in $removed; do + listdir="/var/spool/mlmmj/$list" + rm -rf "$listdir" + printf 'Deleted list directory: %s\n' "$listdir" +done -# Outgoing mail: "user@domain user@domain" >vaddress -sed 's/:.*$//g' /etc/postfix/vaddress +## Generate virtual mappings from mailing list addresses +# "address@domain list@localhost.mlmmj" >mlvirtual +# "list@localhost.mlmmj mlmmj:list" >mltransport +touch /etc/postfix/mlvirtual +touch /etc/postfix/mltransport +for list in $(ls -A /var/spool/mlmmj); do + address="/var/spool/mlmmj/$list/control/listaddress" # there could be multiple + sed "s/$/ $list@localhost.mlmmj/g" <$address >>/etc/postfix/mlvirtual + echo "$list@localhost.mlmmj mlmmj:$list" >>/etc/postfix/mltransport +done -# Generate Berkeley DB files +## Generate Berkeley DB files +postmap /etc/postfix/mltransport +postmap /etc/postfix/mlvirtual postmap /etc/postfix/vaddress postmap /etc/postfix/vmailbox postmap /etc/userconfig/aliases +## Execute postfix daemons exec /usr/sbin/postfix start-fg diff --git a/postfix/main.cf b/postfix/main.cf index 7ded588..7f701a8 100644 --- a/postfix/main.cf +++ b/postfix/main.cf @@ -53,4 +53,8 @@ virtual_uid_maps = static:2000 virtual_gid_maps = static:2000 virtual_mailbox_limit = 0 -virtual_alias_maps = hash:/etc/userconfig/aliases +# Mlmmj mailing list parameters +mlmmj_destination_recipient_limit = 1 +transport_maps = hash:/etc/postfix/mltransport + +virtual_alias_maps = hash:/etc/userconfig/aliases hash:/etc/postfix/mlvirtual diff --git a/postfix/make_list.sh b/postfix/make_list.sh new file mode 100755 index 0000000..45a198e --- /dev/null +++ b/postfix/make_list.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +mkdir -p "/var/spool/mlmmj/$1" +cd "/var/spool/mlmmj/$1" + +mkdir -p incoming queue queue/discarded archive subconf unsubconf bounce \ + moderation subscribers.d digesters.d requeue nomailsubs.d + +touch index +ln -s "/etc/userconfig/lists/$1" control +ln -s /etc/userconfig/listtext text + +printf 'Created list directory: %s\n' "$(pwd)" diff --git a/postfix/master.cf b/postfix/master.cf index 935dbec..3511856 100644 --- a/postfix/master.cf +++ b/postfix/master.cf @@ -65,6 +65,8 @@ postlog unix-dgram n - n - 1 postlogd # agent. See the pipe(8) man page for information about ${recipient} # and other message envelope options. # ==================================================================== +mlmmj unix - n n - - pipe + flags=ORhu user=mlmmj argv=/usr/bin/mlmmj-receive -F -L /var/spool/mlmmj/${nexthop} # # maildrop. See the Postfix MAILDROP_README file for details. # Also specify in main.cf: maildrop_destination_recipient_limit=1 -- cgit v1.2.3