commit 990faa37a29c3cde5e0f48336e712c6ad71c5fa4 from: Omar Polo date: Sun Jun 06 08:59:06 2021 UTC initial commit commit - /dev/null commit + 990faa37a29c3cde5e0f48336e712c6ad71c5fa4 blob - /dev/null blob + 4e1fee443717b12634573d8c7ead23e2a1ff37d7 (mode 755) --- /dev/null +++ sync-userdb @@ -0,0 +1,36 @@ +#!/bin/sh + +set -e + +# On OpenBSD these are only /etc/mail/… +./userctl aliases > /usr/local/etc/mail/aliases +./userctl virtuals > /usr/local/etc/mail/virtuals +./userctl domains > /usr/local/etc/mail/domains +./userctl users > /usr/local/etc/mail/passwd + +./userctl users.passwd > /usr/local/etc/dovecot/users + +m() +{ + if [ ! -d "$1" ]; then + mkdir "$1" + chown vmail:vmail "$1" + fi +} + +# ensure the maildirs exists +for dir in $(./userctl users.mdirs); do + homedir=$(dirname "$dir") + domdir=$(dirname "$homedir") + + m "$domdir" + m "$homedir" + m "$dir" +done + +# eventually add something like +# service dovecot restart +# service smtpd restart +# for FreeBSD or +# rcctl restart dovecot smtpd +# for OpenBSD. blob - /dev/null blob + 2242e9676b5a4c2afb64f0170794d39c051c7a94 (mode 755) --- /dev/null +++ userctl @@ -0,0 +1,40 @@ +#!/bin/sh + +if [ ! -f "userctl.awk" ]; then + echo "Can't find userctl.awk!" >&2 + exit 1 +fi + +if [ ! -f "userdb" ]; then + echo "Can't find userdb!" >&2 + exit 1 +fi + +# run +run() +{ + awk -f userctl.awk -v action="$1" userdb +} + +case "$1" in + aliases) run "aliases" ;; + virtuals) run "virtuals" ;; + domains) run "domains" ;; + users) run "users" ;; + users.passwd) run "users.passwd" ;; + users.mdirs) run "users.mdirs" ;; + help) + echo "USAGE: $0 " + echo "where action is one of" + echo " - aliases" + echo " - virtuals" + echo " - domains" + echo " - users" + echo " - users.passwd" + echo " - users.mdirs" + ;; + *) + echo "Unknown action $1" >&2 + exit 1 + ;; +esac blob - /dev/null blob + e2508111640881847ba987c5a6d714afcd4031d0 (mode 644) --- /dev/null +++ userctl.awk @@ -0,0 +1,79 @@ +#!/usr/bin/env awk + +# expects action to be defined, like -v action=aliases + +/^[[:space:]]*$/ { next } +/^[[:space:]]*#/ { next } + +/:$/ { + # drop the : + gsub(":", "", $1); + domain = $1; + domains[domainslen++] = domain; + next; +} + +$1 == "user" { + user = sprintf("%s@%s", $2, domain); + users[user] = $3 + + # change “vmail” to match the local user that + # delivers the mail + aliases[user] = "vmail"; + next; +} + +$1 == "alias" { + if ($3 != "") { + target = $3; + } else { + target = user; + } + + if (domain != "") { + alias = sprintf("%s@%s", $2, domain); + } else { + alias = $2; + } + aliases[alias] = target; +} + +# output in the correct format +END { + if (action == "aliases") { + for (alias in aliases) { + if (match(alias, "@")) + continue; + printf("%s: %s\n", alias, aliases[alias]); + } + } else if (action == "virtuals") { + for (alias in aliases) { + if (!match(alias, "@")) + continue; + printf("%s %s\n", alias, aliases[alias]); + } + } else if (action == "domains") { + for (domain in domains) { + printf("%s\n", domains[domain]); + } + } else if (action == "users") { + for (user in users) { + printf("%s %s\n", user, users[user]); + } + } else if (action == "users.passwd") { + for (user in users) { + # user@doma.in:hash:::::: + # user@doma.in:hash::::::userdb_quota_rule=*:storage=1G + printf("%s:%s::::::\n", user, users[user]); + } + } else if (action == "users.mdirs") { + for (user in users) { + split(user, m, "@"); + # adjust the maildir path + printf("/var/vmail/%s/%s/Maildir\n", m[2], m[1]); + } + } else { + print "unknown action!\n" > "/dev/stderr" + exit 1 + } +} blob - /dev/null blob + 4de2010aed3ade02bf2b912a1a31d33c326ed9a2 (mode 644) --- /dev/null +++ userdb.sample @@ -0,0 +1,18 @@ +example.com: + # Indentation is optional, but improves legibility. + # The following defines the user op@example.com; + # is the hash of the password computed + # with `smtpctl encrypt` + user op + # and define an arbitrary number of aliases + alias service1 + alias other-alias + + user otheruser + + # aliases can be to virtual users on other hosts + alias abuse someone@example2.com + +example2.com: + user someone + # …