James君!〜config.xml のパイプライン

spoolmanager ブロック in config.xml

で、これらの Matcher & Mailet が、

<mailet match="RelayLimit=30" class="Null"/>

のようなかたちで使われていることに「アレ??」と感じた読者もいよう。要するにこういった「RelayLimit」や「Null」はクラス名(それぞれ、org.apache.james.transport.mailets.Null, org.apache.james.transport.matchers.RelayLimit)なのだが、いわゆる「FQCN」(Fully Qualified Class Name:完全修飾クラス名)ではない。じゃあ、「パッケージ名」はどうなるのか....というと、これは config.xml では分けて別に指定するのである。ちょいと一般的なやり方と異なるので、最初は?となるのではなかろうか。

まあ、ここらへんをまとめて指定するのが、config.xml の spoolmanager ブロックである。spoolmanager ブロックは、

config --- spoolmanager -+-- threads
                         +-- mailetpackages --* mailetpackage
                         +-- matcherpackages --* matcherpackage
                         +-* processor --* mailet --* 各自設定要素

という構造になっている。先ほどの「Mailet & Matcher のパッケージ指定」は、mailetpackages, matcherpackages ブロックのそれぞれに、mailetpackage, matcherpackage タグで書くことになる。まあ、フツーはこんなところか。

   <spoolmanager>
      <!-- Number of spool threads -->
      <threads> 10 </threads>

      <!-- Set the Java packages from which to load mailets and matchers -->
      <mailetpackages>
         <mailetpackage>org.apache.james.transport.mailets</mailetpackage>
         <mailetpackage>自分が開発するMailetのパッケージ名</mailetpackage>
      </mailetpackages>
      <matcherpackages>
         <matcherpackage>org.apache.james.transport.matchers</matcherpackage>
         <matcherpackage>自分が開発するMatcherのパッケージ名</matcherpackage>
      </matcherpackages>
      <processor name="root">
        ............
      </processor>
   </spoolmanager>

パイプライン・プロセッサ

で問題は、「<processor>」タグである。要するにこの中に mailetタグを書いていくのだが、これはいくつでも書いていけるものだ。しかも、「○○の場合は...」というような場合分け的なフローをつくり出すことさえ出来てしまう。まあ、これは一種の「パイプライン」になっていて、「パイプラインが尽きるまで」順に処理されていく...と考えるのがまず良いだろう。

本質的には mailet は「メールを処理する」わけだが、問題を複雑にするのは、特殊な制御目的の mailet があることである。これらが「パイプライン」を作り上げる重要な役割を果たす。

Null mailet などの [終了] Mailet
これらの Mailet は積極的にメールを「握りつぶす」。[終了] と Mailet 一覧で示した Mailet は、パイプラインを終了させる副作用を持つので、そこでパイプラインが終了する。
ToProcessor mailet
mailet タグの子要素となる processor タグで指定される processor に分岐する。言い替えるとサブフローへ分岐させる、という重要な役割を果たす。

デフォルトの config.xml では、次の processor が定義されている。

root
入口に当たる processor
error
何かエラーが起きた場合に分岐する。error processor は明示的な ToProcessor の呼び出しだけではなく、内部的なエラーが起きた時に自動的に分岐する。
transport
非スパムメールのみの処理
spam
スパムメールの場合に分岐
local-address-error
エラーでも特に宛先が James にない場合に分岐
relay-denied
宛先が外部アドレスの場合に分岐。要するにリレーを試みたケースであり、エラーにすべきである。

では、これらの processor がどういうパイプラインで流れてくるのか、をまとめることにしよう。まず、コメント類を抜き、各Mailetに応じたサブエレメントは最小限にして示す。

 <processor name="root">
    <mailet match="RelayLimit=30" class="Null"/>
    <!-- query.bondedsender.org はホワイトリスト -->
    <mailet match="InSpammerBlacklist=query.bondedsender.org"
            class="ToProcessor">
      <processor> transport </processor>
    </mailet>

    <!-- dnsbl.njabl.org はブラックリスト -->
    <mailet match="InSpammerBlacklist=dnsbl.njabl.org"
            class="ToProcessor">
      <processor> spam </processor>
      <notice>550 Requested action not taken: rejected - see http://njabl.org/ </notice>
    </mailet>

    <!-- relays.ordb.org はブラックリスト -->
    <mailet match="InSpammerBlacklist=relays.ordb.org"
            class="ToProcessor">
      <processor> spam </processor>
      <notice>550 Requested action not taken: rejected - see http://www.ordb.org/ </notice>
    </mailet>

    <mailet match="All" class="ToProcessor">
       <processor> transport </processor>
    </mailet>
 </processor>

 <processor name="error">
    <mailet match="All" class="ToRepository">
       <repositoryPath> file://var/mail/error/</repositoryPath>
    </mailet>
 </processor>

 <processor name="transport">
    <mailet match="RecipientIsLocal" class="LocalDelivery"/>
    <mailet match="HostIsLocal" class="ToProcessor">
       <processor> local-address-error </processor>
       <notice>550 - Requested action not taken: no such user here</notice>
    </mailet>

    <mailet match="RemoteAddrNotInNetwork=127.0.0.1" class="ToProcessor">
       <processor> relay-denied </processor>
       <notice>550 - Requested action not taken: relaying denied</notice>
    </mailet>

    <mailet match="All" class="RemoteDelivery">
       <outgoing> file://var/mail/outgoing/ </outgoing>
       <delayTime>  5 minutes </delayTime>
       
    </mailet>
 </processor>

 <processor name="spam">
    <mailet match="All" class="ToRepository">
       <repositoryPath>file://var/mail/spam/</repositoryPath>
    </mailet>
 </processor>

 <processor name="local-address-error">
    <mailet match="All" class="ToRepository">
       <repositoryPath> file://var/mail/address-error/</repositoryPath>
    </mailet>
 </processor>

 <processor name="relay-denied">
    <mailet match="All" class="ToRepository">
       <repositoryPath>file://var/mail/relay-denied/</repositoryPath>
    </mailet>
 </processor>

パイプラインの流れ図

これを図にまとめると次のようになる。

|root|
  |
RelayLimit: Null
  |
InSpammerBlackList ---------------+--->|transport|
  |                               |         |
InSpammerBlackList -+->|spam|    |    RecipientIsLocal
  |                 |    |        |     :LocalDelivery
InSpammerBlackList -+    |        |         |
  |                     All       |      HostIsLocal ---> |local-address-error|
  |                :ToRepository  |         |                        |
  |               (/var/mail/spam)|         |                       All
 All -----------------------------+         |                    :ToRepository
                                            |               (/var/mail/address-
                                            |                     error)
                                            |
                                      RemoteAddrNotInNetwork --> |relay-denied|
                                            |                        |
                                           All                      All
                                       :RemoteDelovery         :ToRepository
                                                              (/var/mail/relay-
                                                                  denied)  

要するに、これを言葉で説明すると、

  1. (|root|) メールが30ホップを越えて転送されてきた。→破棄
  2. (|root|) query.bondedsender.org のブラックリストに載っている。→transport
  3. (|root|) dnsbl.njabl.org のブラックリストに載っている。→spam
  4. (|root|) relays.ordb.org のブラックリストに載っている。→spam
  5. (|root|) →transport
  6. (|transport|) ローカルの受取人がいる。→ローカル配信する
  7. (|transport|) ローカルで受取人がいない → local-address-error
  8. (|transport|) 外部からのメールである(リレーである)→ relay-denied
  9. (|transport|) とすれば内部からの外部への送信である → 外部配信する
  10. (|transport|) (終了)
  11. (|spam|,|local-address-error|,|relay-denied|) それぞれエラーメールとして保存し終了。

ということになる。要するにここで使われている Mailet は、ToProcessor を除くとすべて [終了] なものばかりで、そこで処理が終っているのである。

とするのならば「パイプラインのどこにあなたが書く Mailet を挿入すべきか?」はおそらく明白だ。|transport| の先頭が良いだろう。そうすれば、スパマ−からのメールは処理せずに、処理されるメールがローカル配信によって保存されてバックアップされるわけである。一般的には特定のメールアドレスに対して送信されたメールにについて、「あなたがさせたい処理」を書いた Mailet を起動したいだろうから、

  <processor name="transport">
    <mailet match="UserIs=hogehoge" class="MyMailet" />
    <mailet match="RecipientIsLocal" class="LocalDelivery"/>
    .......

というかたちで config.xml を書くのが普通ではなかろうか。



copyright by K.Sugiura, 1996-2006