読者です 読者をやめる 読者になる 読者になる

tohokuaikiのチラシの裏

技術的ネタとか。

Confluenceのプラグイン開発を承ります。ご連絡はこちらのホームページからお願いいたします。

PostfixでMySQLのデータベースを覗いて転送する+ Virtual Domain

http://tohokuaiki.jp という会員サイトを何年も運営しているのですが、これのメール転送サービスというのをしたくなったのでその作業メモ。前提として、このサイトはROOT権限を持ってて*1MTAを使えること・・・です。

したいこと

この会員サイトは、部活なので毎年10人くらい登録ユーザーが増える。

自分は35期に入ったので、この会員制サイトで itoh@35.tohokuaiki.jp というメールアドレスを発行して、会員登録したメールアドレス先に転送してあげたい。

もちろん、いちいちユーザーアカウント追加とかそういうことはしないで全自動で。

DNSの解決

これは簡単で、

* IN CNAME tohokuaiki.jp.

としてやった。

Postfixで受け取るバーチャルドメインの追加

main.cfのmydestinationに毎年追加するとか疲れることはやりたくないわけです。

そこで使ったのが、virtual_alias_domains。毎年対応としては、1.tohokuaiki.jp ...., 52.tohokuaiki.jp, 53.tohokuaiki.jpとしていかなければならないので、

main.cfで

virtual_alias_domains = pcre:/etc/postfix/virtual_alias_domains

として、/etc/postfix/virtual_alias_domains には正規表現

/^[0-9]+\.tohokuaiki\.jp$/ dummy

とした。

このdummyというのが曲者で、これが無いとpostmapでDB化できない。

postmap: warning: virtual_alias_domains, line 2: expected format: key whitespace value

といわれてしまう。んー、どうしたら・・・と思ったらこのページ

この場合は、検索キーとしてドメインが登録されていれば、キーに対する値は何が登録されていても良い。

というのを理解して、なるほど・・・と思った。要するにKey=>Valueでvirtual_alias_domainsはその形式を要請されるわけだけど、この場合はHit下かどうかだけが知りたいので、そのValueのほうはどうでもいいのですね。

会員制サイトの会員データと連携

会員制裁とはXOOPSで作られている。したがって、PostfixMySQLルックアップを使ってやれば良いというのはすぐわかった。

このあたりからこの詳細記事に飛んで行ってmain.cfに

virtual_alias_maps = mysql:/etc/postfix/virtual_alias_maps_mysql_tohokuaiki

と指定して大体問題なくできたのだけど、2箇所引っかかった。

ローカルホストにつなぐときは、IP指定

これは、何かでも聞いたのだけど、MySQLはローカルにつなぎに行くときにlocahostで指定するとUnixソケットを使い、127.0.0.1で指定するとTCPでつなぎに行く。

で、どうやらPostfixUnixソケットでつなごうとするとダメらしい。ここはおとなしく、hosts=127.0.0.1 としておく。

検索Queryの%は%%で

additional_conditionsにLIKEを使った条件式を使ったら

fatal: db_common_parse: /etc/postfix/virtual_alias_maps_mysql_tohokuaiki: Invalid query template: SELECT ...

といわれてしまった。

ダブルクォートとかシングルクォートかなぁと思ったが、
http://nixforums.org/about168788-Postfix-MySQL----LIKE-in-SELECT.html
によると、%は%%で表現されると合って、日本語版じゃなくて英語版のPostfixマニュアルを見たら確かにそんな記述があった。

リロード必要?

SQLとかを書き換えた際は、postfix reloadをしないとどうもうまく反映されないことがあった。書き換えだけでうまくいくと思ってたので要注意。

最後に

XOOPS側でユーザー登録があった際に、このMail転送テーブルをちょいちょいと自動更新してやればいいのだけど、それはPHP側の問題でものすごく簡単な話なので割愛。