あおきです。

  In mail "[ruby-list:23277] net/smtp.rb extra lines ?"
    "Kikutani, Makoto" <kikutani / Galaxy.net> wrote:

> どうも、最近自分の出したメイルに2行くらい余計な空行が最後に
> 付いているのに気付いたので、まあcurのバグに違いないと思っていろいろ
> 調べたのですが、

> なんてのを実行しても、やはり余計な空行が付きますね。
> これは使いかたが悪いのか、あるいは net/smtp.rb の問題なのでしょうか?

一行は smtp のバグでした。ごめんなさい。後の一行は謎です。
とりあえず以下のパッチ試してください。
チェックインもします。


> # どうもnetの下は難しすぎていつも追えない。protocol.rb の each_crlf_line
> # あたりまで行ってギブアップ

そうですか。ぼくは ごく普通に書いてるつもりなんですが(あたりまえか)、
「net/* は理解できない」という声がよくあがるので ちょっと悩んでます。
-------------------------------------------------------------------
あおきみねろう

Index: protocol.rb =================================================================== RCS file: /home/aamine/cvs/maillib/protocol.rb,v retrieving revision 1.2.2.21 retrieving revision 1.2.2.23 diff -u -r1.2.2.21 -r1.2.2.23 --- protocol.rb 2000/06/12 16:33:45 1.2.2.21 +++ protocol.rb 2000/06/16 10:34:56 1.2.2.23 @@ -7,15 +7,6 @@ This library is distributed under the terms of the Ruby license. You can freely distribute/modify this library. -=end - - -require 'socket' - - -module Net - -=begin == Net::Protocol @@ -66,10 +57,16 @@ =end +require 'socket' + + +module Net + class Protocol Version = '1.1.22' + class << self def start( address = 'localhost', port = nil, *args ) @@ -480,9 +477,6 @@ CRLF = "\r\n" - D_CRLF = ".\r\n" - TERMEXP = /\n|\r\n|\r/o - def read( len, dest = '' ) @pipe << "reading #{len} bytes...\n" if @pipe; pipeoff @@ -531,7 +525,7 @@ def readline - ret = readuntil( CRLF ) + ret = readuntil( "\r\n" ) ret.chop! ret end @@ -542,9 +536,9 @@ rsize = 0 - while (str = readuntil( CRLF )) != D_CRLF do + while (str = readuntil( "\r\n" )) != ".\r\n" do rsize += str.size - str.gsub!( /\A\./o, '' ) + str.gsub!( /\A\./, '' ) dest << str end @@ -559,7 +553,7 @@ arr = [] str = nil - while (str = readuntil( CRLF )) != D_CRLF do + while (str = readuntil( "\r\n" )) != ".\r\n" do str.chop! arr.push str yield str if iterator? @@ -602,7 +596,7 @@ def writeline( str ) do_write_beg do_write_do str - do_write_do CRLF + do_write_do "\r\n" do_write_fin end @@ -629,8 +623,7 @@ else write_pendstr_inner src end - each_crlf_line2( :i_w_pend ) - do_write_do D_CRLF + do_write_do ".\r\n" wsize = do_write_fin @pipe << "wrote #{wsize} bytes text\n" if pipeon @@ -657,32 +650,40 @@ def each_crlf_line( src, mid ) - beg = 0 - buf = pos = s = bin = nil + buf = '' + str = m = nil - adding( src ) do - beg = 0 - buf = @wbuf + adding( src, buf ) do while true do - pos = buf.index( TERMEXP, beg ) - break unless pos - s = $&.size - break if pos + s == buf.size - 1 and buf[-1] == ?\r + m = /[^\r\n]*(\n|\r\n|\r)/.match( buf ) + break unless m - __send__ mid, buf[ beg, pos - beg ] << CRLF - beg = pos + s + str = m[0] + if str.size == buf.size and buf[-1] == ?\r then + # "...\r" : can follow "\n..." + break + end + buf[ 0, str.size ] = '' + str.chop! + str.concat "\r\n" + __send__ mid, str end - @wbuf = buf[ beg, buf.size - beg ] if beg != 0 + end + if not buf.empty? then # un-terminated last line + buf.concat "\r\n" + __send__ mid, buf + elsif not str then # empty src + __send__ mid, "\r\n" end end - def adding( src ) + def adding( src, buf ) i = nil case src when String 0.step( src.size, 512 ) do |i| - @wbuf << src[ i, 512 ] + buf << src[ i, 512 ] yield end @@ -690,38 +691,22 @@ while true do i = src.read( 512 ) break unless i - @wbuf << i + buf << i yield end else src.each do |bin| - @wbuf << bin - yield if @wbuf.size > 512 + buf << bin + yield if buf.size > 512 end end end - def each_crlf_line2( mid ) - buf = @wbuf - beg = pos = nil - - buf << "\n" unless /\n|\r/o === buf[-1,1] - - beg = 0 - while true do - pos = buf.index( TERMEXP, beg ) - break unless pos - __send__ mid, buf[ beg, pos - beg ] << CRLF - beg = pos + $&.size - end - end - def do_write_beg @writtensize = 0 @sending = '' - @wbuf = '' end def do_write_do( arg )