技術日記
さくらVPS+CentOS+PHPでCatchAllなメール受信Edit

試しにやってみたらやたらとはまったのでメモ。

さくらのVPSに適当なバーチャルホスト(foo.example.com)を割り振り、そのバーチャルホスト宛に届いたすべてのメール(*@foo.example.com)をPHPスクリプトで受信したい。

CatchAllじゃないんだったら、受信したいアカウントの.forwardとかからスクリプトを呼び出せばいいんだけど、CatchAllとなるとまず受信したいアカウントというものが存在しないわけで、その辺から設定する必要がある。

具体的には、まず適当な受信用のアカウント(mailreciever)を用意する。

[sourcecode language="plain"] useradd -s /sbin/nologin mailreciever [/sourcecode]

で、そのアカウントとバーチャルホストのCatchAll転送先を結びつける。まずはバーチャルホストをsendmailが受信するドメインとして追加するために、/etc/mail/local-host-namesに以下を追加。

[sourcecode language="plain"] foo.example.com [/sourcecode]

そして、そのドメインのCatchAll転送先としてmailrecieverアカウントを登録するために、/etc/mail/virtualusertableに以下を追加。

[sourcecode language="plain"] @foo.example.com mailreciever [/sourcecode]

virtualusertableはコンパイルが必要なので、

[sourcecode language="plain"] yum install sendmail-cf # 必要ならば makemap hash /etc/mail/virtualusertable.db < /etc/mail/virtualusertable [/sourcecode]

mailrecieverアカウントに受信したときにPHPスクリプト(/path/to/script.php)を実行するように/etc/aliasesに以下を追加。

[sourcecode language="plain"] mailreciever: "|/usr/bin/php /path/to/script.php" [/sourcecode]

というのは実はうまく動かなかった。smrsh環境の制約に引っかかるらしい。そこで、

[sourcecode language="plain"] ln -s /usr/bin/php /etc/smrsh/php [/sourcecode]

のように/etc/smrshディレクトリ内にPHPのCLIバイナリのシンボリックリンクを作っておいて、先ほど書いた/etc/aliasesの内容を、

[sourcecode language="plain"] mailreciever: "|/etc/smrsh/php /path/to/script.php" [/sourcecode]

と変更するとsmrsh環境が原因のエラーを回避できる。

ちなみに/etc/aliasesもコンパイルが必要なので、

[sourcecode language="plain"] newaliases [/sourcecode]

を実行してコンパイルしておく。

これでlocalhost上で*@foo.example.com宛てのメールを送ると、ちゃんと/path/to/script.phpが起動できるようになったのだが、外部からメールを送ってもちゃんと着信していない。

ああ、もちろんそれ以前に、foo.example.comのドメインを該当サーバーのIPアドレスでDNS登録しておく必要があるけど、そういう問題ではない。

あと、自分でセットしたソフトウェアファイアウォールで25ポートINがふさがっているのかと思ったりもしたが、それもない。さくらインターネットが25ポートINを外側でふさいでいるのかと思ったのだが、それでもない。

正解は、さくらVPS+CentOSでインストールされるsendmailのデフォルト設定は、localhostからのSMTPしか受信しないようになっている、だった。

sendmail.cfには触らないと心に誓っているんで、あきらめてpostfixにでも入れ直そうかと思ったんだけど、ググってみたらそれほど設定変更は大変そうじゃなかったんで、sendmailのまま設定を変えて対応した。

/etc/mail/sendmail.mcの

[sourcecode language="plain"] DAEMON_OPTIONS('Port=smtp,Addr=127.0.0.1, Name=MTA')dnl [/sourcecode]

という行をコメントアウトして、

[sourcecode language="plain"] dnl # DAEMON_OPTIONS('Port=smtp,Addr=127.0.0.1, Name=MTA')dnl [/sourcecode]

に変更し、

[sourcecode language="plain"] m4 /etc/mail/sendmail.mc /etc/mail/sendmail.cf [/sourcecode]

でコンパイルしてからsendmailを再起動したら、無事外部からのSMTP接続も受信してくれるようになり、foo.example.com宛てのすべてのエールを/path/to/script.phpで処理できるようになった。

なんかものすごくはまりどころが多かった。

Published At2011-12-19 23:22Updated At2011-12-19 23:22