main
equa 2023-03-14 17:42:05 +00:00
commit de4607f946
3 changed files with 118 additions and 0 deletions

47
README.md 100644
View File

@ -0,0 +1,47 @@
# town mailing list manager
our little bespoke town engine. it runs on a janky procmail script
## setup
our system is very particular to running on public unix systems and probably
wouldn't be advisable for anything with external mail.
we have our local mail set up so that it's impossible to spoof the
envelope sender of an email with `local_login_sender_maps` in postfix;
the list handles this to make the emails look pretty and to evade spoofing
the software works on the assumption that everything lives in the home dir
of a user named `list`.
our list account needs two directories, `lists/` and `archive/`.
our scripts can autopopulate everything here, but you can also do manual
configuration in `lists/` to change access control to certain mailing lists.
copy procailrc to `~/.procmailrc` and set up `~/.forward` to filter all mail
through it:
```
|/usr/bin/procmail
```
if you want to have any special read-only mailing lists, you can populate
`lists/LISTNAME.senders` with a list of allowed senders, one on each line
a user can subscribe by naming the lists they want to subscribe to in a
`.townlists` file in their home directory
rather than checking these lists every post, we populate some internal
subscription lists with `make_lists.sh`, which should run on a cron job.
## assumptions
- mailing list names are `[a-z0-9_]{1,16}`
- we check this in the .townlists files and in sending
- everything lives in our home directory
- `lists/` and `archive/` directories exist
- usernames don't contain special characters
- i don't actually know which ones would be an issue
but town doesn't usually allow anything too crazy anyway
### subscriptions
- everyone we care about lives in /home and their usernames correspond to the directories
- list subscriptions are stored per-line in `.townlists`

15
make_lists.sh 100755
View File

@ -0,0 +1,15 @@
#!/bin/sh
rm -- "${HOME}/lists/"*.users.new
for listfile in /home/*/.townlists; do
user="$(basename "$(dirname "$listfile")")"
for x in $(grep '^[a-z0-9_]\{1,16\}$' "$listfile"); do
echo "$user" >> "${HOME}/lists/${x}.users.new"
done
done
rm -- "${HOME}/lists"/*.users
for i in "${HOME}/lists"/*.users.new; do
mv -- "$i" "$(dirname "$i")"/"$(basename "$i" .new)"
done

56
procmailrc 100644
View File

@ -0,0 +1,56 @@
# mailing list protocol!
# depends on a bunch of files in $HOME/lists --
# a "listname.users" containing all of the users
# and (optionally) a "listname.senders" if you want to restrict that
SHELL=/bin/sh
SENDMAIL=/usr/sbin/sendmail
LINEBUF=10000000
:0
* ^To:.*list\+\/[a-z0-9_]+@tilde\.town
LIST=| echo "$MATCH" | sed 's/@.*//' | sed 's/\(.\{16\}\).*/\1/' | tr '[:upper:]' '[:lower:]'
:0A
{
:0A
* ? [ -e ${HOME}/lists/${LIST}.users ]
RECIPIENTS=| cat ${HOME}/lists/${LIST}.users | tr '\n' ' '
:0E
{ RECIPIENTS="" }
}
# Extract envelope sender. Email addresses are actually very complex
# but we're on tilde.town so our email addresses aren't going to have spaces
:0A
* ^From \/[^ ]*
ENV_SENDER=|echo "$MATCH" | sed "s/ .*//"
:0A
ENV_USER=|echo "$ENV_SENDER" | sed "s/@.*//"
:0A
{
# If we have a restricted list of senders we should abort if it's not in there
:0A
* ? [ -e "${HOME}/lists/${LIST}.senders" ]
{
:0A
* !? grep -F "${ENV_USER}" "${HOME}/lists/${LIST}.senders"
# hack to quit procmailrc immediately (WHY)
{ EXITCODE=77 HOST= }
}
}
:0Af
| formail -a "X-Loop: list+${LIST}@tilde.town" -I "Reply-To: ${LIST} <list+${LIST}@tilde.town>" -I "From: ${ENV_SENDER}"
:0A
{
UMASK=003
:0c:
archive/${LIST}
}
:0A
! ${RECIPIENTS}