Postfixにて非ユーザー宛のメールを受信して任意のプログラムに渡す

メールでデータ入力できるWebアプリなどを作るときに、非ユーザー宛のメールを受信して任意のプログラムに渡したいことがある。そのときのやり方。Postfix正規表現によるエイリアス機能を使って実現する。

なお、このやり方だと私の環境ではユーザー宛(アカウントがあるユーザー宛)のメールがうまく受信できていない。

環境

なお、main.cfが書き換えられ、かつ、postfixの再起動ができる権限が必要。

main.cfの設定変更

まずは初期状態を確認する。

# postconf -d | grep ^local_recipient_maps
local_recipient_maps = proxy:unix:passwd.byname $alias_maps

# postconf -d | grep ^alias_maps
alias_maps = hash:/etc/aliases

# postconf -d | grep ^default_privs
default_privs = nobody

local_recipient_mapsで、どこ宛のメールであるならば受け付けるのかを設定している。デフォルトは、@の前が、アカウントがあるユーザー名とエイリアスに登録されている文字列。 alias_mapsで@の前の文字列をチェックするためのデータベース(ファイル)を指定している。デフォルトは/etc/aliases。default_privsで、エイリアスにマッチしたメールを処理するためのコマンドの実行者を指定している。

この3つのパラメーターを変更する。

% cd /etc/postfix
% sudo cp -p main.cf main.cf.org
% vi main.cf

以下のようにパラメータを変更する。

# postconf  | grep ^alias_maps
alias_maps = hash:/etc/aliases, regexp:/etc/postfix/application.regexp

# postconf  | grep ^local_recipient_maps
local_recipient_maps =

# postconf | grep ^default_privs
default_privs = 任意のユーザー名(新規ユーザを作るか、メールの処理プログラムのユーザにしておく)

正規表現によるエイリアスの記述場所である/etc/postfix/application.regexpを作成する。

% sudo touch application.regexp

postfixを再起動する。

% sudo postfix reload

受け入れメールアドレスの指定

/etc/postfix/application.regexp を編集する。たとえば、「数字4桁」-「英数字3文字」-d@foo.bar.jpというメールアドレスを受けとり、/tmp/mail-spool.txtというファイルに保存したければ以下のように記述する。ポイントは@の後ろが省略されることがあるので、「(@.*)?$」を記述すること。

/^[0-9]{4}-[0-9a-zA-Z]{3}-d(@.*)?$/ "| /bin/cat >> /tmp/mail-spool.txt"

これで、1234-abc-d@foo.bar.jp というメールを送ると /tmp/mail-spool.txt に保存される。ちゃんと動いているかは /var/log/mail.log で確認する。自分が作成したプログラムへ送りたい場合は「"| /bin/cat >> /tmp/mail-spool.txt"」のパイプの後ろを修正すればよい。このコマンドは default_privs で設定したユーザー権限で実行される。

しかし、このままだと上の正規表現に引っかからないメールはすべて "unknown user"としてエラーメールが送信者へ返ってしまう。スパムが多い現在あまり良い挙動でない。そこで、正規表現が上から評価されていくことを利用して、一番最後に何でも/dev/nullへ放り込む設定にする。つまり以下のように2行目を書き加える。

/^[0-9]{4}-[0-9a-zA-Z]{3}-d(@.*)?$/ "| /bin/cat >> /tmp/mail-spool.txt"
/^.*(@.*)?$/ /dev/null

これで、1234-abcd-e@foo.bar.jp というメールを送ると、このメールは /dev/nullへ直行するようになる。直行しているかどうかは、/var/log/mail.log で確認する。