Net version 1.1.3

o  http.rb rd
o  Session -> Protocol


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@596 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
aamine 1999-12-29 11:14:04 +00:00
parent 0c00050f84
commit a1d1b15167
4 changed files with 419 additions and 372 deletions

View File

@ -5,6 +5,9 @@
maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp> maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This file is derived from http-access.rb This file is derived from http-access.rb
This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this library.
=end =end
require 'net/session' require 'net/session'
@ -17,253 +20,296 @@ class HTTPError < ProtocolError; end
class HTTPBadResponse < HTTPError; end class HTTPBadResponse < HTTPError; end
class HTTPSession < Session =begin
Version = '1.1.2' = HTTP class
session_setvar :port, '80' == Class Methods
session_setvar :command_type, 'Net::HTTPCommand'
: new( address, port = 80 )
def get( path = '/', header = nil, ret = '' )
confirm_connection
@proto.get edit_path(path), header, ret
end
def head( path = '/', header = nil )
confirm_connection
@proto.head edit_path(path), header
end
private
def confirm_connection
if @socket.closed? then
@socket.reopen
end
end
def do_finish create new HTTP object.
unless @proto.error_occured or @socket.closed? then
head '/', { 'Connection' => 'Close' } : port
returns HTTP default port, 80
: command_type
returns Command class, HTTPCommand
== Methods
: get( path, header = nil, ret = '' )
get data from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
The data will be written to "ret" using "<<" method.
This method returns response header (Hash) and "ret".
: head( path, header = nil )
get only header from "path" on connecting host.
"header" is a Hash like { 'Accept' => '*/*', ... }.
This method returns header as a Hash like
{ 'content-length' => 'Content-Length: 2554',
'content-type' => 'Content-Type: text/html',
... }
=end
class HTTP < Protocol
Version = '1.1.3'
protocol_param :port, '80'
protocol_param :command_type, '::Net::HTTPCommand'
def get( path, u_header = nil, ret = '' )
header = connecting {
@command.get ret, edit_path(path), u_header
}
return header, ret
end
def head( path, u_header = nil )
connecting {
@command.head edit_path(path), u_header
}
end end
end
def edit_path( path ) private
path
end
class << self
def Proxy( addr, port ) def connecting
klass = super if @socket.closed? then
klass.module_eval %- @socket.reopen
def edit_path( path ) end
'http://' + address + (port == self.port ? '' : ":\#{port}") + path header = yield
@socket.close unless keep_alive? header
header
end
def keep_alive?( header )
if str = header[ 'connection' ] then
if /\Aconnection:\s*keep-alive/i === str then
return true
end
else
if @http_version == '1.1' then
return true
end end
-
klass
end
end
end
HTTP = HTTPSession
class HTTPCommand < Command
HTTPVersion = '1.1'
def initialize( sock )
@http_version = HTTPVersion
@in_header = {}
@in_header[ 'Host' ] = sock.addr
#@in_header[ 'User-Agent' ] = "Ruby http version #{HTTPSession::Version}"
@in_header[ 'Connection' ] = 'keep-alive'
@in_header[ 'Accept' ] = '*/*'
super sock
end
attr :http_version
def get( path, u_header = nil, ret = '' )
header = get_response(
sprintf( 'GET %s HTTP/%s', path, HTTPVersion ), u_header )
if chunked? header then
clen = read_chunked_body( ret )
header.delete 'transfer-encoding'
header[ 'content-length' ] = "Content-Length: #{clen}"
else
@socket.read content_length( header ), ret
end
@socket.close unless keep_alive? header
return header, ret
end
def head( path, u_header = nil )
header = get_response(
sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header )
@socket.close unless keep_alive? header
header
end
# def put
# def delete
# def trace
# def options
private
def do_quit
unless @socket.closed? then
@socket.close
end
end
def get_response( line, u_header )
@socket.writeline line
write_header u_header
rep = get_reply
header = read_header
reply_must rep, SuccessCode
header
end
def get_reply
str = @socket.readline
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
raise HTTPBadResponse, "wrong status line format: #{str}"
end
@http_version = $1
status = $2
discrip = $3
klass = case status[0]
when ?1 then
case status[2]
when ?0 then ContinueCode
when ?1 then SuccessCode
else UnknownCode
end
when ?2 then SuccessCode
when ?3 then RetryCode
when ?4 then ServerBusyCode
when ?5 then FatalErrorCode
else UnknownCode
end
klass.new( status, discrip )
end
def content_length( header )
unless str = header[ 'content-length' ] then
raise HTTPBadResponce, "content-length not given"
end
unless /\Acontent-length:\s*(\d+)/i === str then
raise HTTPBadResponce, "content-length format error"
end
$1.to_i
end
def keep_alive?( header )
if str = header[ 'connection' ] then
if /\Aconnection:\s*keep-alive/i === str then
return true
end end
else
if @http_version == '1.1' then
return true
end
end
false
end
def chunked?( header )
if str = header[ 'transfer-encoding' ] then
if /\Atransfer-encoding:\s*chunked/i === str then
return true
end
end
false
end
def read_header
header = {}
while true do
line = @socket.readline
break if line.empty?
/\A[^:]+/ === line
nm = $&
nm.strip!
nm.downcase!
header[ nm ] = line
end
header
end
def write_header( user )
if user then
header = @in_header.dup.update user
else
header = @in_header
end
header.each do |n,v|
@socket.writeline n + ': ' + v
end
@socket.writeline ''
if tmp = header['Connection'] then
/close/i === tmp
else
false false
end end
end
def read_chunked_body( ret )
line = nil def do_finish
len = nil unless @command.error_occured or @socket.closed? then
total = 0 head '/', { 'Connection' => 'Close' }
end
while true do end
line = @socket.readline
unless /[0-9a-hA-H]+/ === line then
raise HTTPBadResponce, "chunk size not given" def edit_path( path )
path
end
class << self
def Proxy( p_addr, p_port )
klass = super
klass.module_eval %-
def edit_path( path )
'http://' + address +
(@port == #{self.port} ? '' : ':' + @port.to_s) + path
end
-
klass
end end
len = $&.hex
break if len == 0
@socket.read( len, ret ); total += len
@socket.read 2 # \r\n
end
while true do
line = @socket.readline
break if line.empty?
end end
total
end end
end HTTPSession = HTTP
class HTTPCommand < Command
HTTPVersion = '1.1'
def initialize( sock )
@http_version = HTTPVersion
@in_header = {}
@in_header[ 'Host' ] = sock.addr
@in_header[ 'Connection' ] = 'keep-alive'
@in_header[ 'Accept' ] = '*/*'
super sock
end
attr :http_version
def get( ret, path, u_header = nil )
header = get_response(
sprintf( 'GET %s HTTP/%s', path, HTTPVersion ), u_header )
if chunked? header then
clen = read_chunked_body( ret )
header.delete 'transfer-encoding'
header[ 'content-length' ] = "Content-Length: #{clen}"
else
@socket.read content_length( header ), ret
end
header
end
def head( path, u_header = nil )
get_response sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header
end
# def put
# def delete
# def trace
# def options
private
def do_quit
unless @socket.closed? then
@socket.close
end
end
def get_response( line, u_header )
@socket.writeline line
write_header u_header
rep = get_reply
header = read_header
reply_must rep, SuccessCode
header
end
def get_reply
str = @socket.readline
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
raise HTTPBadResponse, "wrong status line format: #{str}"
end
@http_version = $1
status = $2
discrip = $3
klass = case status[0]
when ?1 then
case status[2]
when ?0 then ContinueCode
when ?1 then SuccessCode
else UnknownCode
end
when ?2 then SuccessCode
when ?3 then RetryCode
when ?4 then ServerBusyCode
when ?5 then FatalErrorCode
else UnknownCode
end
klass.new( status, discrip )
end
def content_length( header )
unless str = header[ 'content-length' ] then
raise HTTPBadResponce, "content-length not given"
end
unless /\Acontent-length:\s*(\d+)/i === str then
raise HTTPBadResponce, "content-length format error"
end
$1.to_i
end
def chunked?( header )
if str = header[ 'transfer-encoding' ] then
if /\Atransfer-encoding:\s*chunked/i === str then
return true
end
end
false
end
def read_header
header = {}
while true do
line = @socket.readline
break if line.empty?
/\A[^:]+/ === line
nm = $&
nm.strip!
nm.downcase!
header[ nm ] = line
end
header
end
def write_header( user )
if user then
header = @in_header.dup.update user
else
header = @in_header
end
header.each do |n,v|
@socket.writeline n + ': ' + v
end
@socket.writeline ''
if tmp = header['Connection'] then
/close/i === tmp
else
false
end
end
def read_chunked_body( ret )
line = nil
len = nil
total = 0
while true do
line = @socket.readline
unless /[0-9a-hA-H]+/ === line then
raise HTTPBadResponce, "chunk size not given"
end
len = $&.hex
break if len == 0
@socket.read( len, ret ); total += len
@socket.read 2 # \r\n
end
while true do
line = @socket.readline
break if line.empty?
end
total
end
end
end # module Net end # module Net

View File

@ -4,8 +4,8 @@
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -19,17 +19,17 @@ module Net
=begin =begin
== Net::POP3Session == Net::POP3
=== Super Class === Super Class
Net::Session Net::Protocol
=== Class Methods === Class Methods
: new( address = 'localhost', port = 110 ) : new( address = 'localhost', port = 110 )
This method create a new POP3Session object. This method create a new POP3 object.
This will not open connection yet. This will not open connection yet.
@ -37,11 +37,11 @@ Net::Session
: start( account, password ) : start( account, password )
This method start POP session. This method start POP3.
: each{|popmail| ...} : each{|popmail| ...}
This method is equals to "pop3session.mails.each" This method is equals to "pop3.mails.each"
: mails : mails
@ -50,12 +50,19 @@ Net::Session
=end =end
class POP3Session < Session class POP3 < Protocol
Version = '1.1.2' Version = '1.1.3'
session_setvar :port, '110' protocol_param :port, '110'
session_setvar :command_type, 'Net::POP3Command' protocol_param :command_type, '::Net::POP3Command'
protocol_param :mail_type, '::Net::POPMail'
def initialize( addr = nil, port = nil )
super
@mails = [].freeze
end
attr :mails attr :mails
@ -68,25 +75,23 @@ Net::Session
private private
def proto_initialize
@mails = [].freeze
end
def do_start( acnt, pwd ) def do_start( acnt, pwd )
@proto.auth( acnt, pwd ) @command.auth( acnt, pwd )
t = self.type.mail_type
@mails = [] @mails = []
@proto.list.each_with_index do |size,idx| @command.list.each_with_index do |size,idx|
if size then if size then
@mails.push POPMail.new( idx, size, @proto ) @mails.push t.new( idx, size, @command )
end end
end end
@mails.freeze @mails.freeze
end end
end # POP3Session end
POPSession = POP3Session POP = POP3
POP3 = POP3Session POPSession = POP3
POP3Session = POP3
=begin =begin
@ -133,10 +138,10 @@ Object
class POPMail class POPMail
def initialize( idx, siz, pro ) def initialize( n, s, cmd )
@num = idx @num = n
@size = siz @size = s
@proto = pro @command = cmd
@deleted = false @deleted = false
end end
@ -145,13 +150,13 @@ Object
attr :size attr :size
def all( dest = '' ) def all( dest = '' )
@proto.retr( @num, dest ) @command.retr( @num, dest )
end end
alias pop all alias pop all
alias mail all alias mail all
def top( lines, dest = '' ) def top( lines, dest = '' )
@proto.top( @num, lines, dest ) @command.top( @num, lines, dest )
end end
def header( dest = '' ) def header( dest = '' )
@ -159,7 +164,7 @@ Object
end end
def delete def delete
@proto.dele( @num ) @command.dele( @num )
@deleted = true @deleted = true
end end
alias delete! delete alias delete! delete
@ -169,7 +174,7 @@ Object
end end
def uidl def uidl
@proto.uidl @num @command.uidl @num
end end
end end
@ -177,30 +182,30 @@ Object
=begin =begin
== Net::APOP3Session == Net::APOP
This class has no new methods. Only way of authetication is changed. This class has no new methods. Only way of authetication is changed.
=== Super Class === Super Class
Net::POP3Session Net::POP3
=end =end
class APOPSession < POP3Session class APOP < POP3
session_setvar :command_type, 'Net::APOPCommand' protocol_param :command_type, 'Net::APOPCommand'
end end
APOP = APOPSession APOPSession = APOP
=begin =begin
== Net::POP3Command == Net::POP3Command
POP3 protocol class. POP3 command class.
=== Super Class === Super Class
@ -240,7 +245,7 @@ Net::Command
: quit : quit
This method finishes POP3 session. This method ends POP using 'QUIT' commmand.
: rset : rset
@ -276,7 +281,7 @@ Net::Command
def auth( acnt, pass ) def auth( acnt, pass )
@socket.writeline( 'USER ' + acnt ) @socket.writeline 'USER ' + acnt
check_reply_auth check_reply_auth
@socket.writeline( 'PASS ' + pass ) @socket.writeline( 'PASS ' + pass )
@ -287,8 +292,7 @@ Net::Command
def list def list
@socket.writeline( 'LIST' ) getok 'LIST'
check_reply( SuccessCode )
arr = [] arr = []
@socket.read_pendlist do |line| @socket.read_pendlist do |line|
@ -301,36 +305,29 @@ Net::Command
def rset def rset
@socket.writeline( 'RSET' ) getok 'RSET'
check_reply( SuccessCode )
end end
def top( num, lines = 0, dest = '' ) def top( num, lines = 0, dest = '' )
@socket.writeline( sprintf( 'TOP %d %d', num, lines ) ) getok sprintf( 'TOP %d %d', num, lines )
check_reply( SuccessCode ) @socket.read_pendstr( dest )
return @socket.read_pendstr( dest )
end end
def retr( num, dest = '', &block ) def retr( num, dest = '', &block )
@socket.writeline( sprintf( 'RETR %d', num ) ) getok sprintf( 'RETR %d', num )
check_reply( SuccessCode ) @socket.read_pendstr( dest, &block )
return @socket.read_pendstr( dest, &block )
end end
def dele( num ) def dele( num )
@socket.writeline( 'DELE ' + num.to_s ) getok sprintf( 'DELE %d', num )
check_reply( SuccessCode )
end end
def uidl( num ) def uidl( num )
@socket.writeline( 'UIDL ' + num.to_s ) rep = getok( sprintf 'UIDL %d', num )
rep = check_reply( SuccessCode )
uid = rep.msg.split(' ')[1] uid = rep.msg.split(' ')[1]
uid uid
@ -341,8 +338,7 @@ Net::Command
def do_quit def do_quit
@socket.writeline( 'QUIT' ) getok 'QUIT'
check_reply( SuccessCode )
end end

View File

@ -1,11 +1,11 @@
=begin =begin
= net/session.rb version 1.1.2 = net/session.rb version 1.1.3
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby style license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -18,9 +18,9 @@ module Net
=begin =begin
== Net::Session == Net::Protocol
the abstruct class for Internet protocol session the abstruct class for Internet protocol
=== Super Class === Super Class
@ -30,22 +30,27 @@ Object
: Version : Version
The version of Session class. It is a string like "1.1.2". The version of Session class. It is a string like "1.1.3".
=== Class Methods === Class Methods
: new( address = 'localhost', port = nil ) : new( address = 'localhost', port = nil )
This method Create a new Session object. This method Creates a new Session object.
: start( address = 'localhost', port = nil, *args ) : start( address = 'localhost', port = nil, *args )
: start( address = 'localhost', port = nil, *args ){|session| .... } : start( address = 'localhost', port = nil, *args ){|session| .... }
This method create a new Session object and start session. This method creates a new Session object and start session.
If you call this method with block, Session object give itself If you call this method with block, Session object give itself
to block and finish session when block returns. to block and finish session when block returns.
: Proxy( address, port )
This method creates a proxy class of its protocol.
Arguments are address/port of proxy host.
=== Methods === Methods
@ -59,14 +64,14 @@ Object
: start( *args ) : start( *args )
This method start session. If you call this method when the session This method start protocol. If you call this method when the protocol
is already started, this only returns false without doing anything. is already started, this only returns false without doing anything.
'*args' are specified in subclasses. '*args' are specified in subclasses.
: finish : finish
This method finish session. If you call this method before session starts, This method ends protocol. If you call this method before protocol starts,
it only return false without doing anything. it only return false without doing anything.
: active? : active?
@ -75,20 +80,20 @@ Object
=end =end
class Session class Protocol
Version = '1.1.2' Version = '1.1.3'
class << self class << self
def start( address = 'localhost', port = nil, *args ) def start( address = 'localhost', port = nil, *args )
session = new( address, port ) instance = new( address, port )
if iterator? then if iterator? then
session.start( *args ) { yield session } instance.start( *args ) { yield instance }
else else
session.start *args instance.start *args
session instance
end end
end end
@ -104,11 +109,8 @@ Object
@port = port @port = port
end end
def connect def connect( addr, port )
tmpa, tmpp = @address, @port super @proxyaddr, @proxyport
@address, @port = @proxyaddr, @proxyport
super
@address, @port = tmpa, tmpp
end end
private :connect private :connect
@ -129,7 +131,7 @@ Object
private private
def session_setvar( name, val ) def protocol_param( name, val )
module_eval %- module_eval %-
def self.#{name.id2name} def self.#{name.id2name}
#{val} #{val}
@ -143,26 +145,26 @@ Object
# #
# sub-class requirements # sub-class requirements
# #
# session_setvar command_type # protocol_param command_type
# session_setvar port # protocol_param port
# #
# private method do_start (optional) # private method do_start (optional)
# private method do_finish (optional) # private method do_finish (optional)
# #
session_setvar :port, 'nil' protocol_param :port, 'nil'
session_setvar :command_type, 'nil' protocol_param :command_type, 'nil'
session_setvar :socket_type, 'Net::ProtocolSocket' protocol_param :socket_type, '::Net::ProtocolSocket'
def initialize( addr = 'localhost', port = nil ) def initialize( addr = nil, port = nil )
@address = addr @address = addr || 'localhost'
@port = port || self.type.port @port = port || self.type.port
@active = false @active = false
@pipe = nil @pipe = nil
@proto = nil @command = nil
@socket = nil @socket = nil
end end
@ -170,6 +172,7 @@ Object
attr :address attr :address
attr :port attr :port
attr :command
attr :socket attr :socket
@ -178,7 +181,7 @@ Object
@active = true @active = true
begin begin
connect connect @address, @port
do_start *args do_start *args
yield if iterator? yield if iterator?
ensure ensure
@ -187,7 +190,7 @@ Object
end end
def finish def finish
if @proto then if @command then
do_finish do_finish
disconnect disconnect
end end
@ -225,19 +228,21 @@ Object
end end
def connect def connect( addr, port )
@socket = self.type.socket_type.open( @address, @port, @pipe ) @socket = self.type.socket_type.open( addr, port, @pipe )
@proto = self.type.command_type.new( @socket ) @command = self.type.command_type.new( @socket )
end end
def disconnect def disconnect
@proto.quit @command.quit
@proto = nil @command = nil
@socket = nil @socket = nil
end end
end end
Session = Protocol
=begin =begin
@ -259,7 +264,7 @@ Object
: quit : quit
This method finishes protocol. This method dispatch command which ends the protocol.
=end =end
@ -301,6 +306,11 @@ Object
@error_occured = true @error_occured = true
rep.error! @socket.sending rep.error! @socket.sending
end end
def getok( line, ok = SuccessCode )
@socket.writeline line
check_reply ok
end
end end

View File

@ -4,8 +4,8 @@
written by Minero Aoki <aamine@dp.u-netsurf.ne.jp> written by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
This library is distributed under the terms of Ruby license. This library is distributed under the terms of the Ruby license.
You can freely distribute/modify this file. You can freely distribute/modify this library.
=end =end
@ -18,57 +18,57 @@ module Net
=begin =begin
== Net::SMTPSession == Net::SMTP
=== Super Class === Super Class
Net::Session Net::Protocol
=== Class Methods === Class Methods
: new( address = 'localhost', port = 25 ) : new( address = 'localhost', port = 25 )
This method create new SMTPSession object. This method create new SMTP object.
=== Methods === Methods
: start( helo_domain = ENV['HOSTNAME'] ) : start( helo_domain = ENV['HOSTNAME'] )
This method opens TCP connection and start SMTP session. This method opens TCP connection and start SMTP.
If session had been started, do nothing and return false. If protocol had been started, do nothing and return false.
: sendmail( mailsrc, from_domain, to_addrs ) : sendmail( mailsrc, from_domain, to_addrs )
This method sends 'mailsrc' as mail. SMTPSession read strings from 'mailsrc' This method sends 'mailsrc' as mail. SMTPSession read strings from 'mailsrc'
by calling 'each' iterator, and convert them into "\r\n" terminated string when write. by calling 'each' iterator, and convert them into "\r\n" terminated string when write.
SMTPSession's Exceptions are: Exceptions which SMTP raises are:
* Protocol::ProtoSyntaxError: syntax error (errno.500) * Net::ProtoSyntaxError: syntax error (errno.500)
* Protocol::ProtoFatalError: fatal error (errno.550) * Net::ProtoFatalError: fatal error (errno.550)
* Protocol::ProtoUnknownError: unknown error * Net::ProtoUnknownError: unknown error
* Protocol::ProtoServerBusy: temporary error (errno.420/450) * Net::ProtoServerBusy: temporary error (errno.420/450)
: finish : finish
This method closes SMTP session. This method ends SMTP.
If session had not started, do nothind and return false. If protocol had not started, do nothind and return false.
=end =end
class SMTPSession < Session class SMTP < Protocol
Version = '1.1.2' Version = '1.1.3'
session_setvar :port, '25' protocol_param :port, '25'
session_setvar :command_type, 'Net::SMTPCommand' protocol_param :command_type, '::Net::SMTPCommand'
def sendmail( mailsrc, fromaddr, toaddrs ) def sendmail( mailsrc, fromaddr, toaddrs )
@proto.mailfrom fromaddr @command.mailfrom fromaddr
@proto.rcpt toaddrs @command.rcpt toaddrs
@proto.data @command.data
@proto.sendmail mailsrc @command.sendmail mailsrc
end end
@ -79,12 +79,12 @@ Net::Session
unless helodom then unless helodom then
raise ArgumentError, "cannot get hostname" raise ArgumentError, "cannot get hostname"
end end
@proto.helo helodom @command.helo helodom
end end
end end
SMTP = SMTPSession SMTPSession = SMTP
=begin =begin
@ -99,14 +99,14 @@ Net::Command
: new( socket ) : new( socket )
This method creates new SMTPCommand object, and open SMTP session. This method creates new SMTPCommand object, and open SMTP.
=== Methods === Methods
: helo( helo_domain ) : helo( helo_domain )
This method send "HELO" command and start SMTP session. This method send "HELO" command and start SMTP.
helo_domain is localhost's FQDN. helo_domain is localhost's FQDN.
: mailfrom( from_addr ) : mailfrom( from_addr )
@ -139,34 +139,30 @@ Net::Command
def helo( fromdom ) def helo( fromdom )
@socket.writeline( 'HELO ' << fromdom ) getok sprintf( 'HELO %s', fromdom )
check_reply( SuccessCode )
end end
def mailfrom( fromaddr ) def mailfrom( fromaddr )
@socket.writeline( 'MAIL FROM:<' + fromaddr + '>' ) getok sprintf( 'MAIL FROM:<%s>', fromaddr )
check_reply( SuccessCode )
end end
def rcpt( toaddrs ) def rcpt( toaddrs )
toaddrs.each do |i| toaddrs.each do |i|
@socket.writeline( 'RCPT TO:<' + i + '>' ) getok sprintf( 'RCPT TO:<%s>', i )
check_reply( SuccessCode )
end end
end end
def data def data
@socket.writeline( 'DATA' ) getok 'DATA', ContinueCode
check_reply( ContinueCode )
end end
def writemail( mailsrc ) def writemail( mailsrc )
@socket.write_pendstr( mailsrc ) @socket.write_pendstr mailsrc
check_reply( SuccessCode ) check_reply SuccessCode
end end
alias sendmail writemail alias sendmail writemail
@ -175,8 +171,7 @@ Net::Command
def do_quit def do_quit
@socket.writeline( 'QUIT' ) getok 'QUIT'
check_reply( SuccessCode )
end end
@ -184,19 +179,19 @@ Net::Command
arr = read_reply arr = read_reply
stat = arr[0][0,3] stat = arr[0][0,3]
cls = UnknownCode klass = UnknownCode
case stat[0] klass = case stat[0]
when ?2 then cls = SuccessCode when ?2 then SuccessCode
when ?3 then cls = ContinueCode when ?3 then ContinueCode
when ?4 then cls = ServerBusyCode when ?4 then ServerBusyCode
when ?5 then when ?5 then
case stat[1] case stat[1]
when ?0 then cls = SyntaxErrorCode when ?0 then SyntaxErrorCode
when ?5 then cls = FatalErrorCode when ?5 then FatalErrorCode
end end
end end
return cls.new( stat, arr.join('') ) klass.new( stat, arr.join('') )
end end