本文へジャンプ

ソフトウェア > Lotus > Lotus Developer Domain > 

Iris Today Archives

Java メール転送エージェント


Lotus Software
by Ronald Albuquerque
レベル:上級者
対象:Designer R5
原文の掲載:2000年6月30日

Iris Today Archivesの原文(US)

インデックス
背景
スクリプト・ライブラリーや共有プロジェクトを用いる
プロフィール文書を用いてユーザー設定を保存する
件名によるコマンド
セキュリティー - 許可された範囲内での転送先アドレスの変更
メッセージを転送するかどうかを決定する
添付ファイルを取り除く
分かりやすい件名を作成する
メッセージの転送と処理
すべてのアクションのログを取る
サンプル・データベースを使用する際の詳細事項
より機能を拡張させるための提言

ネットワークや通信回線は日々高速になっていますが、しかしそれらは依然として満足が行くものではありません。常にインターネットや、会社のサーバーと通信ができるわけではありませんし、その回線のもつ最大のスピードで通信できることを保証してくれるわけでもありません。実際、最繁時間には極端に遅くなる回線もあります。

このようなことにより、頻繁に通信を行ったり、ダイヤルアップでメールをチェックする従業員は、少なからず不満を感じているでしょう。

その解決方法の1つとして、社内のメールを自宅からアクセスしやすい他のメール・アカウントに転送するということが考えられます。この記事では Java とノーツの強力な機能に焦点を当て、ノーツ・メール・データベース用の賢いメール転送エージェントの開発を行っていきます。

この記事で用いられるソースコードを見るには、Iris Sandbox から Java メール転送エージェントのサンプル・データベース (Java Mail Forwarding Agent sample database) をダウンロードしてください。

サンプルのエージェントには以下のような特長があります。
  • メールの件名に書かれたコマンドを理解し、プリファレンスを設定します。
  • 転送する際にメールから添付ファイルを取り除きます。
  • セキュリティーの確保。ノーツ・メールのユーザーあるいは、転送先のメール・アドレスの所有者だけがメッセージを送ってプリファレンスを変更できます。
  • ユーザーの好みに応じたモードを用いてメッセージを転送します。
  • 受信フォルダーの新着メールを対象にしています。エージェントはスケジュールに従って実行されるか、新着メールが到着するたびに実行されます。
  • ユーザー・プリファレンスを保存するためにプロフィール文書を用います。
  • 容易に更新できるように、スクリプト・ライブラリーには Java のコードが用いられています。
  • そのノーツ・ユーザー自身や、転送先メール・アドレスの所有者が作成したメッセージは転送しません。
  • エラーのトラブル・シューティングのために、独自のエージェント・ログのデータベースにコマンドを記録します。
  • 転送されたノーツ・メール・データベースの受信フォルダー内のメッセージを既読にしますが、削除はしません。

以下の必要条件に注意してください。
  • サンプルのデータベースには ノーツ R5 とドミノ・デザイナー R5 が必要です。
  • Java 言語、ノーツ R5 の Java バックエンド・クラス、そしてドミノ・エージェントの概念に精通している必要があります。
  • Java でのドミノ・エージェントの相当の開発経験が必要になります。

背景
不定期に在宅からアクセスする人は、社内のノーツ・メール・データベースのメールを自宅からアクセスしやすいインターネット・サービス・プロバイダーの個人的なアカウントに転送したいと思うことでしょう。でもその時には、特定の条件に基づいてメールを転送したいと思う人もいることでしょう。さらに、巨大な添付ファイルを含むメールをダウンロードして、電話回線を占有されたくないと思うことでしょう。

一般的には、仕事の時間は午前9時から午後5時までだと思います。そして、その仕事の時間の種類について3つのモードに分類してみました。
  • 通常 -- あなたは、この場合、普通はオフィスにいます。 そして、勤務時間中はメールの転送をしたくありません。
  • 在宅勤務 -- 勤務日の一部またはすべての時間に、自宅で仕事をしており、メールの転送を望んでいます。
  • 休暇/オフ -- あなたはカリブ海の浜辺でくつろいでいるか、北インドの山を探検しています。このような場合は、メールをチェックすることも読むこともできないので、メールの転送をしません。
仕事のモードを切り替えるぐらい容易に転送モードを切り替えたいことでしょう。また、あなたのスケジュールや要求が変わると、その新しい状況に対応したエージェントに更新する必要ありますが、できるだけトラブルが起こらないように済ませたいことでしょう。
 
上に戻る
 
スクリプト・ライブラリーや共有プロジェクトを用いる
デフォルトでは Java メール転送エージェントの Java コードは JavaAgent.java ファイルに格納されています。また、必要に応じてプロジェクトにソース・ファイルを追加できます。

エージェントのすべてのコードを書くことは可能ですが、ノーツはエージェントが処理したすべての文書の内部的なリストに保持しています。エージェントを変更した場合、このリストを再設定する必要があります。実際には、エージェントを実行したときにすべての文書を再処理する必要があるでしょう。

この問題を解決するには、Java のプログラム・コードの大部分をスクリプト・ライブラリーに保存する方法を取ります。

これをドミノ・デザイナーでどのようにすればよいのかを示します。
  1. ドミノ・デザイナーでメール・データベースを開きます。
  2. 設計要素から 〔リソース〕-〔スクリプトライブラリ〕 を選択します。
  3. 新規スクリプト・ライブラリーを作成します。
  4. 〔実行〕ドロップダウン・リストから Java を選択し、Java でライブラリーを作成することを宣言します。
以下に示されたスクリプト・ライブラリーの一覧では、今回使用していく Java クラスに ProcessMail という名が付けられた状態で表示されています。

Script Library

初めてエージェントが実行されると、受信フォルダーのすべての文書が処理されます。
それ以降は、未処理の文書のみが対象となります。そして、もうリストをリセットすることなしに、 ProcessMail スクリプト・ライブラリーを思う存分変更できます。

このスクリプトをエージェントに取り付けるには (エージェントでフックするには)、以下に示す Java メール転送エージェントのコードのように、Java エージェントから ProcessMail クラスのインスタンスを作成し、 ProcessMail::start() メソッドを呼び出します。

public class JavaAgent extends AgentBase
{
public void NotesMain()
{
try{
Session session=getSession();
AgentContext agentContext=session.getAgentContext();

//ここにコードを書いてください。
ProcessMail mailer=new ProcessMail(session.agentContext);
mailer.start();
}
catch(Exception e){System.out.println(e.getMessage());
e.printStackTrace();}
}// of NotesMain
}// of JavaAgent

このエージェントは受信フォルダー内のメッセージしか処理対象にしていないということに注意してください。
  1. 〔実行する文書〕セクションでは、〔前回の実行以降に作成または変更されたすべての文書〕を選択してください。
  2. 〔検索の追加〕ボタンをクリックして〔検索ビルダー〕ダイアログボックスを開きます。ダイアログボックス内の、〔検索条件〕のプルダウン・メニューから〔フォルダーより検索〕を選択し、一覧の中から〔受信ボックス〕を選択し [OK] をクリックします。

    これで、〔フォルダー 受信ボックス〕フィルターが加わりました。

    Which Document(s) Should it Act on?
Java エージェントをコンパイルするには、共有プロジェクトを使用する必要がありますが、以下にその方法を示します。
  1. Java メール転送エージェントを開きます。
  2. ウインドウの下部にある〔プロジェクトを編集〕ボタンをクリックします。すると〔Java エージェントファイルの構成〕ダイアログ・ボックスが現れます。
  3. そこで〔参照〕ドロップダウンリストから〔共有 Java ライブラリー〕を選択します。
  4. ProcessMail クラスをハイライトし、〔追加/置換ファイル〕ボタンをクリックします。


    Organize Java Agent Files dialog box
  5. 〔OK〕ボタンを押し、変更を保存します。
 
上に戻る
 
プロフィール文書を用いてユーザー設定を保存する
プロフィール・フォームは、ユーザー固有またはデータベース固有の値を収集する際に使われるフォームです。こうして収集された固有の値はプロフィール文書として格納され、必要に応じて取り出され使用されます。

プロフィールフ・ォームの説明とそれらの働きについては、プロフィール・フォームの補足をご覧ください。

このエージェントでは、プロフィール・フォームは、実行モードや、転送先アドレスなどのユーザーの設定を保存または取得するために用いられます。ProcessMail::getProfileDocValue() メソッドや ProcessMail::setProfileDocValue() メソッドは、そのために用いられます。

このエージェントで使用する ProcessMail プロフィール・フォームを作成する手順を以下に示します。
  1. modeemailaddress の2つのフィールドを持つフォームを作成します。
  2. 〔設計〕-〔フォームのプロパティ〕を選択し、〔メニューに含む〕のチェック・ボックスのチェックを外します。
  3. このフォームが、どのビューにも現れないことを確認します。

ここで、ProcessMail スクリプト・ライブラリーで用いられているメソッドを示します。 このメソッドは、mode フィールドに格納されているエージェントの実行状態を取得するためのものです。

public String getMode () throws NotesException
{
String sRet = this.getProfileDocValue("mode");

// null ならば、mode をデフォルト値に設定し、エラーをノーツ・ログに記録する。
if (sRet==null)
{
sRet=sDefaultMode;
this.setMode(sDefaultMode);
maillog.logError(1,"ProcessMail::getMode () - モードをヌルからデフォルト値に設定する "+sDefaultMode);
}
else
maillog.logAction ("ProcessMail::getMode () - 設定されていたモードは "+sRet);

return (sRet);

}
 
上に戻る
 
件名によるコマンド
このエージェントの特長の1つに、プロフィール文書を操作するコマンドを理解し、処理できるということがあります。本質的に、メッセージは以下の2つのタイプに分類することができます。
  • エージェントに対する命令を件名に含むコマンド・メッセージ
  • 必要に応じて転送される通常のメッセージ
エージェントが実行を開始すると、エージェントは受信フォルダー内の未処理の文書のリストを取得します。そして、メッセージの件名にコマンドがあるかどうかをチェックします。

たとえば、"processmail set mode telecommute" という件名のメッセージを自分自身に送ると、エージェントは実行状態を在宅勤務モードに設定します。
エージェントは実行状態を「在宅勤務」モードに設定します。その結果、通常の電子メールはすべて転送されることになります。

転送先の電子メール・アドレスを変更したい場合は、"processmail set emailaddress your.name@company.com" というような件名のメッセージを自分自身に送ります。

そのロジックを実装した ProcessMail スクリプト・ライブラリーのメソッドを以下に示します。

private boolean isAgentCommand (String sSubject)
{
boolean retval = false;
if (sSubject==null) sSubject= " ";
sSubject = sSubject.toLowerCase ();
if (sSubject.startsWith("processmail set "))
retval = true;
return (retval);

}

 
上に戻る
 
セキュリティー - 許可された範囲内での転送先アドレスの変更
スパイが何らかの方法で、あなたがこの便利なエージェントを利用していることを知り、あなたのメールを盗み見したいと考えたとします。

ロータス ノーツは、スパイが簡単にあなたのメール・データベースを破壊できないように、優れたセキュリティーを提供します。しかしながら、あなたが在宅中あるいは長期休暇中に、この侵入者は、エージェントが自分のところにメッセージが転送するという期待をして、"processmail set emailaddress maxwell.smart@getsmart.com" という件名で、あなたにメールを送りつけるかもしれません。

この種の事件を防ぐために、エージェントにはあるレベルのユーザー・セキュリティーが実装されています。転送先のメール・アドレスの変更を指示を受け取ったときに、送信者の電子メール・アドレス (From フィールドの値) が、以下の条件に当てはまるかを調べます。
  • ノーツ・メール・データベースの所有者自身 (つまり、あなた自身)
  • プロフィール文書に格納されている転送先アドレスと同一
実際にどのように動作するかを示します。あなたのノーツの正規の (決して変わることがない) 名前 (CN: Canonicl Name) が David Beckham/Manchester United/England で、転送先のメール・アドレスが david_beckham@freeserve.co.uk だとします。そうすると、あなたは、これらの2つのアカウントからエージェントに命令を送ることができます。

そして、転送先アドレスを david_beckham@manufree.net に変更したとすれば、エージェントは david_beckham@freeserve.co.uk から送られた命令を記録に残しますが、転送先変更の命令は無視します。
 
上に戻る
 
メッセージを転送するかどうかを決定する
処理しているメッセージが、エージェントに対する命令でないことが分かると、今度はそのメッセージを転送すればよいかをエージェントは判断することになります。

まず最初に、メッセージの作成者を調べます。その際には、Document::getItemValueString() メソッドを用いて、文書アイテム "From" の値を取得します。

作成者が、そのノーツ・ユーザー自身であれば、文書は転送されませんが、その代わりに、処理済のマークがつけられます。これは、カーボン・コピー (CC) に自分自身のアドレスをつけてメッセージを送り、自分の他の電子メール・アドレスに転送したくない場合に便利なものです。

次に、実行モードを決定するために、プロフィール文書の mode フィールドの値を取得します。

エージェントのモードには以下のようなものがあります。
  • 通常:午前9時から午後5時の間はメッセージを転送しない。
  • 在宅勤務:すべてのメッセージを転送する。
  • 休暇:メッセージを転送しない。
  • オフ:メッセージを転送しない。

モードを決定すると、エージェントは、文書が作成された日時を解釈し、メッセージを転送するかどうか判断します。

これを実装した ProcessMail スクリプト・ライブラリーのメソッドを以下に示します。

private boolean shallProcess (Document doc) throws NotesException
{
String currentmode= this.getMode ();

Date created = doc.getCreated().toJavaDate ();
Calendar createdcal = Calendar.getInstance ();
createdcal.setTime (created);
int hourcreated = createdcal.get(Calendar.HOUR_OF_DAY);
//int hourcreated = created.getHours (); //推奨されていない API を使った例

boolean bReturn = false;

//mode が normal (通常) で、文書を午後5時から午前9時に受け取った場合に転送する
if (currentmode.equalsIgnoreCase("normal"))
{
if ( (hourcreated >= 9) && (hourcreated <=17) )
bReturn = true;
}
//mode がtelecommute (在宅勤務) ならば、文書を転送する
else if (currentmode.equalsIgnoreCase("telecommute") )
{
bReturn = true;

}
// mode が vacation (休暇) または off (オフ) ならば文書を転送しない
else if ( currentmode.equalsIgnoreCase("vacation") || currentmode.equalsIgnoreCase("off") )
{
bReturn = false;
}
if (bReturn)
maillog.logAction("ProcessMail: 文書を転送します。");
else
maillog.logAction("ProcessMail: 文書を転送しません。");
return (bReturn);

}
 
上に戻る
 
添付ファイルを取り除く
電子メールに1つ、あるいは複数のファイルが添付されている場合が頻繁にあり、しかもそれらのサイズが非常に大きい場合があります。このような添付ファイルを自分のインターネット・サービスプロバイダーのアドレスに転送されないように、エージェントはメッセージを転送する際に、すべての添付ファイルを本文から取り除いて転送します。これにはノーツの Java API にある RichText クラスが利用されています。

//リッチテキストなら、添付ファイルを取り除いて文書にコピーする
if (Body.getType()==Item.RICHTEXT)

{
RichTextItem rtbody = (RichTextItem)doc.getFirstItem("Body");
maillog.logAction("Text of message: "+rtbody.getText());
String sText = rtbody.getText ();
memo.appendItemValue("Body","\n"+sText+"\n");
 
上に戻る
 
分かりやすい件名を作成する
前の節のサンプル・コードで見たように、エージェントは新しい文書を作成し、メッセージの本文をそこにコピーします。それから、以下で示すように送信者のアドレスから新しい文書の件名を作成します。

送信者がノーツ・ユーザーの場合、送信者の階層名に元の文書の件名をつなげたものが、新しい文書の件名になります。また、送信者の階層名は正規の名前と組織名に単純化されます。

たとえば、「午前 10 時にトレーニング」という件名のメッセージを Ryan Giggs/Manchester United/England から受け取ったとします。エージェントがメッセージを転送するときには、件名は、

[Ryan Giggs/England] 午前 10 時にトレーニング

というようになります。

送信者がインターネット・メールのユーザーの場合は、送信者の電子メール・アドレスの後に、元のメッセージの件名が続いたものが、新しい文書の件名となります。

この例では、「土曜日のゲームは日曜日に延期」という件名のメッセージを Alex_Ferguson@manutd.co.uk から受け取った場合、転送されるメッセージの件名は、

[Alex_Ferguson@manutd.co.uk] 土曜日のゲームは日曜日に延期

となります。

こうすることで転送先のアカウントから転送されたメールを受け取っても、元々のメールの送信者を知ることができます。
 
上に戻る
 
メッセージの転送と処理
エージェントはすべての条件を照合すると、文書を作成し、本文を付け加え、件名を生成します。それから、メッセージを転送し、文書を処理済とマークします。そして、次のメッセージの処理に取りかかります。

エージェントは Document::Senc() メソッドを使用して、メッセージを送信します。そして、AgentContext::updateProcessedDoc メソッドを用いて文書に処理済のマークをつけます。
 
上に戻る
 
すべてのアクションのログを取る
エージェントを実行していると、時折何かトラブルが生じることがあります。このような問題の原因を突き止めるために、エージェントはすべてのアクションのログを記録します。これには、以前作成したノーツ・エージェント・ログ・データベースが使用されます。エージェント・ログ・テンプレート (ALOG4.NTF) を用いて、このデータベースを作成できます。

このデータベースを使うために、エージェントはまず最初に、ノーツの Java API にある Log クラスを用いてログ・データベースへのアクセスを行います。

これを実現しているプログラム・コードを以下に示します。

//2. ノーツ・エージェント・ログを開き、開始情報を記録する
maillog = session.createLog(db.getTitle() + " on " + db.getServer());
maillog.openNotesLog (sMailLogServer,ProcessMail.sMailLogDB);

エージェントが何かアクションを実行するたびに、このコードによりエージェント・ログにアクションが記録されます。

以下のコードは実行開始時を記録するためのものです。

Date startdate = new Date ();
maillog.logAction("ProcessMail の開始日時 " + startdate.toString ());

エージェントは、Log::logError() メソッドを用いてエラーをログに記録します。 このエラーを記録するメソッドは、主に catch ステートメントの中で発生します。
 
上に戻る
 
サンプル・データベースを使用する際の詳細事項
この記事で用いられているコードのすべてを見るには、Java メール転送エージェントのサンプル・データベースを Iris Sandbox からダウンロードしてください。以下に、ProcessMail メール配信エージェントをノーツ・メール・データベースで利用する際に必要な詳細事項について述べます。
  1. ドミノ・デザイナーでノーツ・メール・データベースを開きます。
  2. ドミノ・デザイナーでサンプル・データベースを開きます。
  3. サンプル・データベースから ProcessMail フォーム (プロフィール・フォームのことです) をメール・データベースにコピー・アンド・ペーストしてください。
  4. サンプル・データベースから Java Mail Forwarding エージェントをご自身のデータベースにコピー・アンド・ペーストしてください。
  5. サンプル・データベースから ProcessMail スクリプト・ライブラリーをご自身のデータベースにコピー・アンド・ペーストしてください。
  6. エージェント・ログ・テンプレート (ALOG4.NTF ファイル) を利用してメール・サーバーにエージェント・ログ・データベースを作成してください。
  7. メール・データベースでスクリプト・ライブラリーを編集し、クラスの先頭にあるプライベート変数をご自身の環境に合った値に変更します。そして、ライブラリーをコンパイルし保存します。
  8. メール・データベースで、Java メール転送エージェントを編集し、エージェントの実行パラメータをご自身の好みに合わせます。そして、コンパイルし保存します。
おめでとうござます。こうして、エージェントを実行できる状態になりました。
 
上に戻る
 
より機能を拡張させるための提言
このエージェントは簡単に機能を拡張させることができます。次によりエージェントを強力にするためのアイデアを紹介します。
  • より多くの実行モードとパラメータを用意する。
  • 複数の転送先アドレスを利用できるようにする。
  • 実行モードの時間の区切りを切り替えられるようにする。
  • 「セキュリティー関連の処理手順を強化する。」で願います。
  • エージェント・ログ・データベースを定期的にリセットする。
  • ノーツ・メール・データベースにあるすべてのフォルダーを操作の対象とする。
  • メールのフィルタリング規則を自由に組み合わせて利用できるようにする。


著者について
ロナルド・アルバカーキはジオトラスト社のソフトウェア設計者です。そこで彼は暗号技術や XML を用いた Java のソフトウェアを開発しています。彼は以前は2年半以上アイリスアソシエイツに勤務しており、Java による自動化ソフトウェアを開発していました。彼はまた、ロータス ノーツやドミノ R5 上の Java 仮想マシンの認証に従事し、技術監修者として R5 システム管理者ヘルプに貢献しました。

ロナルドはアイルランドのダブリン市立大学で、応用数学の名誉学位を取得しました。彼の友人や家族は、彼の 80 年代の音楽への情熱やマンチェスターユナイテッドやサッカーに関係することに熱中しすぎていることについて我慢しています。彼はまた3匹の飼い猫にくだらない芸を仕込むのに熱心になっています。

彼と連絡をとるには、 rja@netcom.com にメールをしてください。

 
上に戻る