どさどさにっき(夏) 〜2008年9月中旬〜

by やまや
<< = >>

2008年9月11日(木)

smtp_bind_address を変えてメールを送る(たぶん完結編)

_ 送信者アドレスによって送信に使う IP アドレスを分離する件。試してみた。

_ このアイデアのキモであるエンベロープ書き換え。from: hoge@example.com, to: fuga@example.net のメールを、to: fuga+example.com@example.net に書き換えるところ。でも、よくよく考えてみたら、こんなことできねーよ。from のアドレスに依存して異なる to に書き換えるなんて芸当はムリ。ダメじゃん。

_ 内蔵機能でできないのならば外部の機能でやるしかない。エンベロープの書き換えだけをやる コンテンツフィルタを作るよ。

_ こんなフィルタスクリプトを書く。あくまで動作検証用であっていろいろ手抜きしてるので、実際の運用に耐えるシロモノではない。間違ってもそのまま使ってはいけない。

#!/bin/sh
sender="$1"
senderdomain=`expr "$1" : '.*@\(.*\)'`
shift
for i in "$@"; do
    rcptlocal=`expr "$i" : '\(.*\)@.*'`
    rcptdomain=`expr "$i" : '.*@\(.*\)'`
    rcpt="$rcpt $rcptlocal+$senderdomain@$rcptdomain"
done
exec /usr/sbin/sendmail -f "$sender" -- $rcpt
んで、postfix からこのスクリプトを呼び出す設定と、その他いろいろ設定。
-- master.cf
filter    unix  -       n       n       -       10      pipe
    flags=q user=filter argv=/path/to/filter.sh ${sender} ${recipient}
pickup    fifo  n       -       n       60      1       pickup
    -o content_filter=

smtp-192.0.2.1      unix  -       -       n       -       -       smtp
    -o smtp_bind_address=192.0.2.1
smtp-192.0.2.2      unix  -       -       n       -       -       smtp
    -o smtp_bind_address=192.0.2.2

-- main.cf
content_filter = filter:dummy
transport_maps = pcre:/etc/postfix/transport.pcre
smtp_generic_maps = pcre:/etc/postfix/generic.pcre
append_at_myorigin = no

-- transport.pcre
/\+example\.com@[^@]*$/		smtp-192.0.2.1:
/\+example\.jp@[^@]*$/		smtp-192.0.2.2:

-- generic.pcre
/^(.*)\+[^@]*@([^@]*)$/		$1@$2

_ content_filter で宛先アドレスを書き換える。書き換え後の宛先を見て、正規表現で transport を選択する。最後に generic_maps で書き換えた宛先を元に戻す。元に戻したアドレスに対してなぜか @$myorigin が補完されてしまうので(原因は追っていない)、これをやめさせる設定を追加しておく。

_ で、期待どおり動きました。ぱちぱちぱち。が、めんどくせー。エンベロープの書き換えしかしないのにメール本体全部やりとりしなきゃいかんからパフォーマンスも悪いし。ここまで苦労してやる価値はないだろ。ムダムダムダ。

_ こんな方法ではなく、milter でやればエンベロープのやりとりだけで完結するものが作れるんじゃないかな、たぶん。たったこれだけのアドレス書き換えをやるために milter を書くというのもずいぶんおおげさだと思うけれど。

_ エンベロープのみを扱える外部スクリプトということで、 access policy deligationを使うことも考えたけど、ダメだった(実際に試して失敗した)。REDIRECT な結果を返せばいいかと思ったけど、RCPT TO が複数あった場合にひとつしか指定されていないのと同じになってしまう。結果的に、ひとりにしかメールは届かず、残りは虚空に消える。本質的に転送であって書き換えじゃないからしかたない。qmail みたいに事前に RCPT TO をひとつずつにバラしておけば、この方法でも失われずにぜんぶ届くと思うけど、それはちょっと。

_ ちなみに、ここまであくまでひとつの postfix で完結させることを前提にやってきたけど、複数のインスタンスを起動するなら、こんなめんどくさいことは必要ない。使いたい IP アドレスごとにそれぞれ専用のインスタンスを起動しておいて、sender_dependent_relayhost_maps を使ってそれぞれのインスタンスにリレーすればいいだけ。使いたい IP アドレスがせいぜい5個とかその程度ならばこれで十分だろう。50個とか100個とかになるとそれだけのインスタンスをいちいち起動してられなくなるが、そんなに IP アドレスを使いわけることなんかふつーはないだろうし。

_ つーか、ソースいじるのがいちばん手っ取り早いかも。


2008年9月12日(金)

無題

_ コンビニで FRISK が1個100円で安売りしてた。箱買いしてきた。うまー。


<< = >>
やまや