Postfix pipemap を使ってみる

こんにちは、masm11 です。

Postfix3 から、テーブルの種類が増えましたね。 inline, randmap, unionmap, pipemap ですね。

今回、pipemap を使うことで Postfix から PostgreSQL へのクエリを削減 できましたので、ご紹介します。

PostgreSQL へのクエリ

弊社サービス Re:lation は、メールの受信方法として、 「POP受信」と「転送受信」の2種類があります。 POP受信は、メールサーバに POP3 でアクセスしてメールを取得する方法です。 一方、転送受信は、fwd-xxxxxx などというメールアドレスにメールサーバから 転送することで受信する方法です。 今回は転送受信の方についての話になります。

fwd-xxxxxx はお客様によってまた受信箱によって異なり、たくさんあります。 中には解約もしくは受信箱削除等によって既に使えなくなったものもあります。 使えなくなったものをいつまでも処理するわけにはいきませんので、 メールが転送されてきた時に、その fwd-xxxxxx が生きているものかどうかを 判断する必要があります。そのために PostgreSQL にアクセスしています。 この時、pgsql テーブルを使用しています。

PostgreSQL にクエリを投げ、その結果として foo+fwd-xxxxxx (サンプル) が返るように してあります。そうすれば、メールはうちのサーバ上では foo というユーザ 宛に届きます。

しかし、このままではいろいろな文字列を PostgreSQL を使って変換しようとして しまいます。

  • fwd-xxxxxx
  • foo+fwd-xxxxxx
  • foo
  • From: ドメイン
  • ~.relationapp.jp

等々。

意図しているのは fwd-xxxxxxfoo+fwd-xxxxxx だけですが、 その他のいろいろなものについてクエリを PostgreSQL に投げては失敗しています。 めっちゃ無駄です。

memcache の利用

まず memcache を使う方法が思い浮かびます。

しかしこれはほとんど意味がありません。 Postfix の memcache 対応は、返り値がない場合にはキャッシュしてくれません。

foo+fwd-xxxxxxfoo に対応する値は存在しませんので、 これらについてのクエリを何度でも PostgreSQL に投げてしまいます。

(fwd-xxxxxxfoo+fwd-xxxxxx はキャッシュしてくれます)

pipemap の利用

そこで pipemap です。

pipemap は、pipemap:{type1:table1, type2:table2, ...} という書式で 書きます。こう書くことで、入力をまず type1:table1 に与え、 その出力を次は type2:table2 に与え、そうして最終的な出力を結果とします。 途中で出力がなかった場合は、そこで中断し、出力なしを結果とします。

なので、まず正規表現で文字列をチェックし、 それにパスした場合のみ pgsql に与えればいいわけです。

1つめは、regexp:test-fwd.regexp とし、test-fwd.regexp の中身は、

/^(fwd-.*)$/ $1

とします。2つめは、pgsql:forward-addresses.pgsql とし、 forward-addresses.pgsql の中身はこれまでどおりです(省略します)。

こうすることで、まず入力が fwd- で始まるかをチェックし、 その場合のみ PostgreSQL に投げることができます。 fwd- で始まらない場合は test-fwd.regexp からの出力がありませんので、 そこで pipemap 処理が中断され、PostgreSQL には投げられません。

これで PostgreSQL へのクエリが削減されました!