特定グループに所属するユーザにメールを配送する

ホスト内のユーザ全員宛てにメールを送る方法 - 101回目のコンパイルにてホスト内のユーザ全員にメールを送信する方法を紹介しました。
今日はもう少し送信する範囲を限定するため、グループに所属するユーザ全員にメールが配送される、いうなれば「グループ同報」とでも言うべき方法を考えてみました。

使用するMTAは前回同様、postfixを想定しています。以下の図のような流れで処理されます。(図中のpostfixコンポーネントはところどころ不正確な部分があると思いますが、ご容赦ください)

ここではあるグループ "hoge" に所属するグループ宛の送信先を "group-hoge" として話を進めます。この宛先は /etc/postfix/aliases.reg の記載する正規表現で変更できます。

  1. "group-hoge"宛てに送信されたメールはpostfixのlocalというコンポーネントに渡されます。
  2. localコンポーネントはaliasの情報を元に配送先を決定します。今回は特定のエイリアスではなく、group-xxxの形式の宛先を持つ物を処理させたいので正規表現エイリアスマップを使用します。
  3. エイリアスマップによって mail2groups.sh というプログラムに送られたメールは宛先情報からグループ名を取得し、対象のグループに所属するユーザに対してメールを個別に配送します。
  4. mail2groups.sh から sendmail コマンドに渡されたメールが個別のユーザに配送されます。

関係するファイルとその中身や編集内容は以下の通りです。

alias_maps = hash:/etc/aliases
    ↓
alias_maps = hash:/etc/aliases, regexp:/etc/postfix/aliases.reg
  • /etc/postfix/aliases.reg (新規)
/^group-.+(@.*)?$/ "|/bin/bash /usr/local/lib/mail2groups.sh"
  • /usr/local/lib/mail2groups.sh (新規)
#!/bin/bash

USERID_MIN=500
USERID_MAX=29999


function isGroupOf()
{
    if [ ${#} -lt 2 -o -z "${2}" ]
    then
        false
        return
    fi
    
    if [ -n "`groups ${1} | awk -F: '{printf \$2}' | grep ${2}`" ]
    then
        true
    else
        false
    fi
}

declare -i USERID=0
TO=""
WILL_BE_SENT=0

while read USER_ENT
do
    USERID="`echo ${USER_ENT} | awk -F: '{print \$3;}'`"
    if [ ${USERID_MIN} -le ${USERID} -a ${USERID} -le ${USERID_MAX} ]
    then
        USERNAME="`echo ${USER_ENT} | awk -F: '{print $1;}'`"
        RCPT_GROUPNAME="${LOCAL#group-}"
        isGroupOf "${USERNAME}" "${RCPT_GROUPNAME}"
        if [ ${?} -eq 0 ]
        then
            TO="${TO} `echo "${USER_ENT}" | awk -F: '{printf $1;}'`"
            WILL_BE_SENT=1
        fi
    fi
done </etc/passwd

if [ ${WILL_BE_SENT} -ne 0 ]
then
    /usr/lib/sendmail $@ ${TO}
else
    # Undelivered Mail by "unknown user"
    exit 67
fi

全てのファイルの準備ができたら /etc/init.d/postfix reload を実行してpostfixをリロードします。
これでユーザグループ宛てのメール送信ができるようになっているはずです。

ちなみに「特定のグループに所属するユーザの一覧」を一度に取得する方法が見当たらなかったため、上記の /usr/local/lib/mail2groups.sh では一般ユーザのUID上限と下限を仮定してその範囲のユーザ全員に対してグループ所属の判定をしているため効率が悪いです。もしそのそういう判定をコマンド一発とかでできる方法をご存知の方がいれば教えていただけると幸いです。