インターネットを駆使した最近のアプリケーションでは,電子メール(本稿ではメールと呼ぶ)をシステムの一部として利用する場合も多い。例えば,「Webサイトでの申し込み確認をメールで送る」機能などである。

 J2EEアプリケーションでは,メール送信の場合にはJavaMail APIが提供されているため,比較的簡単に送信することができる。

 しかし,メールによる自動申し込みを受け付けるような機能の場合,メールを受けて何らかの処理を行う必要があり,JavaMail APIだけでは不十分である。なぜなら,JavaMail APIにはメールを受信するという機能は提供されていないからだ。提供されているのは,「メール・サーバーにメールの送信を依頼する」「メール・サーバーが受け取ったメールを読む」というMail User Agent(MUA)の機能のみである。

図1●一般的なメール・アプリケーションの構造
 本来メールを送受信するという処理は,他のメール・サーバーとのメールのやり取りを行う必要がある。このような機能をもったプログラムをMail Transfer Agent(MTA)と呼び,代表的なプログラムにsendmailがある。よって,メールを受け取ることが機能の一部となるようなシステムの場合,sendmailやqmailなどのMTAを別途用意し,システムを構築する場合も多いだろう(図1[拡大表示])。

 多くのMTAでは,特定のアドレスへのメールを受け取った際に,プログラムを起動することが可能であり,通常はこの機能を利用して前述のようなメールを受け取るシステムを作ることになる。
起動されるプログラムはプロセスとして起動されるためサーバー資源を多く必要とするばかりでなく,起動オーバーヘッドも大きい。

 今回紹介する Apache Jamesは,ピュアJavaで作成されたMTAだ。メールの送受信を行うだけでなく,POP3の機能やNNTPサーバー機能も提供する,高機能なMTAである。

SMTP,POP,NNTPサーバー機能も備える

 Java Apache Mail Enterprise Server(以降 James)は,Apache Jakarta Projectにて開発されていた,Java エンタープライズメール・サーバーだ。昨年Apache Jakartaプロジェクトから移動し,Apacheの1プロジェクトとなった。Jamesは,メールの送受信や,メーリング・リスト管理機能などの一般的なMTAの機能以外にも,以下のような機能を提供している。

  • POP3サーバー機能
  • NNTPサーバー機能
  • FetchPOP機能
  • メール・アプリケーション組み込み機能

     Jamesの一番の特徴は,最後の「メール・アプリケーション組み込み機能」といえる。

     Jamesは,Mailetと呼ばれるプログラムを複数組み込むことができる。Mailetとは,一定の条件のメールを受信した際に起動されるプログラムである。Jamesに独自に開発したMailetを組み込むことで,様々な処理を行うメール・サーバーが構築できるのである。Mailetはスレッドとして起動されるため,多くのMTAのようなプロセス起動のためのオーバーヘッドやOSリソースを必要とせず,高速に動作するという利点もある。

     その他の機能(POP3やNNTPなど)も充実しており,Jamesを起動するだけで,SMTPサーバー,POP3サーバー,NNTPサーバーなどが簡単に構築できる。さらにJavaVMが動作する環境であればどこでも動作可能という点,MailetはJavaで作成できJavaが提供する様々な機能が利用可能という点は,非常に魅力的である。

    メーリング・リスト作成機能や充実した管理機能

     JamesはMailetによるアプリケーション組み込み機能に注目しがちだが,基本的な機能も充実している。例えば,受け取ったメールやニュースの保存方法は,ファイル・システムのみでなく、RDBに格納することも可能だ。メーリング・リストの作成や購読者が自動登録する機能も提供されており,簡単な設定でメーリング・リスト機能が実現できる機能もある。メール・クライアント(UMA)からのアクセスには,POP3機能を提供しており,SMTP Authentication,TLS POP3などのセキュリティ機能も実験ステータスながら提供されている。

     ユーザー情報の管理(追加や削除など)はリモート・マネージャとよばれるサービスが提供しており,telnet経由で様々な設定が行える(表1)。また,ユーザー情報をLDAPから得る機能も実験ステータスながら提供されており,オープンソースのメール・サーバーとしても十分に実用に耐えうるものとなっている。

    表1●Jamesが提供する管理コマンド

    コマンド 意味
    help ヘルプの表示
    listusers 既存のアカウント・リストの表示
    countusers 既存アカウントの数を表示
    adduser [username] [password] ユーザーの追加
    verify [username] ユーザーの存在検査
    deluser [username] ユーザーの削除
    setpassword [username] [password] パスワードの設定
    setalias [alias] [user] エイリアス名の定義
    unsetalias [alias] エイリアス名の解除
    setforwarding [username] [emailaddress] フォワードの設定
    unsetforwarding [username] フォワードの解除
    user [repositoryname] ユーザー・リポジトリの変更
    shutdown Jamesのシャットダウン
    quit 管理コネクションの終了

    Avalonアプリケーション・フレームワーク上に構築

    図2●Jamesのアーキテクチャ
     Jamesは自身の動作のために,Apache Avalon プロジェクトのアプリケーション・フレームワークを利用している。Apache Avalonプロジェクトはコンポーネント指向のサーバープログラムを作成するための,フレームワークやコンポーネントを提供するプロジェクトである。このAvalonのフレームワーク上にJamesは構築されている。James内にはMailetが複数配置される(図2[拡大表示])。

     AvalonのフレームワークをJ2EEアプリケーション・サーバー,Jamesを1つのWebアプリケーション,Mailetがサーブレットと考えると判りやすいだろう。

     JamesのアークテクチャはAvalonのフレームワークに大きく依存しているが,Jamesの利用においては,Avalonフレームワークを意識することはそう多くはない。Avalonプロジェクトは,前述のようなフレームワークやコンポーネントから方法論まで提供している非常に巨大なプロジェクトである。多くのオープンソース・プロダクトがその影響を受けており,サーバー・アプリケーションを開発する場合には,非常に興味深いプロジェクトだ(本連載でも機会があれば紹介したいと思う)。

    メール・サーバーとしての利用方法

     Jamesを純粋な SMTPサーバー,POPサーバーとして利用する場合,起動までは非常に簡単だ。Jamesの最新安定版(執筆時 2.1.3)のバイナリリリースのパッケージであるjames-2.1.3.zipをhttp://james.apache.org/download.cgiより入手し,適切なディレクトリに展開後,XMLの設定ファイルにDNSサーバーのアドレスを定義するのみである(リスト1)。

    リスト1●設定ファイルDNS定義部抜粋

      <dnsserver>
       <servers>
         <server>192.168.0.1</server>
       </servers>
       <authoritative>false</authoritative>
      </dnsserver>

     設定後,Windows用,Unix用にそれぞれ用意されている起動スクリプトを実行すればよい。コマンドラインより起動すると,リスト2のような出力がなされる。リモートマネージャと,POP3サーバー,SMTPサーバー,NNTPサーバーが標準状態で起動されるのが,おわかりいただけると思う(この作業はUnix環境で実行する場合は,SMTPポートなどを利用するためroot権限で行う必要がある)。

    リスト2●起動メッセージ

    C:\james-2.1.3\bin>run.bat
    Using PHOENIX_HOME:  C:\Research\james-2.1.3
    Using PHOENIX_TMPDIR: C:\Research\james-2.1.3\temp
    Using JAVA_HOME:   c:\java\j2sdk1.4.2_01

    Phoenix 4.0.1

    James 2.1.3
    Remote Manager Service started plain:4555
    POP3 Service started plain:110
    SMTP Service started plain:25
    NNTP Service started plain:119
    Fetch POP Disabled

     この状態でTelnetコマンドを利用してJamesにアクセスし,表2に挙げたJamesの管理コマンドを利用すれば,ユーザーの登録などが行える。例えば,test01とtest02を登録する場合にはリスト3のように行う。これだけでメール環境が出来上がる。「test01@domain名」に対してメールを送信し,POP3をサポートしているMUA(例えば Outlook Express)でJamesにアクセスすればよい。Windowsのサービスとして登録するためのツールも用意されているので,非常に便利だ。

    リスト3●ユーザー追加

    >telnet localhost 4555
    JAMES Remote Administration Tool 2.1.3
    Please enter your login and password
    Login id:
    root
    Password:
    root
    Welcome root. HELP for a list of commands
    adduser test01 test01
    User test01 added
    adduser test02 test02
    User test02 added
    quit

    メール・アプリケーションサーバーとしての利用方法

     通常利用でも十分に強力な機能を提供するJamesであるが,Mailetを利用することでより強力なツールとなる。

    図3●Jamesの動作
     前述のようにMailetはJamesに組み込む,メール受信時に起動され何らかの処理を行うプログラムである。Mailetは受信メールに対して,任意の条件によって起動するように定義する。例えば,一定の文字列で始まる差出人アドレスやあて先アドレスのメールを受信した場合に,あるMailetを起動するといった具合である。

     この条件の判断はMatcherと呼ばれるプログラムで判断される。すなわちMatcherとMailetは組みあわせて利用する。MatcherもMailetも標準でいくつか提供されているが,自身で作成することが可能である。むしろ,自身でMatcherおよびMailetが作成できることがJamesの魅力といえる。

     MatcherおよびMailetの関係を(図3[拡大表示])に示す。Jamesには,MatcherやMailetがリレーショナルデータベースへの接続を行うための,DataSourceの提供機能も備わっている。またMailetにはメール送信機能も提供されており,返信メールの送信などの機能が簡単に実現でき,アプリケーションに無限の可能性を与えるものとなっている。

     Matcher,Mailetとも作成は比較的簡単だ。両者とも,独自のクラスを作成するためのスーパークラスが提供されているので,そのクラスを継承したクラスを作成すればよい。Mailetの起動を判断するMatcherは,リスト4のように記述する。例のMatcherは受信者のアドレスがjoinで始まる場合,Mailetを呼び出すというMatcherである。

    リスト4●SampleMatcher.java

    import org.apache.mailet.GenericRecipientMatcher;
    import org.apache.mailet.MailAddress;

    public class SampleMatcher extends GenericRecipientMatcher {
      public boolean matchRecipient( MailAddress recipient ) {
        if ( recipient.getUser().startsWith("join")){
          return true;
        }
        return false;
      }
    }

     呼び出されるMailetは,リスト5のように記述する。

    リスト5●SampleMailet.java

    import javax.mail.MessagingException;
    import org.apache.mailet.GenericMailet;
    import org.apache.mailet.Mail;

    public class SampleMailet extends GenericMailet {

      public void service(Mail mail) throws MessagingException {
       // メール受信時の処理を記述する
      }
    }

     これらのクラスをJamesに組み込み,設定ファイルにMatcherとMailetの関係を定義すれば完了である。リスト6に設定ファイルの抜粋を示す。

    リスト6●設定ファイル抜粋

     <mailet match="SampleMatcher" class="SampleMailet" />

     たったこれだけの作業で,メール・アプリケーションが作成できるのである。

     ご覧のようにJamesは,非常に強力かつ本格的なメール・サーバーである。メールの受信を伴うアプリケーションの構築を検討されている場合には,採用を検討してみてはいかがだろうか。OS非依存,ピュアJava,Apacheライセンスのプログラミング可能なメール・サーバーが,システムに安定性と柔軟性,高い開発効率をもたらすことと思う。

    黒住幸光(Kurozumi Yukimitsu)

    ■著者紹介
    黒住幸光(くろずみ ゆきみつ)氏
    株式会社アークシステム システム構築スペシャリスト。1995年,スーパー・コンピュータ向け言語処理環境の研究中に,生まれて間もないJavaと出会う。のちにJavaに専念するため転職を決意。現在,株式会社アークシステムにてオープンソース・ソフトウエアを用いたWWWシステムの構築,コンサルティングを行うかたわら,雑誌への執筆,StrutsユーザーMLの管理,Ja-JakartaプロジェクトTurbine翻訳の取りまとめなど幅広く活動中。メール・アドレスは,yukimi_2@yahooo.co.jp