mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
o protocol.rb: version 1.1.9
o smtp.rb: arguments discription of do_ready was wrongly void git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
688169fd83
commit
d8d148d816
4 changed files with 285 additions and 347 deletions
359
lib/net/http.rb
359
lib/net/http.rb
|
@ -38,11 +38,14 @@ class HTTPBadResponse < HTTPError; end
|
||||||
|
|
||||||
== Methods
|
== Methods
|
||||||
|
|
||||||
: get( path, header = nil, ret = '' )
|
: get( path, header = nil, dest = '' )
|
||||||
|
: get( path, header = nil ) {|str| .... }
|
||||||
get data from "path" on connecting host.
|
get data from "path" on connecting host.
|
||||||
"header" is a Hash like { 'Accept' => '*/*', ... }.
|
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||||
The data will be written to "ret" using "<<" method.
|
Data is written to "dest" by using "<<" method.
|
||||||
This method returns response header (Hash) and "ret".
|
This method returns response header (Hash) and "dest".
|
||||||
|
|
||||||
|
If called as iterator, give a part String of entity body.
|
||||||
|
|
||||||
: head( path, header = nil )
|
: head( path, header = nil )
|
||||||
get only header from "path" on connecting host.
|
get only header from "path" on connecting host.
|
||||||
|
@ -53,6 +56,30 @@ class HTTPBadResponse < HTTPError; end
|
||||||
'content-type' => 'Content-Type: text/html',
|
'content-type' => 'Content-Type: text/html',
|
||||||
... }
|
... }
|
||||||
|
|
||||||
|
: post( path, data, header = nil, dest = '' )
|
||||||
|
: post( path, data, header = nil ) {|str| .... }
|
||||||
|
post "data"(must be String now) to "path" (and get entity body).
|
||||||
|
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||||
|
Data is written to "dest" by using "<<" method.
|
||||||
|
This method returns response header (Hash) and "dest".
|
||||||
|
|
||||||
|
If called as iterator, give a part String of entity body.
|
||||||
|
|
||||||
|
ATTENTION: entity body could be empty
|
||||||
|
|
||||||
|
: get2( path, header = nil )
|
||||||
|
send GET request for "path".
|
||||||
|
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||||
|
This method returns response header (Hash).
|
||||||
|
|
||||||
|
: get_body( dest = '' )
|
||||||
|
: get_body {|str| .... }
|
||||||
|
gets entity body of forwarded 'get2' or 'post2' methods.
|
||||||
|
Data is written in "dest" by using "<<" method.
|
||||||
|
This method returns "dest".
|
||||||
|
|
||||||
|
If called as iterator, give a part String of entity body.
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
class HTTP < Protocol
|
class HTTP < Protocol
|
||||||
|
@ -61,19 +88,71 @@ class HTTPBadResponse < HTTPError; end
|
||||||
protocol_param :command_type, '::Net::HTTPCommand'
|
protocol_param :command_type, '::Net::HTTPCommand'
|
||||||
|
|
||||||
|
|
||||||
def get( path, u_header = nil, ret = '' )
|
def get( path, u_header = nil, dest = nil, &block )
|
||||||
u_header ||= {}
|
u_header ||= {}
|
||||||
header = connecting( u_header ) {
|
if block then
|
||||||
@command.get ret, edit_path(path), u_header
|
dest = ReadAdapter.new( block )
|
||||||
|
ret = nil
|
||||||
|
else
|
||||||
|
dest = ret = ''
|
||||||
|
end
|
||||||
|
resp = nil
|
||||||
|
connecting( u_header ) {
|
||||||
|
@command.get edit_path(path), u_header
|
||||||
|
resp = @command.get_response
|
||||||
|
@command.try_get_body( resp, dest )
|
||||||
}
|
}
|
||||||
|
|
||||||
return header, ret
|
return resp['http-header'], ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def head( path, u_header = nil )
|
def get2( path, u_header = {} )
|
||||||
|
only_header( :get, path, u_header )
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_body( dest = '', &block )
|
||||||
|
if block then
|
||||||
|
dest = ReadAdapter.new( block )
|
||||||
|
end
|
||||||
|
@command.try_get_body @response, dest
|
||||||
|
ensure_termination @u_header
|
||||||
|
|
||||||
|
dest
|
||||||
|
end
|
||||||
|
|
||||||
|
def head( path, u_header = {} )
|
||||||
|
ret = only_header( :head, path, u_header )['http-header']
|
||||||
|
ensure_termination u_header
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def post( path, data, u_header = nil, dest = nil, &block )
|
||||||
u_header ||= {}
|
u_header ||= {}
|
||||||
header = connecting( u_header ) {
|
if block then
|
||||||
@command.head edit_path(path), u_header
|
dest = ReadAdapter.new( block )
|
||||||
|
ret = nil
|
||||||
|
else
|
||||||
|
dest = ret = ''
|
||||||
|
end
|
||||||
|
resp = nil
|
||||||
|
connecting( u_header, true ) {
|
||||||
|
@command.post path, u_header, data
|
||||||
|
resp = @command.get_response
|
||||||
|
@command.try_get_body( resp, dest )
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp['http-header'], ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def post2( path, data, u_header = {} )
|
||||||
|
only_header :post, path, u_header, data
|
||||||
|
end
|
||||||
|
|
||||||
|
# not tested because I could not setup apache (__;;;
|
||||||
|
def put( path, src = nil, u_header = {}, &block )
|
||||||
|
u_header ||= u_header
|
||||||
|
connecting( u_header, true ) {
|
||||||
|
@command.put path, u_header, src, dest
|
||||||
}
|
}
|
||||||
|
|
||||||
header
|
header
|
||||||
|
@ -83,30 +162,51 @@ class HTTPBadResponse < HTTPError; end
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
|
def only_header( mid, path, u_header, data = nil )
|
||||||
|
@u_header = u_header ? procheader(u_header) : {}
|
||||||
|
@response = nil
|
||||||
|
ensure_connection @u_header
|
||||||
|
if data then
|
||||||
|
@command.send mid, edit_path(path), @u_header, data
|
||||||
|
else
|
||||||
|
@command.send mid, edit_path(path), @u_header
|
||||||
|
end
|
||||||
|
@response = @command.get_response
|
||||||
|
@response['http-header']
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# called when connecting
|
# called when connecting
|
||||||
def do_finish
|
def do_finish
|
||||||
unless @socket.closed? then
|
unless @socket.closed? then
|
||||||
@command.head '/', { 'Connection' => 'Close' }
|
begin
|
||||||
|
@command.head '/', { 'Connection' => 'Close' }
|
||||||
|
rescue EOFError
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def connecting( u_header )
|
def connecting( u_header, putp = false )
|
||||||
u_header = procheader( u_header )
|
u_header = procheader( u_header )
|
||||||
|
ensure_connection u_header
|
||||||
|
yield
|
||||||
|
ensure_termination u_header
|
||||||
|
end
|
||||||
|
|
||||||
|
def ensure_connection( u_header )
|
||||||
if not @socket then
|
if not @socket then
|
||||||
u_header['Connection'] = 'Close'
|
u_header['Connection'] = 'Close'
|
||||||
start
|
start
|
||||||
elsif @socket.closed? then
|
elsif @socket.closed? then
|
||||||
@socket.reopen
|
@socket.reopen
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
header = yield
|
def ensure_termination( u_header )
|
||||||
|
|
||||||
unless keep_alive? u_header then
|
unless keep_alive? u_header then
|
||||||
@socket.close
|
@socket.close
|
||||||
end
|
end
|
||||||
|
@u_header = @response = nil
|
||||||
header
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def keep_alive?( header )
|
def keep_alive?( header )
|
||||||
|
@ -155,6 +255,20 @@ class HTTPBadResponse < HTTPError; end
|
||||||
HTTPSession = HTTP
|
HTTPSession = HTTP
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPSuccessCode < SuccessCode; end
|
||||||
|
class HTTPCreatedCode < SuccessCode; end
|
||||||
|
class HTTPAcceptedCode < SuccessCode; end
|
||||||
|
class HTTPNoContentCode < SuccessCode; end
|
||||||
|
class HTTPResetContentCode < SuccessCode; end
|
||||||
|
class HTTPPartialContentCode < SuccessCode; end
|
||||||
|
|
||||||
|
class HTTPMultipleChoiceCode < RetryCode; end
|
||||||
|
class HTTPMovedPermanentlyCode < RetryCode; end
|
||||||
|
class HTTPMovedTemporarilyCode < RetryCode; end
|
||||||
|
class HTTPNotModifiedCode < RetryCode; end
|
||||||
|
class HTTPUseProxyCode < RetryCode; end
|
||||||
|
|
||||||
|
|
||||||
class HTTPCommand < Command
|
class HTTPCommand < Command
|
||||||
|
|
||||||
HTTPVersion = '1.1'
|
HTTPVersion = '1.1'
|
||||||
|
@ -173,40 +287,25 @@ class HTTPBadResponse < HTTPError; end
|
||||||
|
|
||||||
attr_reader :http_version
|
attr_reader :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
|
def get( path, u_header )
|
||||||
clen = read_chunked_body( ret )
|
request sprintf('GET %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
header.delete 'transfer-encoding'
|
end
|
||||||
header[ 'content-length' ] = "Content-Length: #{clen}"
|
|
||||||
else
|
def head( path, u_header )
|
||||||
if clen = content_length( header ) then
|
request sprintf('HEAD %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
@socket.read clen, ret
|
|
||||||
else
|
|
||||||
@socket.read_all ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
header
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def post( path, u_header, data )
|
||||||
def head( path, u_header = nil )
|
request sprintf('POST %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
get_response sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header
|
@socket.write data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def put( path, u_header, src )
|
||||||
# not work
|
request sprintf('PUT %s HTTP/%s', path, HTTPVersion), u_header
|
||||||
def post( path, u_header = nil )
|
@socket.write_bin src
|
||||||
get_response sprintf( 'POST %s HTTP/%s', path, HTTPVersion ), u_header
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# not work
|
|
||||||
def put( path, u_header = nil )
|
|
||||||
get_response sprintf( 'PUT %s HTTP/%s', path, HTTPVersion ), u_header
|
|
||||||
end
|
|
||||||
|
|
||||||
# def delete
|
# def delete
|
||||||
|
|
||||||
|
@ -215,19 +314,64 @@ class HTTPBadResponse < HTTPError; end
|
||||||
# def options
|
# def options
|
||||||
|
|
||||||
|
|
||||||
|
def get_response
|
||||||
|
rep = get_reply
|
||||||
|
rep = get_reply while ContinueCode === rep
|
||||||
|
header = {}
|
||||||
|
while true do
|
||||||
|
line = @socket.readline
|
||||||
|
break if line.empty?
|
||||||
|
nm = /\A[^:]+/.match( line )[0].strip.downcase
|
||||||
|
header[nm] = line
|
||||||
|
end
|
||||||
|
|
||||||
|
rep['http-header'] = header
|
||||||
|
reply_must rep, SuccessCode
|
||||||
|
|
||||||
|
rep
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_body( rep, dest )
|
||||||
|
header = rep['http-header']
|
||||||
|
if chunked? header then
|
||||||
|
read_chunked( dest, header )
|
||||||
|
else
|
||||||
|
if clen = content_length( header ) then
|
||||||
|
@socket.read clen, dest
|
||||||
|
else
|
||||||
|
###
|
||||||
|
### "multipart/bytelenges" check should be done here ...
|
||||||
|
###
|
||||||
|
@socket.read_all dest
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def try_get_body( rep, dest )
|
||||||
|
rep = get_reply while ContinueCode === rep
|
||||||
|
return nil unless rep['body-exist']
|
||||||
|
|
||||||
|
get_body rep, dest
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
def get_response( line, u_header )
|
def request( req, u_header )
|
||||||
@socket.writeline line
|
@socket.writeline req
|
||||||
write_header u_header
|
if u_header then
|
||||||
rep = get_reply
|
header = @in_header.dup.update( u_header )
|
||||||
header = read_header
|
else
|
||||||
reply_must rep, SuccessCode
|
header = @in_header
|
||||||
|
end
|
||||||
header
|
header.each do |n,v|
|
||||||
|
@socket.writeline n + ': ' + v
|
||||||
|
end
|
||||||
|
@socket.writeline ''
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def get_reply
|
def get_reply
|
||||||
str = @socket.readline
|
str = @socket.readline
|
||||||
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
|
unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then
|
||||||
|
@ -237,20 +381,66 @@ class HTTPBadResponse < HTTPError; end
|
||||||
status = $2
|
status = $2
|
||||||
discrip = $3
|
discrip = $3
|
||||||
|
|
||||||
|
be = false
|
||||||
klass = case status[0]
|
klass = case status[0]
|
||||||
when ?1 then
|
when ?1 then
|
||||||
case status[2]
|
case status[2]
|
||||||
when ?0 then ContinueCode
|
when ?0 then ContinueCode
|
||||||
when ?1 then SuccessCode
|
when ?1 then HTTPSuccessCode
|
||||||
|
else UnknownCode
|
||||||
|
end
|
||||||
|
when ?2 then
|
||||||
|
case status[2]
|
||||||
|
when ?0 then be = true; HTTPSuccessCode
|
||||||
|
when ?1 then be = false; HTTPSuccessCode
|
||||||
|
when ?2 then be = true; HTTPSuccessCode
|
||||||
|
when ?3 then be = true; HTTPSuccessCode
|
||||||
|
when ?4 then be = false; HTTPNoContentCode
|
||||||
|
when ?5 then be = false; HTTPResetContentCode
|
||||||
|
when ?6 then be = true; HTTPPartialContentCode
|
||||||
|
else UnknownCode
|
||||||
|
end
|
||||||
|
when ?3 then
|
||||||
|
case status[2]
|
||||||
|
when ?0 then be = true; HTTPMultipleChoiceCode
|
||||||
|
when ?1 then be = true; HTTPMovedPermanentryCode
|
||||||
|
when ?2 then be = true; HTTPMovedTemporarilyCode
|
||||||
|
when ?3 then be = true; HTTPMovedPermanentryCode
|
||||||
|
when ?4 then be = false; HTTPNotModifiedCode
|
||||||
|
when ?5 then be = false; HTTPUseProxyCode
|
||||||
else UnknownCode
|
else UnknownCode
|
||||||
end
|
end
|
||||||
when ?2 then SuccessCode
|
|
||||||
when ?3 then RetryCode
|
|
||||||
when ?4 then ServerBusyCode
|
when ?4 then ServerBusyCode
|
||||||
when ?5 then FatalErrorCode
|
when ?5 then FatalErrorCode
|
||||||
else UnknownCode
|
else UnknownCode
|
||||||
end
|
end
|
||||||
klass.new( status, discrip )
|
code = klass.new( status, discrip )
|
||||||
|
code['body-exist'] = be
|
||||||
|
code
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_chunked( ret, header )
|
||||||
|
line = nil
|
||||||
|
len = nil
|
||||||
|
total = 0
|
||||||
|
|
||||||
|
while true do
|
||||||
|
line = @socket.readline
|
||||||
|
unless /[0-9a-hA-H]+/ === line then
|
||||||
|
raise HTTPBadResponse, "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
|
||||||
|
|
||||||
|
header.delete 'transfer-encoding'
|
||||||
|
header[ 'content-length' ] = "Content-Length: #{total}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,63 +464,6 @@ class HTTPBadResponse < HTTPError; end
|
||||||
false
|
false
|
||||||
end
|
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 HTTPBadResponse, "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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -216,66 +216,6 @@ Net::POP3
|
||||||
APOPSession = APOP
|
APOPSession = APOP
|
||||||
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
== Net::POP3Command
|
|
||||||
|
|
||||||
POP3 command class.
|
|
||||||
|
|
||||||
=== Super Class
|
|
||||||
|
|
||||||
Net::Command
|
|
||||||
|
|
||||||
=== Class Methods
|
|
||||||
|
|
||||||
: new( socket )
|
|
||||||
This method creates new POP3Command object. 'socket' must be ProtocolSocket.
|
|
||||||
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
: auth( account, password )
|
|
||||||
This method do POP authorization (no RPOP)
|
|
||||||
In case of failed authorization, raises Protocol::ProtocolError exception.
|
|
||||||
|
|
||||||
: list
|
|
||||||
a list of mails which existing on server.
|
|
||||||
The list is an array like "array[ number ] = size".
|
|
||||||
|
|
||||||
ex:
|
|
||||||
|
|
||||||
The list from server is
|
|
||||||
|
|
||||||
1 2452
|
|
||||||
2 3355
|
|
||||||
4 9842
|
|
||||||
:
|
|
||||||
|
|
||||||
then, an array is
|
|
||||||
|
|
||||||
[ nil, 2452, 3355, nil, 9842, ... ]
|
|
||||||
|
|
||||||
: quit
|
|
||||||
This method ends POP using 'QUIT' commmand.
|
|
||||||
|
|
||||||
: rset
|
|
||||||
This method reset all changes done in current session,
|
|
||||||
by sending 'RSET' command.
|
|
||||||
|
|
||||||
: top( num, lines = 0 )
|
|
||||||
This method gets all mail header and 'lines' lines body
|
|
||||||
by sending 'TOP' command. 'num' is mail number.
|
|
||||||
|
|
||||||
WARNING: the TOP command is 'Optional' in RFC1939 (POP3)
|
|
||||||
|
|
||||||
: retr( num : Integer )
|
|
||||||
This method gets a mail by 'RETR' command. 'num' is mail number.
|
|
||||||
|
|
||||||
: dele( num : Integer )
|
|
||||||
This method deletes a mail on server by 'DELE'.
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
|
|
||||||
class POP3Command < Command
|
class POP3Command < Command
|
||||||
|
|
||||||
|
@ -371,22 +311,6 @@ Net::Command
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
== APOPCommand
|
|
||||||
|
|
||||||
=== Super Class
|
|
||||||
|
|
||||||
POP3Command
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
: auth( account, password )
|
|
||||||
This method do authorization by sending 'APOP' command.
|
|
||||||
If server is not APOP server, this raises Net::ProtoAuthError exception.
|
|
||||||
On other errors, raises Net::ProtocolError.
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
class APOPCommand < POP3Command
|
class APOPCommand < POP3Command
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ require 'socket'
|
||||||
|
|
||||||
module Net
|
module Net
|
||||||
|
|
||||||
Version = '1.1.7'
|
Version = '1.1.9'
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
|
@ -219,27 +219,6 @@ Object
|
||||||
Session = Protocol
|
Session = Protocol
|
||||||
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
== Net::Command
|
|
||||||
|
|
||||||
=== Super Class
|
|
||||||
|
|
||||||
Object
|
|
||||||
|
|
||||||
=== Class Methods
|
|
||||||
|
|
||||||
: new( socket )
|
|
||||||
This method create new Command object. 'socket' must be ProtocolSocket.
|
|
||||||
This method is abstract class.
|
|
||||||
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
: quit
|
|
||||||
This method dispatch command which ends the protocol.
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
class Command
|
class Command
|
||||||
|
|
||||||
|
@ -317,10 +296,26 @@ Object
|
||||||
def initialize( cod, mes )
|
def initialize( cod, mes )
|
||||||
@code = cod
|
@code = cod
|
||||||
@msg = mes
|
@msg = mes
|
||||||
|
@data = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :code, :msg
|
attr_reader :code, :msg
|
||||||
|
|
||||||
|
def []( key )
|
||||||
|
if @data then
|
||||||
|
@data[key]
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def []=( key, val )
|
||||||
|
unless h = @data then
|
||||||
|
@data = h = {}
|
||||||
|
end
|
||||||
|
h[key] = val
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def error!( sending )
|
def error!( sending )
|
||||||
mes = <<MES
|
mes = <<MES
|
||||||
|
@ -370,78 +365,6 @@ MES
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
== Net::ProtocolSocket
|
|
||||||
|
|
||||||
=== Super Class
|
|
||||||
|
|
||||||
Object
|
|
||||||
|
|
||||||
=== Class Methods
|
|
||||||
|
|
||||||
: new( address = 'localhost', port = nil )
|
|
||||||
This create new ProtocolSocket object, and connect to server.
|
|
||||||
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
: close
|
|
||||||
This method closes socket.
|
|
||||||
|
|
||||||
: address, addr
|
|
||||||
a FQDN address of server
|
|
||||||
|
|
||||||
: ip_address, ipaddr
|
|
||||||
an IP address of server
|
|
||||||
|
|
||||||
: port
|
|
||||||
connecting port number.
|
|
||||||
|
|
||||||
: closed?
|
|
||||||
true if ProtocolSokcet have been closed already
|
|
||||||
|
|
||||||
|
|
||||||
: read( length )
|
|
||||||
This method read 'length' bytes and return the string.
|
|
||||||
|
|
||||||
: readuntil( target )
|
|
||||||
This method read until find 'target'. Returns read string.
|
|
||||||
|
|
||||||
: readline
|
|
||||||
read until "\r\n" and returns it without "\r\n".
|
|
||||||
|
|
||||||
: read_pendstr
|
|
||||||
This method read until "\r\n.\r\n".
|
|
||||||
At the same time, delete period at line head and final line ("\r\n.\r\n").
|
|
||||||
|
|
||||||
: read_pendlist
|
|
||||||
: read_pendlist{|line| .... }
|
|
||||||
This method read until "\r\n.\r\n". This method resembles to 'read_pendstr',
|
|
||||||
but 'read_pendlist' don't check period at line head, and returns array which
|
|
||||||
each element is one line.
|
|
||||||
|
|
||||||
When this method was called with block, evaluate it for each reading a line.
|
|
||||||
|
|
||||||
|
|
||||||
: write( src )
|
|
||||||
This method send 'src'. ProtocolSocket read strings from 'src' by 'each'
|
|
||||||
iterator. This method returns written bytes.
|
|
||||||
|
|
||||||
: writebin( src )
|
|
||||||
This method send 'src'. ProtocolSokcet read string from 'src' by 'each'
|
|
||||||
iterator. This method returns written bytes.
|
|
||||||
|
|
||||||
: writeline( str )
|
|
||||||
This method writes 'str'. There has not to be bare "\r" or "\n" in 'str'.
|
|
||||||
|
|
||||||
: write_pendstr( src )
|
|
||||||
This method writes 'src' as a mail.
|
|
||||||
ProtocolSocket reads strings from 'src' by 'each' iterator.
|
|
||||||
This returns written bytes.
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
|
|
||||||
class WriteAdapter
|
class WriteAdapter
|
||||||
|
|
||||||
|
@ -639,6 +562,13 @@ Object
|
||||||
public
|
public
|
||||||
|
|
||||||
|
|
||||||
|
def write( str )
|
||||||
|
do_write_beg
|
||||||
|
do_write_do str
|
||||||
|
do_write_fin
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def writeline( str )
|
def writeline( str )
|
||||||
do_write_beg
|
do_write_beg
|
||||||
do_write_do str
|
do_write_do str
|
||||||
|
@ -647,10 +577,10 @@ Object
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def writebin( src )
|
def write_bin( src, block = nil )
|
||||||
do_write_beg
|
do_write_beg
|
||||||
if iterator? then
|
if block then
|
||||||
yield WriteAdapter.new( self, :do_write_do )
|
block.call WriteAdapter.new( self, :do_write_do )
|
||||||
else
|
else
|
||||||
src.each do |bin|
|
src.each do |bin|
|
||||||
do_write_do bin
|
do_write_do bin
|
||||||
|
@ -660,18 +590,6 @@ Object
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def write( src )
|
|
||||||
do_write_beg
|
|
||||||
if iterator? then
|
|
||||||
yield WriteAdapter.new( self, :write_inner )
|
|
||||||
else
|
|
||||||
write_inner src
|
|
||||||
end
|
|
||||||
each_crlf_line2( :i_w )
|
|
||||||
do_write_fin
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def write_pendstr( src )
|
def write_pendstr( src )
|
||||||
@pipe << "writing text from #{src.type}\n" if pre = @pipe ; @pipe = nil
|
@pipe << "writing text from #{src.type}\n" if pre = @pipe ; @pipe = nil
|
||||||
|
|
||||||
|
|
|
@ -74,15 +74,14 @@ Net::Protocol
|
||||||
protocol_param :command_type, '::Net::SMTPCommand'
|
protocol_param :command_type, '::Net::SMTPCommand'
|
||||||
|
|
||||||
|
|
||||||
def sendmail( mailsrc, fromaddr, toaddrs, &block )
|
def sendmail( mailsrc, fromaddr, toaddrs )
|
||||||
@command.mailfrom fromaddr
|
do_ready fromaddr, toaddrs
|
||||||
@command.rcpt toaddrs
|
@command.write_mail mailsrc
|
||||||
@command.data
|
|
||||||
@command.write_mail( mailsrc, &block )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def ready( fromaddr, toaddrs, &block )
|
def ready( fromaddr, toaddrs, &block )
|
||||||
sendmail nil, fromaddr, toaddrs, &block
|
do_ready fromaddr, toaddrs
|
||||||
|
@command.write_mail( &block )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +91,12 @@ Net::Protocol
|
||||||
private
|
private
|
||||||
|
|
||||||
|
|
||||||
|
def do_ready( fromaddr, toaddrs )
|
||||||
|
@command.mailfrom fromaddr
|
||||||
|
@command.rcpt toaddrs
|
||||||
|
@command.data
|
||||||
|
end
|
||||||
|
|
||||||
def do_start( helodom = ENV['HOSTNAME'] )
|
def do_start( helodom = ENV['HOSTNAME'] )
|
||||||
unless helodom then
|
unless helodom then
|
||||||
raise ArgumentError, "cannot get hostname"
|
raise ArgumentError, "cannot get hostname"
|
||||||
|
@ -111,48 +116,6 @@ Net::Protocol
|
||||||
SMTPSession = SMTP
|
SMTPSession = SMTP
|
||||||
|
|
||||||
|
|
||||||
=begin
|
|
||||||
|
|
||||||
== Net::SMTPCommand
|
|
||||||
|
|
||||||
=== Super Class
|
|
||||||
|
|
||||||
Net::Command
|
|
||||||
|
|
||||||
=== Class Methods
|
|
||||||
|
|
||||||
: new( socket )
|
|
||||||
This method creates new SMTPCommand object, and open SMTP.
|
|
||||||
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
: helo( helo_domain )
|
|
||||||
This method send "HELO" command and start SMTP.
|
|
||||||
helo_domain is localhost's FQDN.
|
|
||||||
|
|
||||||
: mailfrom( from_addr )
|
|
||||||
This method sends "MAIL FROM" command.
|
|
||||||
from_addr is your mail address (xxxx@xxxx)
|
|
||||||
|
|
||||||
: rcpt( to_addrs )
|
|
||||||
This method sends "RCPT TO" command.
|
|
||||||
to_addrs is array of mail address (xxxx@xxxx) of destination.
|
|
||||||
|
|
||||||
: data
|
|
||||||
This method sends "DATA" command.
|
|
||||||
|
|
||||||
: write_mail( mailsrc )
|
|
||||||
: write_mail {|socket| ... }
|
|
||||||
send 'mailsrc' as mail.
|
|
||||||
SMTPCommand reads strings from 'mailsrc' by calling 'each' iterator.
|
|
||||||
When iterator, SMTPCommand only stand by socket and pass it.
|
|
||||||
(The socket will accepts only 'in_write' method in the block)
|
|
||||||
|
|
||||||
: quit
|
|
||||||
This method sends "QUIT" command and ends SMTP session.
|
|
||||||
|
|
||||||
=end
|
|
||||||
|
|
||||||
class SMTPCommand < Command
|
class SMTPCommand < Command
|
||||||
|
|
||||||
|
@ -189,7 +152,7 @@ Net::Command
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def write_mail( mailsrc, &block )
|
def write_mail( mailsrc = nil, &block )
|
||||||
@socket.write_pendstr mailsrc, &block
|
@socket.write_pendstr mailsrc, &block
|
||||||
check_reply SuccessCode
|
check_reply SuccessCode
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue