やまだあきらです.
しばし間が空きましたが再びメール解析用のスクリプトのお話です.
Thu, 25 Sep 97 11:50:36 +0900 頃の
Mail-Count: 04637
Subject: [ruby-list:4637] Re: mail address class
についてのお話にて 石塚圭樹 さん曰く…
(石 == keiju / bc.mbn.or.jp (石塚圭樹 ) さん)
In article 04637, <199709241419.XAA10620 / penta.tyo.otc.ogis-ri.co.jp>
石> そうですね. クラスの構造などは一度になかなか決められないなと感じていま
石> す. 私も, 最初クラスで作っていて後からモジュールにしたりすることは良く
石> あります.
はい, 石塚さんにいろいろうかがいながら
頻繁にあっちこっち移動してたりします.
石> C++などと違ってrubyはかなり動的な言語であることと, クラス/モジュールの
石> 構成に関して自由度が高いので, 実際に機能がはっきりしてきてからでも遅く
石> ないと思っています.
そうですね.
最終的には実際の使用例を作ってみないとわからないですね.
# ……ruby な ML サーバプログラム? (^_^;)
なお, サイズもサイズになってきましたので
今回は Web の方に置いてみました.
<URL:http://www.netlab.co.jp/~akira/ruby/RFC822.rb> です.
さて, 内容についてですが:
石> [全体として]
石> 前回はAddressクラスがありましたが今度はHeaderクラスになりましたね.
石>
石> 正直いってこの段階では, Headerクラスの必要性はないと思います. class
石> RFC822にHeaderの機能をマージした方が良いと思います.
その後考えてみて, Header クラスをやめて RFC822 クラスにマージしました.
おっしゃる通り, 少なくとも現状では Header と Body に
クラス別けしてしまう必要はなさそうに思えたためです.
でもって
石> 個人的にはAddressクラスは残しておいた方が良かったんではないかと思って
石> います. (正規化された)文字列としてHeaderの中にアドレスのパーズ機能を持
石> たせるよりも, クラスとして独立させてAddressクラスにアドレスのパーズ機
石> 能を持たせた方が(Headerもスリムになりますし)すっきりすると思います. ま
この辺りも取り入れさせてもらいまして
Address クラスを復活させました.
(以下個々に)
>> module RFC822_staff
石> 今は定数だけですが, ここで定義されるメソッドがあるとさらにモジュールら
石> しくなるんですけどね.
Header を RFC822 にマージして Address を復活させた関係で
一部のメソッドを RFC822_staff モジュールに移動してみました.
# 適当かどうかはまだわかりませんが.
石> [1]
>> class Header
>> attr :header
>> …
>> include RFC822_staff
石> classの直後にincludeがある方が好きです.
/usr/local/lib/ruby 配下をみても attr が
こういった位置にあるのは特異(^_^;)なようですので
そのようにしました.
石> [2]
>> @date =
>> Header.date_to_gmtime(@header['Date']) if @header.key?('Date')
>> @subject = @header['Subject'] if @header.key?('Subject')
石> で十分です. 気になるのは@dateは良いとして, @subjectをインスタンス変数
石> として割り当てなくても良いのでは? って感じがします.
その通りですね.
石> [5]
>> def make_reply_header #(my_address)
>> if r = self.get_address('Reply-to')
>> h += "To: " + r + "\n"
>> elsif r = self.get_address('From')
>> h += "To: " + r + "\n"
>> end
石>
石> Header#get_address()は配列を返すんですよね... Reply-toやFromは, 通常は
石> 1アドレスなので, これで動作しているんですが... 明示的に:
石>
石> h += "To: " + r[0] + "\n"
石>
石> としておいた方が無難かと...
この辺りはとりあえずのテスト用でしたので.
石> あと, += よりは, String#concatの方が実行効率は良いです. 今回のような場
石> 合はconcatを用いても間違いはないでしょう.
了解です. そう言うことを知りませんでした.
石> あと, 勝手な要望ですが, MHの様に自分でカスタマイズが行いやすい構造になっ
石> ていると嬉しいですね.
私もそう思います.
が, これはどういうふうに実装するのが嬉しいですかね?
mew(ヒェ〜)のコードをみると
(defvar mew-noreplyto-to-list '("From:")
"*To: field list picked at mew-summary-reply if Reply-To: doesn't exist.")
(defvar mew-noreplyto-cc-list '("To:" "Cc:" "Apparently-To:")
"Cc: field list picked at mew-summary-reply if Reply-To: doesn't exist.")
(defvar mew-replyto-to-list '("Reply-To:" "From:")
"*To: field list picked at mew-summary-reply if Reply-To: exists.")
(defvar mew-replyto-cc-list '("To:" "Cc:" "Apparently-To:")
"*Cc: field list picked at mew-summary-reply if Reply-To: exists.")
なんてなってるのですが, まねするというのも手かな?
石> [8]
>> def <=>(o)
石> Integer <=> aRFC822
石>
石> などが, 実現できていませんよね?
なるほど.
石> Integer#<=>(other)は, 当然, Integerのメソッドなので定義はできません(実
石> 際にはできますが, それはおいておいて). そのかわり, 自分が知らないクラ
石> スが来ると, x, y = other.corece(self)を呼びだし x<=>yを実行するように
石> なっています. Rationalの場合を例にとると, Rational#coerce(other)は:
この辺りまねてみましたがどうでしょう?
石> [9]
>> とりあえず mbox 形式は考えていません.
石> これからメイラを作るんだったら, ファイル形式を自由に選べる方がベストで
石> すね.
えーと, RFC822 なメッセージの解析をするためのもの
と考えていますので mbox 形式は対応しないと思います.
MUA などで適宜分割した上で RFC822 クラスを使うってので
十分んかなぁ,と.
石> [10]
>> # まだエラー処理, その他はいっさいしていません.
石> 確かに, もうそろそろ考えた方が良いかも...
う… まだしてません.
明らかに異常(ファイルがないとか)の場合はともかくとして
アドレス解析の経過でエラーが出た場合なんてのは
どう対処するのがいいのかなあ? などと悩んでいたりします.
一律にエラーを提示して終了しちゃうってのもなんだしなあ.
エラーがあったフィールドを無視するとか,
エラーがあったら止まっちゃうとかの切り替えができるといいのかな?
石> [11]
>> ## o multipart ボディを扱える (まだ, やってない)
石> ここをどのように扱うかが, 興味ありますね.
multipart の場合は boundary で分割して
RFC822 な子供のクラスを作るのかなあ.
t = RFC822.new(hoge)
part_i = t.part[1]
part_ii = t.part[2]
とか…?
# t.part[0] は body の中の最初のパートまでの部分?
multipart はまだよいとして, 分割されてる方は
どう扱うのがよいのだろう???
# 「?」ばっかりだ…(;_;)
--
やまだ あきら (akira / linux.or.jp or akira / nurs.or.jp)
Linux 関連ページ <URL:http://www.netlab.co.jp/~akira/linux/>