Message::* Perl modules

はじめのはじめに

たとえば Perl で書かれた CGI script, それも掲示板なんかには、 こんなみっともない code が載っていたりします。

jcode'convert(*from, "jis");
jcode'convert(*subject, "jis");
jcode'convert(*message, "jis");
open (MAIL, "| $sendmail");
print MAIL "From: $mail ($from)\n";
print MAIL "To: $mailto\n";
print MAIL "Subject: $subject\n";
print MAIL "\n";
print MAIL "$message";
print MAIL "\n";
close (MAIL);

これでは視認性も良くないですし、うっかり修正し間違えると 変なメッセージを送信してしまいます。 (筆者はしょっちゅうはまってました:-) (それに多くの code では、 HTML でのクロスサイトスクリプティング (CSS) 問題と 類似の問題への対処をしていません。)

オブジェクト指向を取り入れて次のような感じでメッセージを 構成したいところです。

use Message::Entity;
my $msg = new Message::Entity;
my $hdr = $msg->header;
$hdr->add ('From')->add ('me@bar.example');
$hdr->add ('To')->add (['foo@bar.example', display_name => 'Mr. foo']);
$hdr->add (Subject => $subject);
$msg->body ($body);

# $smtp->send は SMTP で送信する method と仮定。
$smtp->send ($msg);

CPAN を探すと、 これに似たようなことができそうなモジュールはあるようですが、 実際に使ってみると、与える値によっては RFC 822/2822 に違反する 結果を出力するとか、そもそもそれ以前に、 $hdr->addr ('Foo Bar <foo@bar.example>') のようにメッセージ形式をモジュール内に隠匿しきれていないとか、非 ASCII 文字を考慮していないとかの不満があります。

(実装方針としては不正な値はモジュールに渡す前に弾くべきという考え方もあるでしょうけど、一般的な利用に際しては賢い設計だとは思えません。)

ということで、はじめは既存のモジュールの wrapper (あるいは補完) を書くつもりでしたが、なんだかごちゃごちゃしていて、 それなら車輪の再発明になっても一から書いてみようと考えました。

特色 (という程のものでもない。)

  1. 結構オブジェクト指向です。
  2. RFC 822/2822 の group を解釈出来ます。
  3. draft-ietf-usefor-msg-id-alt-00 に基づいた送信アドレスなどによる Message-ID を生成出来ます。
  4. 文字コード変換処理を外部に追い出しています。 jcode.pl でも Jcode.pm でも Encode::* でも、好きなものをお使い下さい。
  5. MIME (RFC 2045, 2046) にほぼ完全に対応しています。

各仕様への対応状況

  1. 電子メイルのメッセージ (RFC 822, RFC 2822) の全機能に対応しています。
  2. 電子ニュース記事 (RFC 1036, son-of-RFC1036, draft-usefor-article (06)) の頭領域の多くに対応しています。
  3. MIME の本文部分 (body part) に対応しています。
  4. MIME の頭領域 (RFC 2045, Content-Disposition) に対応しています。 パラメーター値拡張 (RFC 2231) も入出力ともに実装しました。
  5. MIME 符号化語 (encoded-word) の解読に対応しています:-)
  6. HTTP/1.0, HTTP/1.1, CGI/1.1, CGI/1.2 の頭領域のうち、 ごく一部に対応しています。 MHTML の Content-Location にも対応しています。
  7. 日付形式では RFC 822/1123, RFC 733, asctime, ISO 8601 (HTML) などに対応しています。日付の出力は sprintf の様な書式文字列を与えることで、多種多様な形式に対応。
  8. X-Moe シリーズに対応しています:-)

制限事項

  1. 類似モジュール(謎)のように、ファイル名やファイル・ハンドルを 渡して読み込ませることが出来ません。
  2. 大きなメッセージでも一気に読み込み、全て主記憶領域で 保持しています。ですからあまり大きなメッセージの処理には 向いていないでしょう。
  3. CRLF が単体で出現する場合、 正しく処理出来ませんないことがあります (近い将来の版で改善の予定)。 (CRLF と等価とみなします。) 将来の版ではオプションで制御可能になるかもしれません。
  4. 説明文 (document; pod) がいい加減です (書くのが面倒だ)。

必要環境

  1. Perl 5.6 以降

    comment を表すのに正規表現 (??{ code }) を使っているので、これを解釈出来る、 5.6 以降の版である必要があります。

  2. Digest::MD2, Digest::MD5, Digest::SHA1

    Message-ID の生成にこれらを使用する場合のみ、 Message::Field::MsgID が使います。

    Content-MD5: 領域の付加や検証を行う場合、 Digest::MD5 が必要です。 (Message::Entity)

  3. MIME::Base64

    ちなみに、 Quoted-Printable や RFC 2231 の % 符号化は自力で復号します。

  4. 文字コード変換処理

    日本語メッセージを扱うなら必須でしょう。 詳しくは文字コードの扱い の章をご参照下さい。

入手

suika.fam.cx の SSH account をお持ちの場合、 CVS から入手出来ます。

$ cvs -d :ext:username@suika.fam.cx:/home/cvs -d perl/lib/Message/

Web からも取り出せます。 <http://suika.fam.cx/gate/cvs/perl/lib/Message/>

最新の tarball を取得

ライセンス

Message::* Perl modules は自由ソフトウェアです。 GNU GPL に従って利用出来ます。詳しくは各ファイルを御覧下さい。

関連文書など

応用

今後の予定

  1. 電子ニュースの頭領域 (RFC 1036, son-of-RFC1036, draft-usefor-article) の完全実装
  2. 追加/非標準の頭領域の実装。
  3. documentation。
  4. 使用例の作成。
  5. 既存モジュールが利用出来る部分は、それを呼び出すようにするか その code を流用する。
  6. 類似モジュールとの界面の共通化
  7. HTTP 用に使えるようにする
$Date: 2002/07/13 11:51:56 $