#!/bin/sh # # /usr/local/sbin/localmkpostfixvirtual # Copyright 2001-2002 Jonas Smedegaard # # $Id: localmkpostfixvirtual,v 1.20 2006-08-02 16:01:40 jonas Exp $ # # Generate virtual file for postfix # # Hints are stored in the "Other" field (using chfn). # # Each user should have space-separated hints like this: # "mailname1@ mailname2@mailgroup1 mailname3@mailgroup2 mailname4@maildomain7". # # The user of each mailgroup should have hints like "@domain1 @domain2" # for each hosted maildomain. # # Generate virtual file like this: # # # ( cd /etc/postfix && localmkpostfixvirtual > virtual.new && diff virtual virtual.new ) # # ..and if the changes are correct, activate the new virtual file: # # # ( cd /etc/postfix && mv virtual.new virtual && postmap virtual ) # # Optional: Several mailgroups can be tied together (when amount of hints # exceeds the limit of the "Other" field: List them all in # "Office" or "roomnumber" field of primary mailgroup (include the # primary mailgroup itself!). # # Optional: root can have hints like "postmaster@ hostmaster@ support@" # for default accounts tied to the sysadmin (default: "postmaster@"). # # Suggestion: Add mailgroup users like this: # adduser --system --no-create-home --group --disabled-password # # TODO: reuse getent requests (drastically improves speed) # TODO: Write command "members" as internal code # get_fullname_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $1}'; } get_roomnumber_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $2}'; } get_other_field() { getent passwd $1 | awk -F: '{print $5}' | awk -F, '{print $5}'; } get_groups() { groups $1 | sed -e 's/^.*: //' -e "s/\( \+\|^\)$1\( \+\|$\)/\1/"; } get_domain() { echo $1 | egrep "^@[\.[:alnum:]-]+$" | sed -e 's/@//'; } get_account() { echo $1 | egrep "^([\.[:alnum:]_-]+|\+)@($gid|$maildomain)?$" | sed -e 's/@.*//'; } sort_u() { for x in $@; do echo $x; done | sort -u; } print_accounts() { uid=$1 maildomain=$2 pre_text=$3 post_fallback_text=$4 test -n "$pre_text" && echo "$pre_text" uid_seen="" joker_seen="" for mailaccountchunk in `get_other_field $uid`; do for mailaccount in `get_account $mailaccountchunk`; do case $mailaccount in '+') if [ -z "$joker_seen" ]; then echo "@$maildomain $uid" joker_seen="$uid" else echo "#WARNING: Catch-all for $maildomain already set to $joker_seen: `get_fullname_field $uid`" fi ;; *) echo "$mailaccount@$maildomain $uid" ;; esac uid_seen=1 done done test -n "$post_fallback_text" -a -z "$uid_seen" && echo "$post_fallback_text" echo } loop="" if [ $# -lt 1 ]; then mailgroups="`members maildomains`" else mailgroups="$@" fi for mailgroup in $mailgroups; do for maildomainchunk in `get_other_field $mailgroup`; do for maildomain in `get_domain $maildomainchunk`; do if [ $loop ]; then echo echo "##################################################################" echo fi loop=true print_accounts root "$maildomain" "$maildomain VIRTUAL" "postmaster@$maildomain root" mailgroupowners="" mailusers="" mailgroupgroups="`get_roomnumber_field $mailgroup`" test -z "$mailgroupgroups" && mailgroupgroups="$mailgroup" for mailgroupgroup in $mailgroupgroups; do mailgroupowners="$mailgroupowners `members -p "$mailgroupgroup"`" mailusers="$mailusers `members -s "$mailgroupgroup"`" done # Do mailgroup owners (and don't warn if there's no addresses attached) for mailgroupowner in `sort_u $mailgroupowners`; do print_accounts $mailgroupowner "$maildomain" "# `get_fullname_field "$mailgroupowner"` (`get_groups "$mailgroupowner"`)" "" done # Do secondary mailgroup members for mailuser in `sort_u $mailusers`; do print_accounts "$mailuser" "$maildomain" "# `get_fullname_field "$mailuser"` (`get_groups "$mailuser"`)" "#WARNING: No addresses for $mailuser" done done done done