--- messaging/manakai/doc/introduction.ja.html 2002/03/21 04:03:45 1.1 +++ messaging/manakai/doc/introduction.ja.html 2002/06/14 12:46:34 1.6 @@ -1,145 +1,364 @@ - - - - -Message::* Perl modules - - - - - - - - - -

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 に違反する -結果を出力するなどの不満があります。 (例えば今の例で -To: 領域に使っている -display_name で「.」が含まれますが、 -RFC 2822 的には新しいメッセージでは互換性のため -quoted-string -にする必要があります。しかしそのまま出力されます。)

- -

参考: 「.」の場合は RFC 2822 的には正しく解釈 -されなければなりませんが (出力はすべきでない)、 -これ以外の文字、例えば制御文字 ESCAPE でも同じようになります。 -こちらは完全に間違いです。

-

参考: 実装方針としては不正な値はモジュールに -渡す前に弾くべきという考え方もあるでしょう。 -でもそんなのは不便です。

- -

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

- -

実装状況

- -
    -
  1. RFC 822, RFC 2822 の頭領域 (header field) を解釈出来ます。
  2. -
  3. 電子ニュース (RFC 1036 など), MIME, その他の追加頭領域の幾つかを解釈出来ます。
  4. -
  5. RFC 822/2822 の group なメイル・アドレスの領域内容を解釈出来ます。
  6. -
  7. 日付形式では RFC 822/1123, RFC 733, asctime, ISO 8601 (HTTP) などに対応。他の用途に転用出来ます。
  8. -
  9. draft-ietf-usefor-msg-id-alt-00 に基づいた送信アドレスなどによる Message-ID を生成出来ます。
  10. -
  11. まだ解釈出来ない構造化 (structured) 頭領域について、表示のために quoted-pair を unquote して値を返すなど出来ます。
  12. -
  13. MIME 本体 (body) にはまだ対応していません。 (text/plain 8bit 固定)
  14. -
  15. 説明はまだ不備です。各モジュールに pod で説明が入っていますが、 -抜けていたり実態に合っていなかったりもします。 -今の段階では code そのものが簡単に理解出来るとは思いますが。
  16. -
- -

今後の予定

- -
    -
  1. 電子ニュースの頭領域 (RFC 1036, son-of-RFC1036, draft-usefor) の実装
  2. -
  3. MIME の頭領域の実装。
  4. -
  5. 追加/非標準の頭領域の実装。
  6. -
  7. MIME 本体 (body) の実装。
  8. -
  9. 文字符号変換のための hook の実装?
  10. -
  11. documentation。
  12. -
  13. 使用例の作成。
  14. -
- -

入手

- -

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 に従って利用出来ます。詳しくは各ファイルを御覧下さい。

- -

参考文献

- - - - -
$date: $
- - + + + + + +Message::* Perl modules + + + + + + + + +

Message::* Perl modules

+ +

$B$O$8$a$N$O$8$a$K(B

+ +

$B$?$H$($P(B Perl $B$G=q$+$l$?(B CGI script, $B$=$l$b7G<(HD$J$s$+$K$O!"(B +$B$3$s$J$_$C$H$b$J$$(B code $B$,:\$C$F$$$?$j$7$^$9!#(B

+ +
+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);
+
+ +

$B$3$l$G$O;kG'@-$bNI$/$J$$$G$9$7!"$&$C$+$j=$@5$74V0c$($k$H(B +$BJQ$J%a%C%;!<%8$rAw?.$7$F$7$^$$$^$9!#(B +($BI. + +

$B%*%V%8%'%/%H;X8~$r + +

+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 $B$O(B SMTP $B$GAw?.$9$k(B method $B$H2>Dj!#(B
+$smtp->send ($msg);
+
+ +

CPAN $B$rC5$9$H!"(B +$B$3$l$K;w$?$h$&$J$3$H$,$G$-$=$&$J%b%8%e!<%k$O$"$k$h$&$G$9$,!"(B +$BRFC 822/2822 $B$K0cH?$9$k(B +$B7k2L$r=PNO$9$k$H$+!"$=$b$=$b$=$l0JA0$K!"(B +$hdr->addr ('Foo Bar <foo@bar.example>') +$B$N$h$&$K%a%C%;!<%87A<0$r%b%8%e!<%kFb$K1#F?$7$-$l$F$$$J$$$H$+!"Hs(B +ASCII $BJ8;z$r9MN8$7$F$$$J$$$H$+$NITK~$,$"$j$^$9!#(B

+ +

($B + +

$B$H$$$&$3$H$G!"$O$8$a$O4{B8$N%b%8%e!<%k$N(B wrapper ($B$"$k$$$OJd40(B) +$B$r=q$/$D$b$j$G$7$?$,!"$J$s$@$+$4$A$c$4$A$c$7$F$$$F!"(B +$B$=$l$J$i + +

$BFC?'(B ($B$H$$$&Dx$N$b$N$G$b$J$$!#(B)

+ +
    +
  1. $B7k9=%*%V%8%'%/%H;X8~$G$9!#(B
  2. +
  3. RFC 822/2822 $B$N(B group $B$r2r +
  4. draft-ietf-usefor-msg-id-alt-00 $B$K4p$E$$$?Aw?.%"%I%l%9$J$I$K$h$k(B Message-ID $B$r@8@.=PMh$^$9!#(B
  5. +
  6. $BJ8;z%3!<%IFHN)(B (CSI) $B$G$9!#(B ($BC"$7(B RFC 822 $B$G$"$kET9g>e(B($BFf(B)$B!"(B +ASCII $B8_49$G$"$kI,MW$O$"$j$^$9!#(B EBCDIC $B$H$+$OL5M}$G$9(B:-< +($B$H$$$&$N$O%a%C%;!<%89=B$$NItJ,$N$3$H$G$9!#(B +MIME $B$r;H$C$F(B EBCDIC $B$J$I$r%a%C%;!<%8K\J8$KF~$l$k$3$H$O2DG=$G$9!#(B))
  7. +
  8. MIME (RFC 2045, +2046) $B$K$[$\40A4$KBP1~$7$F$$$^$9!#(B
  9. +
+ +

$B3F;EMM$X$NBP1~>u67(B

+ +
    +
  1. $BEE;R%a%$%k$N%a%C%;!<%8(B (RFC 822, RFC 2822) +$B$NA45!G=$KBP1~$7$F$$$^$9!#(B
  2. +
  3. $BEE;R%K%e!<%95-;v(B (RFC 1036, +son-of-RFC1036, + +draft-usefor-article (06)) $B$NF,NN0h$NB?$/$KBP1~$7$F$$$^$9!#(B
  4. +
  5. MIME $B$NK\J8ItJ,(B (body part) $B$KBP1~$7$F$$$^$9!#(B + +
  6. +
  7. MIME $B$NF,NN0h(B +(RFC 2045, +Content-Disposition) $B$KBP1~$7$F$$$^$9!#(B +$B%Q%i%a!<%?!RFC 2231) +$B$bF~=PNO$H$b$K +
  8. MIME $BId9f2=8l(B (encoded-word) +$B$N2rFI$KBP1~$7$F$$$^$9(B:-)
  9. +
  10. HTTP/1.0, HTTP/1.1, CGI/1.1, CGI/1.2 $B$NF,NN0h$N$&$A!"(B +$B$4$/0lIt$KBP1~$7$F$$$^$9!#(B MHTML $B$N(B +Content-Location $B$K$bBP1~$7$F$$$^$9!#(B
  11. +
  12. $BF|IU7A<0$G$O(B RFC 822/1123, +RFC 733, asctime, ISO 8601 (HTML) +$B$J$I$KBP1~$7$F$$$^$9!#F|IU$N=PNO$O(B sprintf +$B$NMM$J=q<0J8;zNs$rM?$($k$3$H$G!"B? +
  13. X-Moe $B%7%j!<%:$KBP1~$7$F$$$^$9(B:-)
  14. +
+ +

$B@)8B;v9`(B

+ +
    +
  1. $BN`;w%b%8%e!<%k(B($BFf(B)$B$N$h$&$K!"%U%!%$%kL>$d%U%!%$%k!&%O%s%I%k$r(B +$BEO$7$FFI$_9~$^$;$k$3$H$,=PMh$^$;$s!#(B
  2. +
  3. $BBg$-$J%a%C%;!<%8$G$b0l5$$KFI$_9~$_!"A4$F +
  4. CR $B$d(B LF $B$,C1BN$G=P8=$9$k>l9g!"(B +$B@5$7$/=hM}=PMh(B$B$^$;$s(B$B$J$$$3$H$,$"$j$^$9(B +($B6a$$>-Mh$NHG$G2~A1$NM=Dj(B)$B!#(B (CRLF $B$HEy2A$H$_$J$7$^$9!#(B) +$B>-Mh$NHG$G$O%*%W%7%g%s$G@)8f2DG=$K$J$k$+$b$7$l$^$;$s!#(B
  5. +
  6. $B$"$C$?$iNI$5$=$&$J5!G=$,L$$BEE;R%a%$%k(B$B$d(B +suika.msg +$B$J$I$G65$($F2<$5$$!#(B)
  7. +
  8. $B3F%b%8%e!<%k$N%*%W%7%g%sBN7O$,$"$^$j@0Hw$5$l$F$$$^$;$s!#(B +($B$=$l$G$b5$;}$A0-$/$J$$DxEY$K$OBN7OE*$@$H;W$$$^$9!#(B)
  9. +
  10. $B@bL@J8(B (document) $B$,NI$$2C8:$G$9!#(B
  11. +
+ +

$B:#8e$NM=Dj(B

+ +
    +
  1. $BEE;R%K%e!<%9$NF,NN0h(B (RFC 1036, +son-of-RFC1036, +draft-usefor-article) $B$N40A4 +
  2. $BDI2C(B/$BHsI8=`$NF,NN0h$N +
  3. documentation$B!#(B
  4. +
  5. $B;HMQNc$N:n@.!#(B
  6. +
  7. $B4{B8%b%8%e!<%k$,MxMQ=PMh$kItJ,$O!"$=$l$r8F$S=P$9$h$&$K$9$k$+(B +$B$=$N(B code $B$rN.MQ$9$k!#(B
  8. +
  9. $BN`;w%b%8%e!<%k$H$N3&LL$N6&DL2=(B
  10. +
+ +

$BI,MW4D6-(B

+ +
    +
  1. Perl (perl 5.6 $B0J9_$^$?$O(B$B?M4V2r@O:-)) +

    comment + $B$rI=$9$N$K@55,I=8=(B (??{ code }) + $B$r;H$C$F$$$k$N$G!"$3$l$r2r +

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

    Message-ID $B$N@8@.$K$3$l$i$r;HMQ$9$k>l9g$N$_!"(B + Message::Field::MsgID $B$,;H$$$^$9!#(B

    +

    $B$3$l$i$,MQ0U$5$l$F$$$J$$4D6-$G$O%(%i!<$K$J$k$N$G!"(B + ($B8=>u$G$O(B) $B>e5-%b%8%e!<%k$N3:EvItJ,$r=q$-49$($FBP=h$7$F2<$5$$!#(B

    +
  4. +
  5. MIME::Base64 +

    $B$A$J$_$K!"(B Quoted-Printable $B$d(B RFC 2231 $B$N(B + % $BId9f2=$O<+NO$GI|9f$7$^$9!#(B

    +
  6. +
  7. $BJ8;z%3!<%IJQ49=hM}(B +

    $BF|K\8l%a%C%;!<%8$r07$&$J$iI,?\$G$7$g$&!#(B + $B>\$7$/$O(B$BJ8;z%3!<%I$N07$$(B + $B$N>O$r$4;2>H2<$5$$!#(B

    +
  8. +
+ +

$BF~ + +

suika.fam.cx $B$N(B SSH account $B$r$*;}$A$N>l9g!"(B CVS $B$+$iF~ + +

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

+ +

Web $B$+$i$bhttp://suika.fam.cx/gate/cvs/perl/lib/Message/> (tarball $B$G0l3g + +

$B%i%$%;%s%9(B

+ +

Message::* Perl modules $B$O<+M3%=%U%H%&%'%"$G$9!#(B +GNU GPL $B$K=>$C$FMxMQ=PMh$^$9!#>\$7$/$O3F%U%!%$%k$r8fMw2<$5$$!#(B

+ +

$B;29MJ88%(B

+ + + +

$BJ8;z%3!<%I$N07$$(B

+ +

$BH\$7$$$3$H$GF,$rG:$^$9$N$O7y$J$N$G(B($BON(B)$B!"(B +[[ $B"*(B$B$B!#(B ]] +Message::* $B$OId9f2=J}K!FHN)(B (CSI) $B$rL\;X$7$Fl9g$O!"(B Message::* $B$rDL$7$?$3$H$G%G!<%?$,2u$l$k$3$H$O(B +$BL5$$$H;W$$$^$9!#(B

+ +

($B$b$A$m$s!"(B RFC 822 $B$J$I3F;EMM$K>H$i$7$F@5E}(B($BE*(B)$B$G(B +$B$"$kI,MW$,$"$j$^$9!#(B atom +$B$K(B8$B%S%C%H!&%3!<%I$,4^$^$l$F$$$k$H@5$7$/07$($^$;$s!#(B) +($BAa$$OC$,!"(B quoted-string +$B$J$I$G$O(B8$B%S%C%HF)2a$@$H$$$&$3$H$G$9!#2s$j$/$I$/$F$4$a$s$J$5$$!#(B)

+ +

$B4{Dj$N>uBV$G$OJ8;z%3!<%I$K4X78$9$kJQ49=hM}$O9T$o$l$^$;$s!#(B +$B$7$+$7!"%U%C%/4X?t$C$]$$$b$N(B($BFf(B)$B$r;XDj$9$k$3$H$G!"(B +$BJQ49=hM}$r$5$;$i$l$^$9!#(B

+ +

$B;XDj=PMh$k%U%C%/4X?t$C$]$$$b$N$O(B2$BDECODER $B$O!"85$N%a%C%;!<%8$r2r@O$9$k;~(B +(parse ()) $B$KE,598F$S=P$5$l$^$9!#(B +ENCODER $B$O!"%a%C%;!<%8$H$7$FJ8;zNs2=$9$k:](B +(stringify () $B$J$I(B) $B$KE,598F$S=P$5$l$^$9!#(B

+ +

$B$3$l$i$N4X?t$O!"EvA3!"Ev3:=hM}$,8F$S=P$5$l$kA0$K;XDj$7$F$*$/(B +$BI,MW$,$"$j$^$9!#(B +Message::Entity->parse $B$J$I$9$kA0$K(B +$BDj5A$7$F$*$/$HNI$$$G$7$g$&!#(B

+ +
+require Message::MIME::Charset;
+$Message::MIME::Charset::DECODER{'*default'} = sub {jcode::euc ($_[1])};
+$Message::MIME::Charset::ENCODER{'*default'} = sub {jcode::jis ($_[1], 'euc')};
+
+ +

$B$3$NNc$G$O!"(B jcode.pl $B$rJQ49=hM}$K;H$$$^$9!#(B +($B$b$A$m$s!"4{$K(B require +$B$5$l$F$$$k$H2>Dj$7$F$$$^$9!#(B)

+

$B:G=i$N(B require $B$G!"JQ49=hM}$rC4Ev$7$F$$$k(B +Message::MIME::Charset $B$rFI$_9~$_$^$9!#(B +($B$3$&$7$F$*$+$J$$$H!"8e$+$i4{DjCM(B (= $BL5JQ49(B) $B$G(B +*default $B$,>e=q$-$5$l$F$7$^$$$^$9!#(B)

+ +

$B$3$N(B code $B$r;H$C$?%9%/%j%W%H$OFbIt=hM}$rF|K\8l(B EUC +$B$G9T$&$H2>Dj$7$F$$$^$9!#$G$9$+$i!"(B DECODER +$B$GF|K\8l(B EUC $B$KJQ49$7$^$9!#(B

+

$B$^$?!"F|K\8l%a%C%;!<%8$G$O(B ISO-2022-JP +$B$r;H$&$N$,47=,$G$9$+$i!"(B ENCODER +$B$G$O(B 7$B%S%C%H(B JIS $B$KJQ49$7$F$$$^$9!#(B

+

$B=hM}$r9T$&4X?t$O!"0z?t$,(B2$B$D0J>eM?$($i$l$^$9!#(B +1$B$DL\$N0z?t$O8F$S=P$7$?(B class module, $B$$$o$f$k(B +$self $B$G$9!#(B($B$3$N>l9g(B self $B$G$O$"$j$^$;$s$,(B:-) +$B$G$bIaDL$OI,MW$J$$$G$7$g$&!#(B

+

2$B$DL\$N0z?t$O=hM}BP>]$NJ8;zNs$G$9!#(B

+

3$B$DL\0J9_$N0z?t$O!"DI2C%*%W%7%g%s$N%O%C%7%e$G$9!#(B +$B$?$@$7!"8=:_DI2C%*%W%7%g%s$ODj5A$5$l$F$$$^$;$s!#(B

+

$B4X?t$,JV$9CM$O(B($B:#$N$H$3$m(B)$B0l$D$@$1$G$9!#(B +$B=hM}$,=*$o$C$?J8;zNs$G$9!#JQ497k2L$H$7$F2?$b$J$/$J$C$F$7$^$C$?$i!"(B +$B$b$A$m$s6uJ8;zNs$rJV$7$F9=$$$^$;$s!#(B (undef +$B$h$j$b6uJ8;zNs$NJ}$,K>$^$7$$$G$7$g$&!#(B)

+ +

$B$5$F!">e5-$NNc$G$O!V(B*default$B!W$N(B EN/DECODER +$B$r;XDj$7$^$7$?$,!"$3$3$K$OBe$o$j$K(B charset $BL>$r;XDj=PMh$^$9!#(B

+ +
+$Message::MIME::Charset::DECODER{'iso-2022-jp'} = sub {jcode::euc ($_[1], 'jis')};
+
+ +

$B$3$3$G$O!"(B ISO-2022-JP $B$rFbIt%3!<%I$KJQ49$9$k(B +$BJ}K!$rDj5A$7$F$$$^$9!#(B charset $BL>(B ($B$*$h$S!V(B*default$B!W(B +$B$OI,$:>.J8;z$G=q$$$F2<$5$$(B!)

+

MIME body $B$d!"(B encoded-word, RFC 2231 $B$N3HD%%Q%i%a!<%?!$NJQ494X?t$,(B +$B8F$S=P$5$l$^$9!#(B ($B;XDj$5$l$?(B charset $BL>$NJQ494X?t$,L$Dj5A$N;~$O!"(B +$B2?$b=hM}$7$^$;$s!#(B) $B$3$l0J30$N>lLL$G$O!"(B *default +$B$GDj5A$5$l$?4X?t$,;H$o$l$^$9!#(B

+ + + +

$B$d$d$3$7$$@bL@$r$7$F$-$^$7$?$,!" + +

+## $B$I$A$i$+9%$-$JJ}$r$I$&$>!#(B
+use Message::MIME::Charset::Jcode 'jcode.pl';
+use Message::MIME::Charset::Jcode 'Jcode';
+
+ +

$B$3$N(B1$B9T$@$1$G!"(B ISO-2022-JP, EUC-JP, Shift_JIS +$B$*$h$S4v$D$+$N4XO"(B charset $B$,MxMQ2DG=$K$J$j$^$9!#(B

+ +

Perl 5.8 $B$K$J$C$F(B Encode $B%b%8%e!<%k$,;H$($k$h$&$K$J$l$P!"(B +$B$b$C$H?'!9$JJ8;z%3!<%I$,3Z$KMxMQ$G$-$k$h$&$K$J$k$H4|BT$7$F$$$^$9!#(B

+ +

$B$H$3$m$G!"$3$N$h$&$K(B charset $BBP1~=hM}$r$7$J$/$F$b!"(B +MIME $B$G(B charset $B;%IU$1$5$l$F%a%C%;!<%8$K4^$a$i$l$F$$$kL$CN$N(B +charset $B$N%G!<%?$,GK2u$5$l$k$3$H$O$"$j$^$;$s!#(B ($B$O$:$G$9!#(B) +($B$=$3$$$i$,!"(B Unicoder $B$N%=%U%H%&%'%"$H$N0c$$$G$9(B($B>P(B)$B!#(B)

+ +
+
$Date: 2002/06/14 12:46:34 $
+ +