たとえば 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 に違反する
結果を出力するなどの不満があります。 (例えば今の例で
To:
領域に使っている
display_name
で「.」が含まれますが、
RFC 2822 的には新しいメッセージでは互換性のため
quoted-string
にする必要があります。しかしそのまま出力されます。)
参考: 「.」の場合は RFC 2822 的には正しく解釈 されなければなりませんが (出力はすべきでない)、 これ以外の文字、例えば制御文字 ESCAPE でも同じようになります。 こちらは完全に間違いです。
参考: 実装方針としては不正な値はモジュールに 渡す前に弾くべきという考え方もあるでしょう。 でもそんなのは不便です。
ということで、はじめは既存のモジュールの wrapper (あるいは補完) を書くつもりでしたが、なんだかごちゃごちゃしていて、 それなら車輪の再発明になっても一から書いてみようと考えました。
header
field
) を解釈出来ます。group
なメイル・アドレスの領域内容を解釈出来ます。Message-ID
を生成出来ます。structured
) 頭領域について、表示のために quoted-pair
を unquote して値を返すなど出来ます。body
) にはまだ対応していません。 (text/plain
8bit
固定)body
) の実装。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 に従って利用出来ます。詳しくは各ファイルを御覧下さい。