mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
aamine
* lib/net/pop.rb: new methods POP3.auth_only, POP3#auth_only * lib/net/http.rb: HTTP.Proxy returns self if ADDRESS is nil. * lib/net/protocol.rb: new method ProtocolError#response * lib/net/protocol.rb,smtp.rb,pop.rb,http.rb: add document. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1546 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
10e80b2402
commit
c664027a34
5 changed files with 743 additions and 376 deletions
|
@ -1,3 +1,12 @@
|
|||
Wed Jun 27 08:53:26 2001 Minero Aoki <#e(:global).g(:email)>\n
|
||||
* lib/net/pop.rb: new methods POP3.auth_only, POP3#auth_only
|
||||
|
||||
* lib/net/http.rb: HTTP.Proxy returns self if ADDRESS is nil.
|
||||
|
||||
* lib/net/protocol.rb: new method ProtocolError#response
|
||||
|
||||
* lib/net/protocol.rb,smtp.rb,pop.rb,http.rb: add document.
|
||||
|
||||
Sat Jun 23 18:28:52 2001 Akinori MUSHA <knu@iDaemons.org>
|
||||
|
||||
* ext/readline/readline.c (readline_event): a non-void function
|
||||
|
|
478
lib/net/http.rb
478
lib/net/http.rb
|
@ -1,125 +1,304 @@
|
|||
=begin
|
||||
|
||||
= net/http.rb version 1.2.0
|
||||
= net/http.rb version 1.2.1
|
||||
|
||||
Copyright (C) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||
This file is derived from "http-access.rb".
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
This file is derived from "http-access.rb".
|
||||
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
GNU General Public License or Ruby License.
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
Ruby Distribute License or GNU General Public License.
|
||||
|
||||
Japanese version of this document is in "net" full package.
|
||||
You can get it from RAA (Ruby Application Archive). RAA is:
|
||||
http://www.ruby-lang.org/en/raa.html
|
||||
NOTE: You can get Japanese version of this document from
|
||||
Ruby Documentation Project (RDP):
|
||||
((<URL:http://www.ruby-lang.org/~rubikitch/RDP.cgi>))
|
||||
|
||||
== What is this module?
|
||||
|
||||
This module provide your program the functions to access WWW
|
||||
documents via HTTP, Hyper Text Transfer Protocol version 1.1.
|
||||
For details of HTTP, refer [RFC2616]
|
||||
((<URL:http://www.ietf.org/rfc/rfc2616.txt>)).
|
||||
|
||||
== Examples
|
||||
|
||||
=== Getting Document From Server
|
||||
|
||||
Be care to ',' (comma) putted after "response".
|
||||
This is required for feature compatibility.
|
||||
|
||||
require 'net/http'
|
||||
Net::HTTP.start( 'some.www.server', 80 ) {|http|
|
||||
response , = http.get('/index.html')
|
||||
puts response.body
|
||||
}
|
||||
|
||||
(shorter version)
|
||||
|
||||
require 'net/http'
|
||||
Net::HTTP.get_print 'some.www.server', '/index.html'
|
||||
|
||||
=== Posting Form Data
|
||||
|
||||
require 'net/http'
|
||||
Net::HTTP.start( 'some.www.server', 80 ) {|http|
|
||||
response , = http.post( '/cgi-bin/any.rhtml',
|
||||
'querytype=subject&target=ruby' )
|
||||
}
|
||||
|
||||
=== Accessing via Proxy
|
||||
|
||||
Net::HTTP.Proxy() creates http proxy class. It has same
|
||||
methods of Net::HTTP but its instances always connect to
|
||||
proxy, instead of given host.
|
||||
|
||||
require 'net/http'
|
||||
|
||||
$proxy_addr = 'your.proxy.addr'
|
||||
$proxy_port = 8080
|
||||
:
|
||||
Net::HTTP::Proxy($proxy_addr, $proxy_port).start( 'some.www.server' ) {|http|
|
||||
# always connect to your.proxy.addr:8080
|
||||
:
|
||||
}
|
||||
|
||||
Since Net::HTTP.Proxy() returns Net::HTTP itself when $proxy_addr is nil,
|
||||
there's no need to change code if there's proxy or not.
|
||||
|
||||
=== Redirect
|
||||
|
||||
require 'net/http'
|
||||
Net::HTTP.version_1_1
|
||||
|
||||
host = 'www.ruby-lang.org'
|
||||
begin
|
||||
Net::HTTP.start( host, 80 ) {|http|
|
||||
response , = http.get('/')
|
||||
}
|
||||
rescue Net::ProtoRetriableError => err
|
||||
if m = %r<http:([^/]+)>.match( err.response['location'] ) then
|
||||
host = m[1].strip
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
NOTE: This code is using ad-hoc way to extract host name, but in future
|
||||
URI class will be included in ruby standard library.
|
||||
|
||||
=== Basic Authentication
|
||||
|
||||
require 'net/http'
|
||||
|
||||
Net::HTTP.start( 'auth.some.domain' ) {|http|
|
||||
response , = http.get( '/need-auth.cgi',
|
||||
'Authentication' => ["#{account}:#{password}"].pack('m').strip )
|
||||
print response.body
|
||||
}
|
||||
|
||||
In version 1.2 (Ruby 1.7 or later), you can write like this:
|
||||
|
||||
require 'net/http'
|
||||
|
||||
req = Net::HTTP::Get.new('/need-auth.cgi')
|
||||
req.basic_auth 'account', 'password'
|
||||
Net::HTTP.start( 'auth.some.domain' ) {|http|
|
||||
response = http.request( req )
|
||||
print response.body
|
||||
}
|
||||
|
||||
== Switching Net::HTTP versions
|
||||
|
||||
You can use old Net::HTTP (in Ruby 1.6) features by calling
|
||||
HTTP.version_1_1. And calling Net::HTTP.version_1_2 allows
|
||||
you to use 1.2 features again.
|
||||
|
||||
# example
|
||||
Net::HTTP.start {|http1| ...(http1 has 1.2 features)... }
|
||||
|
||||
Net::HTTP.version_1_1
|
||||
Net::HTTP.start {|http2| ...(http2 has 1.1 features)... }
|
||||
|
||||
Net::HTTP.version_1_2
|
||||
Net::HTTP.start {|http3| ...(http3 has 1.2 features)... }
|
||||
|
||||
Yes, this is not thread-safe.
|
||||
|
||||
== class Net::HTTP
|
||||
|
||||
=== Class Methods
|
||||
|
||||
: new( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
|
||||
creates a new Net::HTTP object.
|
||||
If proxy_addr is given, this method is equals to
|
||||
Net::HTTP::Proxy(proxy_addr,proxy_port).
|
||||
creates a new Net::HTTP object.
|
||||
If proxy_addr is given, this method is equals to
|
||||
Net::HTTP::Proxy(proxy_addr,proxy_port).
|
||||
|
||||
: start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
|
||||
: start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) {|http| .... }
|
||||
is equals to
|
||||
is equals to
|
||||
|
||||
Net::HTTP.new( address, port, proxy_addr, proxy_port ).start(&block)
|
||||
Net::HTTP.new(address, port, proxy_addr, proxy_port).start(&block)
|
||||
|
||||
: get( address, path, port = 80 )
|
||||
gets entity body from path and returns it.
|
||||
return value is a String.
|
||||
gets entity body from path and returns it.
|
||||
return value is a String.
|
||||
|
||||
: get_print( address, path, port = 80 )
|
||||
gets entity body from path and print it.
|
||||
return value is an entity body (a String).
|
||||
gets entity body from path and print it.
|
||||
return value is an entity body (a String).
|
||||
|
||||
: Proxy( address, port )
|
||||
creates a HTTP proxy class.
|
||||
Arguments are address/port of proxy host.
|
||||
You can replace HTTP class by this proxy class.
|
||||
: Proxy( address, port = 80 )
|
||||
creates a HTTP proxy class.
|
||||
Arguments are address/port of proxy host.
|
||||
You can replace HTTP class by this proxy class.
|
||||
|
||||
# example
|
||||
proxy_http = HTTP::Proxy( 'proxy.foo.org', 8080 )
|
||||
:
|
||||
proxy_http.start( 'www.ruby-lang.org' ) do |http|
|
||||
# connecting proxy.foo.org:8080
|
||||
:
|
||||
end
|
||||
If ADDRESS is nil, this method returns self (Net::HTTP class).
|
||||
|
||||
# example
|
||||
proxy_class = Net::HTTP::Proxy( 'proxy.foo.org', 8080 )
|
||||
:
|
||||
proxy_class.start( 'www.ruby-lang.org' ) do |http|
|
||||
# connecting proxy.foo.org:8080
|
||||
:
|
||||
end
|
||||
|
||||
: proxy_class?
|
||||
If self is HTTP, false.
|
||||
If self is a class which was created by HTTP::Proxy(), true.
|
||||
If self is HTTP, false.
|
||||
If self is a class which was created by HTTP::Proxy(), true.
|
||||
|
||||
: port
|
||||
HTTP default port (80).
|
||||
|
||||
HTTP default port (80).
|
||||
|
||||
=== Instance Methods
|
||||
|
||||
: start
|
||||
: start {|http| .... }
|
||||
creates a new Net::HTTP object and starts HTTP session.
|
||||
creates a new Net::HTTP object and starts HTTP session.
|
||||
|
||||
When this method is called with block, gives HTTP object to block
|
||||
and close HTTP session after block call finished.
|
||||
When this method is called with block, gives a HTTP object to block
|
||||
and close the HTTP session after block call finished.
|
||||
|
||||
: active?
|
||||
true if HTTP session is started.
|
||||
|
||||
: address
|
||||
the address to connect
|
||||
|
||||
: port
|
||||
the port number to connect
|
||||
|
||||
: open_timeout
|
||||
: open_timeout=(n)
|
||||
seconds to wait until connection is opened.
|
||||
If HTTP object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: read_timeout
|
||||
: read_timeout=(n)
|
||||
seconds to wait until reading one block (by one read(1) call).
|
||||
If HTTP object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: finish
|
||||
finishes HTTP session.
|
||||
If HTTP session had not started, do nothing and return false.
|
||||
|
||||
: proxy?
|
||||
true if self is a HTTP proxy class
|
||||
true if self is a HTTP proxy class
|
||||
|
||||
: proxy_address
|
||||
address of proxy host. If self is not a proxy, nil.
|
||||
address of proxy host. If self is not a proxy, nil.
|
||||
|
||||
: proxy_port
|
||||
port number of proxy host. If self is not a proxy, nil.
|
||||
port number of proxy host. If self is not a proxy, nil.
|
||||
|
||||
: get( path, header = nil, dest = '' )
|
||||
: get( path, header = nil ) {|str| .... }
|
||||
gets data from "path" on connecting host.
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
Response body is written into "dest" by using "<<" method.
|
||||
This method returns Net::HTTPResponse object.
|
||||
gets data from "path" on connecting host.
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
Response body is written into "dest" by using "<<" method.
|
||||
This method returns Net::HTTPResponse object.
|
||||
|
||||
# example
|
||||
response = http.get( '/index.html' )
|
||||
If called with block, give a part String of entity body.
|
||||
|
||||
If called with block, give a part String of entity body.
|
||||
In version 1.1, this method might raises exception for also
|
||||
3xx (redirect). On the case you can get response object by
|
||||
err.response.
|
||||
|
||||
In version 1.2, this method never raises exception.
|
||||
|
||||
# version 1.1 (Ruby 1.6)
|
||||
response, body = http.get( '/index.html' )
|
||||
|
||||
# version 1.2 (Ruby 1.7 or later)
|
||||
response = http.get( '/index.html' )
|
||||
|
||||
# compatible in both version
|
||||
response , = http.get( '/index.html' )
|
||||
response.body
|
||||
|
||||
# using block
|
||||
File.open( 'save.txt', 'w' ) {|f|
|
||||
http.get( '/~foo/', nil ) do |str|
|
||||
f.write str
|
||||
end
|
||||
}
|
||||
# some effect
|
||||
File.open( 'save.txt', 'w' ) {|f|
|
||||
http.get '/~foo/', nil, f
|
||||
}
|
||||
|
||||
: head( path, header = nil )
|
||||
gets only header from "path" on connecting host.
|
||||
"header" is a Hash like { 'Accept' => '*/*', ... }.
|
||||
This method returns a Net::HTTPResponse object.
|
||||
You can http header from this object like:
|
||||
gets only header from "path" on connecting host.
|
||||
"header" is a Hash like { 'Accept' => '*/*', ... }.
|
||||
This method returns a Net::HTTPResponse object.
|
||||
You can http header from this object like:
|
||||
|
||||
response['content-length'] #-> '2554'
|
||||
response['content-type'] #-> 'text/html'
|
||||
response['Content-Type'] #-> 'text/html'
|
||||
response['CoNtEnT-tYpe'] #-> 'text/html'
|
||||
response = nil
|
||||
Net::HTTP.start( 'some.www.server', 80 ) {|http|
|
||||
response = http.head( '/index.html' )
|
||||
}
|
||||
response['content-length'] #-> '2554'
|
||||
response['content-type'] #-> 'text/html'
|
||||
response['Content-Type'] #-> 'text/html'
|
||||
response['CoNtEnT-tYpe'] #-> 'text/html'
|
||||
|
||||
: post( path, data, header = nil, dest = '' )
|
||||
: post( path, data, header = nil ) {|str| .... }
|
||||
posts "data" (must be String) to "path".
|
||||
If the body exists, also gets entity body.
|
||||
Response body is written into "dest" by using "<<" method.
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
This method returns Net::HTTPResponse object.
|
||||
posts "data" (must be String) to "path".
|
||||
If the body exists, also gets entity body.
|
||||
Response body is written into "dest" by using "<<" method.
|
||||
"header" must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
This method returns Net::HTTPResponse object.
|
||||
|
||||
If called with block, gives a part of entity body string.
|
||||
If called with block, gives a part of entity body string.
|
||||
|
||||
# version 1.1
|
||||
response, body = http.post( '/index.html', 'querytype=subject&target=ruby' )
|
||||
# version 1.2
|
||||
response = http.post( '/index.html', 'querytype=subject&target=ruby' )
|
||||
# compatible for both version
|
||||
response , = http.post( '/index.html', 'querytype=subject&target=ruby' )
|
||||
|
||||
: request( request, [src] )
|
||||
# using block
|
||||
File.open( 'save.html', 'w' ) {|f|
|
||||
http.post( '/index.html', 'querytype=subject&target=ruby' ) do |str|
|
||||
f.write str
|
||||
end
|
||||
}
|
||||
# same effect
|
||||
File.open( 'save.html', 'w' ) {|f|
|
||||
http.post '/index.html', 'querytype=subject&target=ruby', nil, f
|
||||
}
|
||||
|
||||
: request( request, [data] )
|
||||
: request( request, [src] ) {|response| .... }
|
||||
sends REQUEST to (remote) http server. This method also writes
|
||||
string from SRC before it if REQUEST is a post/put request.
|
||||
(giving SRC for get/head request causes ArgumentError.)
|
||||
|
||||
If called with block, gives a HTTP response object to the block.
|
||||
sends REQUEST to (remote) http server. This method also writes
|
||||
string from DATA string if REQUEST is a post/put request.
|
||||
(giving DATA for get/head request causes ArgumentError.)
|
||||
|
||||
If called with block, gives a HTTPResponse object to the block.
|
||||
|
||||
== class Net::HTTP::Get, Head, Post
|
||||
|
||||
|
@ -131,7 +310,7 @@ entity path. All arguments named "key" is case-insensitive.
|
|||
: new
|
||||
creats HTTP request object.
|
||||
|
||||
=== Methods
|
||||
=== Instance Methods
|
||||
|
||||
: self[ key ]
|
||||
returns the header field corresponding to the case-insensitive key.
|
||||
|
@ -140,13 +319,32 @@ entity path. All arguments named "key" is case-insensitive.
|
|||
: self[ key ] = val
|
||||
sets the header field corresponding to the case-insensitive key.
|
||||
|
||||
: each {|name, val| .... }
|
||||
iterates for each field name and value pair.
|
||||
|
||||
: basic_auth( account, password )
|
||||
set Authorization: header for basic auth.
|
||||
|
||||
: range
|
||||
returns a Range object which represents Range: header field.
|
||||
|
||||
: range = r
|
||||
: set_range( i, len )
|
||||
set Range: header from Range (arg r) or beginning index and
|
||||
length from it (arg i&len).
|
||||
|
||||
: content_length
|
||||
returns a Integer object which represents Content-Length: header field.
|
||||
|
||||
: content_range
|
||||
returns a Range object which represents Content-Range: header field.
|
||||
|
||||
== class Net::HTTPResponse
|
||||
|
||||
HTTP response class. This class wraps response header and entity.
|
||||
All arguments named KEY is case-insensitive.
|
||||
|
||||
=== Methods
|
||||
=== Instance Methods
|
||||
|
||||
: self[ key ]
|
||||
returns the header field corresponding to the case-insensitive key.
|
||||
|
@ -166,7 +364,7 @@ All arguments named KEY is case-insensitive.
|
|||
iterates for each field name and value pair.
|
||||
|
||||
: canonical_each {|name,value| .... }
|
||||
iterates for each canonical field name and value pair.
|
||||
iterates for each "canonical" field name and value pair.
|
||||
|
||||
: code
|
||||
HTTP result code string. For example, '302'.
|
||||
|
@ -175,34 +373,18 @@ All arguments named KEY is case-insensitive.
|
|||
HTTP result message. For example, 'Not Found'.
|
||||
|
||||
: read_body( dest = '' )
|
||||
gets response body and write it into DEST using "<<" method.
|
||||
gets entity body and write it into DEST using "<<" method.
|
||||
If this method is called twice or more, nothing will be done
|
||||
and returns first DEST.
|
||||
|
||||
: read_body {|str| .... }
|
||||
gets response body little by little and pass it to block.
|
||||
gets entity body little by little and pass it to block.
|
||||
|
||||
: body
|
||||
response body. If #read_body has been called, this method
|
||||
returns arg of #read_body, DEST. Else gets body as String
|
||||
and returns it.
|
||||
response body. If #read_body has been called, this method returns
|
||||
arg of #read_body DEST. Else gets body as String and returns it.
|
||||
|
||||
|
||||
== Switching Net::HTTP versions
|
||||
|
||||
You can use Net::HTTP 1.1 features by calling HTTP.version_1_1 .
|
||||
And calling Net::HTTP.version_1_2 allows you to use 1.2 features
|
||||
again.
|
||||
|
||||
# example
|
||||
HTTP.start {|http1| ...(http1 has 1.2 features)... }
|
||||
|
||||
HTTP.version_1_1
|
||||
HTTP.start {|http2| ...(http2 has 1.1 features)... }
|
||||
|
||||
HTTP.version_1_2
|
||||
HTTP.start {|http3| ...(http3 has 1.2 features)... }
|
||||
|
||||
=end
|
||||
|
||||
require 'net/protocol'
|
||||
|
@ -224,18 +406,13 @@ module Net
|
|||
|
||||
protocol_param :port, '80'
|
||||
|
||||
|
||||
def initialize( addr = nil, port = nil )
|
||||
super
|
||||
|
||||
@proxy_address = nil
|
||||
@proxy_port = nil
|
||||
|
||||
@curr_http_version = HTTPVersion
|
||||
@seems_1_0_server = false
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def conn_command( sock )
|
||||
|
@ -255,7 +432,11 @@ module Net
|
|||
class << self
|
||||
|
||||
def Proxy( p_addr, p_port = nil )
|
||||
ProxyMod.create_proxy_class( p_addr, p_port || self.port )
|
||||
if p_addr then
|
||||
ProxyMod.create_proxy_class( p_addr, p_port || self.port )
|
||||
else
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
alias orig_new new
|
||||
|
@ -271,32 +452,34 @@ module Net
|
|||
new( address, port, p_addr, p_port ).start( &block )
|
||||
end
|
||||
|
||||
@is_proxy_class = false
|
||||
@proxy_addr = nil
|
||||
@proxy_port = nil
|
||||
|
||||
def proxy_class?
|
||||
false
|
||||
@is_proxy_class
|
||||
end
|
||||
|
||||
def proxy_address
|
||||
nil
|
||||
end
|
||||
|
||||
def proxy_port
|
||||
nil
|
||||
end
|
||||
attr_reader :proxy_address
|
||||
attr_reader :proxy_port
|
||||
|
||||
end
|
||||
|
||||
def proxy?
|
||||
false
|
||||
type.proxy?
|
||||
end
|
||||
|
||||
def proxy_address
|
||||
nil
|
||||
type.proxy_address
|
||||
end
|
||||
|
||||
def proxy_port
|
||||
nil
|
||||
type.proxy_port
|
||||
end
|
||||
|
||||
alias proxyaddr proxy_address
|
||||
alias proxyport proxy_port
|
||||
|
||||
def edit_path( path )
|
||||
path
|
||||
end
|
||||
|
@ -304,52 +487,22 @@ module Net
|
|||
|
||||
module ProxyMod
|
||||
|
||||
class << self
|
||||
|
||||
def create_proxy_class( p_addr, p_port )
|
||||
mod = self
|
||||
klass = Class.new( HTTP )
|
||||
klass.module_eval {
|
||||
include mod
|
||||
@proxy_address = p_addr
|
||||
@proxy_port = p_port
|
||||
}
|
||||
def klass.proxy_class?
|
||||
true
|
||||
end
|
||||
|
||||
def klass.proxy_address
|
||||
@proxy_address
|
||||
end
|
||||
|
||||
def klass.proxy_port
|
||||
@proxy_port
|
||||
end
|
||||
|
||||
klass
|
||||
end
|
||||
|
||||
def self.create_proxy_class( p_addr, p_port )
|
||||
mod = self
|
||||
klass = Class.new( HTTP )
|
||||
klass.module_eval {
|
||||
include mod
|
||||
@is_proxy = true
|
||||
@proxy_address = p_addr
|
||||
@proxy_port = p_port
|
||||
}
|
||||
klass
|
||||
end
|
||||
|
||||
def initialize( addr, port )
|
||||
super
|
||||
@proxy_address = type.proxy_address
|
||||
@proxy_port = type.proxy_port
|
||||
end
|
||||
|
||||
attr_reader :proxy_address, :proxy_port
|
||||
|
||||
alias proxyaddr proxy_address
|
||||
alias proxyport proxy_port
|
||||
|
||||
def proxy?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def conn_socket( addr, port )
|
||||
super @proxy_address, @proxy_port
|
||||
super proxy_address, proxy_port
|
||||
end
|
||||
|
||||
def edit_path( path )
|
||||
|
@ -363,7 +516,11 @@ module Net
|
|||
# for backward compatibility
|
||||
#
|
||||
|
||||
@@newimpl = true
|
||||
if Version < '1.2.0' then ###noupdate
|
||||
@@newimpl = false
|
||||
else
|
||||
@@newimpl = true
|
||||
end
|
||||
|
||||
class << self
|
||||
|
||||
|
@ -375,6 +532,10 @@ module Net
|
|||
@@newimpl = false
|
||||
end
|
||||
|
||||
def is_version_1_2?
|
||||
@@newimpl
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setvar( obj )
|
||||
|
@ -662,15 +823,15 @@ module Net
|
|||
|
||||
d1 = m[1].to_i
|
||||
d2 = m[2].to_i
|
||||
if m[1] and m[2] then arr.push (d1 .. d2)
|
||||
elsif m[1] then arr.push (d1 .. -1)
|
||||
elsif m[2] then arr.push (-d2 .. -1)
|
||||
if m[1] and m[2] then arr.push d1..d2
|
||||
elsif m[1] then arr.push d1..-1
|
||||
elsif m[2] then arr.push -d2..-1
|
||||
else
|
||||
raise HTTPHeaderSyntaxError, 'range is not specified'
|
||||
end
|
||||
end
|
||||
|
||||
return *arr
|
||||
return arr
|
||||
end
|
||||
|
||||
def range=( r, fin = nil )
|
||||
|
@ -906,7 +1067,10 @@ module Net
|
|||
@buf.concat s
|
||||
end
|
||||
|
||||
alias << write
|
||||
def <<( s )
|
||||
@buf.concat s
|
||||
self
|
||||
end
|
||||
|
||||
def terminate
|
||||
ret = @buf
|
||||
|
@ -1028,7 +1192,7 @@ module Net
|
|||
end
|
||||
|
||||
def value
|
||||
SuccessCode === self or error! self
|
||||
SuccessCode === self or error!
|
||||
end
|
||||
|
||||
|
||||
|
@ -1134,4 +1298,8 @@ module Net
|
|||
|
||||
}
|
||||
|
||||
|
||||
HTTPResponse = NetPrivate::HTTPResponse
|
||||
HTTPResponseReceiver = NetPrivate::HTTPResponse
|
||||
|
||||
end # module Net
|
||||
|
|
335
lib/net/pop.rb
335
lib/net/pop.rb
|
@ -1,25 +1,115 @@
|
|||
=begin
|
||||
|
||||
= net/pop.rb version 1.2.0
|
||||
= net/pop.rb version 1.2.1
|
||||
|
||||
Copyright (C) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
GNU General Public License or Ruby License.
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
Ruby Distribute License or GNU General Public License.
|
||||
|
||||
Japanese version of this document is in "net" full package.
|
||||
You can get it from RAA (Ruby Application Archive). RAA is:
|
||||
http://www.ruby-lang.org/en/raa.html
|
||||
NOTE: You can get Japanese version of this document from
|
||||
Ruby Documentation Project (RDP):
|
||||
((<URL:http://www.ruby-lang.org/~rubikitch/RDP.cgi>))
|
||||
|
||||
== What is This Module?
|
||||
|
||||
This module provides your program the functions to retrieve
|
||||
mails via POP3, Post Office Protocol version 3. For details
|
||||
of POP3, refer [RFC1939] ((<URL:http://www.ietf.org/rfc/rfc1939.txt>)).
|
||||
|
||||
== Examples
|
||||
|
||||
=== Retrieving Mails
|
||||
|
||||
This example retrieves mails from server and delete it (on server).
|
||||
Mails are written in file named 'inbox/1', 'inbox/2', ....
|
||||
Replace 'pop3.server.address' your POP3 server address.
|
||||
|
||||
|
||||
== Net::POP3
|
||||
require 'net/pop'
|
||||
|
||||
=== Super Class
|
||||
Net::POP3.start( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) {|pop|
|
||||
if pop.mails.empty? then
|
||||
puts 'no mail.'
|
||||
else
|
||||
i = 0
|
||||
pop.each_mail do |m| # or "pop.mails.each ..."
|
||||
File.open( 'inbox/' + i.to_s, 'w' ) do |f|
|
||||
f.write m.pop
|
||||
end
|
||||
m.delete
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
puts "#{pop.mails.size} mails popped."
|
||||
}
|
||||
|
||||
Net::Protocol
|
||||
=== Shorter Version
|
||||
|
||||
require 'net/pop'
|
||||
i = 0
|
||||
Net::POP3.start( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) {|pop|
|
||||
pop.delete_all do |m|
|
||||
File.open( 'inbox/' + i.to_s, 'w' ) {|f|
|
||||
f.write m.pop
|
||||
}
|
||||
i += 1
|
||||
end
|
||||
}
|
||||
|
||||
And this is more shorter example.
|
||||
|
||||
require 'net/pop'
|
||||
i = 0
|
||||
Net::POP3.delete_all( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) do |m|
|
||||
File.open( 'inbox/' + i.to_s, 'w' ) {|f|
|
||||
f.write m.pop
|
||||
}
|
||||
i += 1
|
||||
end
|
||||
|
||||
=== Writing to File directly
|
||||
|
||||
All examples above get mail as one big string.
|
||||
This example does not create such one.
|
||||
|
||||
require 'net/pop'
|
||||
Net::POP3.delete_all( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) do |m|
|
||||
File.open( 'inbox', 'w' ) {|f|
|
||||
m.pop f ####
|
||||
}
|
||||
end
|
||||
|
||||
=== Using APOP
|
||||
|
||||
net/pop also supports APOP authentication. There's two way to use APOP:
|
||||
(1) using APOP class instead of POP3
|
||||
(2) passing true for fifth argument of POP3.start
|
||||
|
||||
# (1)
|
||||
require 'net/pop'
|
||||
Net::APOP.start( 'apop.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) {|pop|
|
||||
# Rest code is same.
|
||||
}
|
||||
|
||||
# (2)
|
||||
require 'net/pop'
|
||||
Net::POP3.start( 'apop.server.address', 110,
|
||||
'YourAccount', 'YourPassword',
|
||||
true ####
|
||||
) {|pop|
|
||||
# Rest code is same.
|
||||
}
|
||||
|
||||
== Net::POP3 class
|
||||
|
||||
=== Class Methods
|
||||
|
||||
|
@ -31,10 +121,9 @@ Net::Protocol
|
|||
: start( address = 'localhost', port = 110, account, password ) {|pop| .... }
|
||||
equals to Net::POP3.new( address, port ).start( account, password )
|
||||
|
||||
# typical usage
|
||||
Net::POP3.start( addr, port, acnt, pass ) do |pop|
|
||||
Net::POP3.start( addr, port, account, password ) do |pop|
|
||||
pop.each_mail do |m|
|
||||
any_file.write m.pop
|
||||
file.write m.pop
|
||||
m.delete
|
||||
end
|
||||
end
|
||||
|
@ -49,9 +138,8 @@ Net::Protocol
|
|||
end
|
||||
end
|
||||
|
||||
.
|
||||
Typical usage:
|
||||
|
||||
# typical usage
|
||||
Net::POP3.foreach( addr, nil, acnt, pass ) do |m|
|
||||
m.pop file
|
||||
m.delete
|
||||
|
@ -59,120 +147,140 @@ Net::Protocol
|
|||
|
||||
: delete_all( address = 'localhost', port = 110, account, password )
|
||||
: delete_all( address = 'localhost', port = 110, account, password ) {|mail| .... }
|
||||
starts POP3 session and delete all mails.
|
||||
If block is given, iterates for each POPMail object before delete.
|
||||
starts POP3 session and delete all mails.
|
||||
If block is given, iterates for each POPMail object before delete.
|
||||
|
||||
# example
|
||||
Net::POP3.delete_all( addr, nil, 'YourAccount', 'YourPassword' ) do |m|
|
||||
m.pop file
|
||||
end
|
||||
|
||||
: auth_only( address = 'localhost', port = 110, account, password )
|
||||
(just for POP-before-SMTP)
|
||||
opens POP3 session and does autholize and quit.
|
||||
This method must not be called while POP3 session is opened.
|
||||
|
||||
# example
|
||||
pop = Net::POP3.auth_only( 'your.pop3.server',
|
||||
nil, # using default (110)
|
||||
'YourAccount',
|
||||
'YourPassword' )
|
||||
|
||||
# typical usage
|
||||
Net::POP3.delete_all( addr, nil, acnt, pass ) do |m|
|
||||
m.pop file
|
||||
end
|
||||
|
||||
=== Instance Methods
|
||||
|
||||
: start( account, password )
|
||||
: start( account, password ) {|pop| .... }
|
||||
starts POP3 session.
|
||||
starts POP3 session.
|
||||
|
||||
When called with block, gives a POP3 object to block and
|
||||
closes the session after block call finish.
|
||||
When called with block, gives a POP3 object to block and
|
||||
closes the session after block call finish.
|
||||
|
||||
: active?
|
||||
true if POP3 session is started.
|
||||
|
||||
: address
|
||||
the address to connect
|
||||
|
||||
: port
|
||||
the port number to connect
|
||||
|
||||
: open_timeout
|
||||
: open_timeout=(n)
|
||||
seconds to wait until connection is opened.
|
||||
If POP3 object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: read_timeout
|
||||
: read_timeout=(n)
|
||||
seconds to wait until reading one block (by one read(1) call).
|
||||
If POP3 object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: finish
|
||||
finishes POP3 session.
|
||||
If POP3 session had not be started, does nothing and return false.
|
||||
|
||||
: mails
|
||||
an array of ((URL:#POPMail)).
|
||||
This array is renewed when session started.
|
||||
an array of Net::POPMail objects.
|
||||
This array is renewed when session started.
|
||||
|
||||
: each_mail {|popmail| .... }
|
||||
: each {|popmail| .... }
|
||||
is equals to "pop3.mails.each"
|
||||
is equals to "pop3.mails.each"
|
||||
|
||||
: delete_all
|
||||
: delete_all {|popmail| .... }
|
||||
deletes all mails.
|
||||
If called with block, gives mails to the block before deleting.
|
||||
deletes all mails on server.
|
||||
If called with block, gives mails to the block before deleting.
|
||||
|
||||
# example 1
|
||||
# pop and delete all mails
|
||||
n = 1
|
||||
pop.delete_all do |m|
|
||||
File.open("inbox/#{n}") {|f| f.write m.pop }
|
||||
n += 1
|
||||
end
|
||||
# example
|
||||
n = 1
|
||||
pop.delete_all do |m|
|
||||
File.open("inbox/#{n}") {|f| f.write m.pop }
|
||||
n += 1
|
||||
end
|
||||
|
||||
# example 2
|
||||
# clear all mails on server
|
||||
Net::POP3.start( addr, port, acc, pass ) do |pop|
|
||||
pop.delete_all
|
||||
end
|
||||
: auth_only( account, password )
|
||||
(just for POP-before-SMTP)
|
||||
opens POP3 session and does autholize and quit.
|
||||
This method must not be called while POP3 session is opened.
|
||||
# example
|
||||
pop = Net::POP3.new( 'your.pop3.server' )
|
||||
pop.auth_only 'YourAccount', 'YourPassword'
|
||||
|
||||
: reset
|
||||
reset the session. All "deleted mark" are removed.
|
||||
|
||||
|
||||
== Net::APOP
|
||||
|
||||
This class defines no new methods.
|
||||
Only difference from POP3 is using APOP authentification.
|
||||
|
||||
=== Super Class
|
||||
|
||||
Net::POP3
|
||||
|
||||
|
||||
== Net::POPMail
|
||||
|
||||
A class of mail which exists on POP server.
|
||||
|
||||
=== Super Class
|
||||
|
||||
Object
|
||||
|
||||
|
||||
=== Methods
|
||||
=== Instance Methods
|
||||
|
||||
: pop( dest = '' )
|
||||
This method fetches a mail and write to 'dest' using '<<' method.
|
||||
This method fetches a mail and write to 'dest' using '<<' method.
|
||||
|
||||
# usage example
|
||||
|
||||
mailarr = []
|
||||
POP3.start( 'localhost', 110 ) do |pop|
|
||||
pop.each_mail do |popm|
|
||||
mailarr.push popm.pop # all() returns 'dest' (this time, string)
|
||||
# or, you can also
|
||||
# popm.pop( $stdout ) # write mail to stdout
|
||||
|
||||
# maybe you also want to delete mail after popping
|
||||
popm.delete
|
||||
end
|
||||
end
|
||||
# example
|
||||
allmails = nil
|
||||
POP3.start( 'your.pop3.server', 110,
|
||||
'YourAccount, 'YourPassword' ) do |pop|
|
||||
allmails = pop.mails.collect {|popmail| popmail.pop }
|
||||
end
|
||||
|
||||
: pop {|str| .... }
|
||||
If pop() is called with block, it gives the block part strings of a mail.
|
||||
gives the block part strings of a mail.
|
||||
|
||||
# usage example
|
||||
|
||||
POP3.start( 'localhost', 110 ) do |pop3|
|
||||
pop3.each_mail do |m|
|
||||
m.pop do |str|
|
||||
# do anything
|
||||
end
|
||||
end
|
||||
end
|
||||
# example
|
||||
POP3.start( 'localhost', 110 ) {|pop3|
|
||||
pop3.each_mail do |m|
|
||||
m.pop do |str|
|
||||
# do anything
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
: header
|
||||
This method fetches only mail header.
|
||||
This method fetches only mail header.
|
||||
|
||||
: top( lines )
|
||||
This method fetches mail header and 'lines' lines body.
|
||||
This method fetches mail header and LINES lines of body.
|
||||
|
||||
: delete
|
||||
: delete!
|
||||
This method deletes mail.
|
||||
deletes mail on server.
|
||||
|
||||
: size
|
||||
size of mail(bytes)
|
||||
mail size (bytes)
|
||||
|
||||
: deleted?
|
||||
true if mail was deleted
|
||||
true if mail was deleted
|
||||
|
||||
=end
|
||||
|
||||
|
@ -205,7 +313,12 @@ module Net
|
|||
pop.delete_all( &block )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def auth_only( address = nil, port = nil,
|
||||
account = nil, password = nil )
|
||||
new( address, port ).auth_only account, password
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -215,6 +328,18 @@ module Net
|
|||
@apop = false
|
||||
end
|
||||
|
||||
def auth_only( account = nil, password = nil )
|
||||
begin
|
||||
connect
|
||||
@active = true
|
||||
@command.auth address, port
|
||||
@command.quit
|
||||
ensure
|
||||
@active = false
|
||||
disconnect
|
||||
end
|
||||
end
|
||||
|
||||
attr :mails
|
||||
|
||||
def each_mail( &block )
|
||||
|
@ -225,6 +350,7 @@ module Net
|
|||
alias each each_mail
|
||||
|
||||
def delete_all
|
||||
io_check
|
||||
@mails.each do |m|
|
||||
yield m if block_given?
|
||||
m.delete unless m.deleted?
|
||||
|
@ -247,23 +373,20 @@ module Net
|
|||
(@apop ? type.apop_command_type : type.command_type).new(sock)
|
||||
end
|
||||
|
||||
def do_start( acnt, pwd )
|
||||
@command.auth( acnt, pwd )
|
||||
def do_start( account, password )
|
||||
@command.auth account, password
|
||||
|
||||
@mails = []
|
||||
mails = []
|
||||
mtype = type.mail_type
|
||||
@command.list.each_with_index do |size,idx|
|
||||
if size then
|
||||
@mails.push mtype.new( idx, size, @command )
|
||||
end
|
||||
mails.push mtype.new(idx, size, @command) if size
|
||||
end
|
||||
@mails.freeze
|
||||
@mails = mails.freeze
|
||||
end
|
||||
|
||||
def io_check
|
||||
if not @socket or @socket.closed? then
|
||||
raise IOError, 'pop session is not opened yet'
|
||||
end
|
||||
(not @socket or @socket.closed?) and
|
||||
raise IOError, 'pop session is not opened yet'
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -359,8 +482,9 @@ module Net
|
|||
critical {
|
||||
getok 'LIST'
|
||||
@socket.read_pendlist do |line|
|
||||
num, siz = line.split( / +/o )
|
||||
arr[ num.to_i ] = siz.to_i
|
||||
m = /\A(\d+)[ \t]+(\d+)/.match(line) or
|
||||
raise BadResponse, "illegal response: #{line}"
|
||||
arr[ m[1].to_i ] = m[2].to_i
|
||||
end
|
||||
}
|
||||
arr
|
||||
|
@ -376,26 +500,26 @@ module Net
|
|||
def top( num, lines = 0, dest = '' )
|
||||
critical {
|
||||
getok sprintf( 'TOP %d %d', num, lines )
|
||||
@socket.read_pendstr( dest )
|
||||
@socket.read_pendstr dest
|
||||
}
|
||||
end
|
||||
|
||||
def retr( num, dest = '', &block )
|
||||
critical {
|
||||
getok sprintf( 'RETR %d', num )
|
||||
@socket.read_pendstr( dest, &block )
|
||||
getok sprintf('RETR %d', num)
|
||||
@socket.read_pendstr dest, &block
|
||||
}
|
||||
end
|
||||
|
||||
def dele( num )
|
||||
critical {
|
||||
getok sprintf( 'DELE %d', num )
|
||||
getok sprintf('DELE %d', num)
|
||||
}
|
||||
end
|
||||
|
||||
def uidl( num )
|
||||
critical {
|
||||
getok( sprintf 'UIDL %d', num ).msg.split(' ')[1]
|
||||
getok( sprintf('UIDL %d', num) ).msg.split(' ')[1]
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -436,17 +560,16 @@ module Net
|
|||
def initialize( sock )
|
||||
rep = super( sock )
|
||||
|
||||
m = /<.+>/.match( rep.msg )
|
||||
unless m then
|
||||
raise ProtoAuthError, "This is not APOP server: can't login"
|
||||
end
|
||||
m = /<.+>/.match( rep.msg ) or
|
||||
raise ProtoAuthError, "not APOP server: cannot login"
|
||||
@stamp = m[0]
|
||||
end
|
||||
|
||||
def auth( account, pass )
|
||||
critical {
|
||||
@socket.writeline sprintf( 'APOP %s %s',
|
||||
account, MD5.new(@stamp + pass).hexdigest )
|
||||
account,
|
||||
MD5.new(@stamp + pass).hexdigest )
|
||||
check_reply_auth
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,62 +1,18 @@
|
|||
=begin
|
||||
|
||||
= net/protocol.rb version 1.2.0
|
||||
= net/protocol.rb version 1.2.1
|
||||
|
||||
Copyright (C) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
GNU General Public License or Ruby License.
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
Ruby Distribute License or GNU General Public License.
|
||||
|
||||
Japanese version of this document is in "net" full package.
|
||||
You can get it from RAA (Ruby Application Archive). RAA is:
|
||||
http://www.ruby-lang.org/en/raa.html
|
||||
|
||||
|
||||
== Net::Protocol
|
||||
|
||||
the abstract class for some internet protocols
|
||||
|
||||
=== Super Class
|
||||
|
||||
Object
|
||||
|
||||
=== Class Methods
|
||||
|
||||
: new( address = 'localhost', port = nil )
|
||||
This method Creates a new protocol object.
|
||||
|
||||
: start( address = 'localhost', port = nil, *protoargs )
|
||||
: start( address = 'localhost', port = nil, *protoargs ) {|proto| .... }
|
||||
This method creates a new Protocol object and opens a session.
|
||||
equals to Net::Protocol.new( address, port ).start( *protoargs )
|
||||
|
||||
=== Methods
|
||||
|
||||
: address
|
||||
the address of connecting server (FQDN).
|
||||
|
||||
: port
|
||||
connecting port number
|
||||
|
||||
: start( *args )
|
||||
: start( *args ) {|proto| .... }
|
||||
This method starts protocol. If protocol was already started,
|
||||
do nothing and returns false.
|
||||
|
||||
'*args' are specified in subclasses.
|
||||
|
||||
When is called with block, gives Protocol object to block and
|
||||
close session when block finished.
|
||||
|
||||
: finish
|
||||
This method ends protocol. If you call this method before protocol starts,
|
||||
it only return false without doing anything.
|
||||
|
||||
: active?
|
||||
true if session have been started
|
||||
NOTE: You can get Japanese version of this document from
|
||||
Ruby Documentation Project (RDP):
|
||||
((<URL:http://www.ruby-lang.org/~rubikitch/RDP.cgi>))
|
||||
|
||||
=end
|
||||
|
||||
|
@ -76,8 +32,7 @@ module Net
|
|||
|
||||
class Protocol
|
||||
|
||||
Version = '1.2.0'
|
||||
|
||||
Version = '1.2.1'
|
||||
|
||||
class << self
|
||||
|
||||
|
@ -106,13 +61,17 @@ module Net
|
|||
|
||||
|
||||
#
|
||||
# sub-class requirements
|
||||
# --- Configuration Staffs for Sub Classes ---
|
||||
#
|
||||
# protocol_param command_type
|
||||
# protocol_param port
|
||||
# protocol_param port
|
||||
# protocol_param command_type
|
||||
# protocol_param socket_type (optional)
|
||||
#
|
||||
# private method do_start (optional)
|
||||
# private method do_finish (optional)
|
||||
# private method do_start (optional)
|
||||
# private method do_finish (optional)
|
||||
#
|
||||
# private method on_connect (optional)
|
||||
# private method on_disconnect (optional)
|
||||
#
|
||||
|
||||
protocol_param :port, 'nil'
|
||||
|
@ -267,8 +226,8 @@ module Net
|
|||
"#<#{type} #{code}>"
|
||||
end
|
||||
|
||||
def error!( data = nil )
|
||||
raise code_type.error_type.new( code + ' ' + Net.quote(msg), data )
|
||||
def error!
|
||||
raise code_type.error_type.new( code + ' ' + Net.quote(msg), self )
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -288,12 +247,13 @@ module Net
|
|||
|
||||
class ProtocolError
|
||||
|
||||
def initialize( msg, data = nil )
|
||||
def initialize( msg, resp )
|
||||
super msg
|
||||
@data = data
|
||||
@response = resp
|
||||
end
|
||||
|
||||
attr :data
|
||||
attr :response
|
||||
alias data response
|
||||
|
||||
def inspect
|
||||
"#<#{type}>"
|
||||
|
@ -644,7 +604,7 @@ module Net
|
|||
|
||||
# private use only (can not handle 'break')
|
||||
def read_pendlist
|
||||
D_off 'reading list...'
|
||||
# D_off 'reading list...'
|
||||
|
||||
str = nil
|
||||
i = 0
|
||||
|
@ -654,7 +614,7 @@ module Net
|
|||
yield str
|
||||
end
|
||||
|
||||
D_on "read #{i} items"
|
||||
# D_on "read #{i} items"
|
||||
end
|
||||
|
||||
|
||||
|
|
203
lib/net/smtp.rb
203
lib/net/smtp.rb
|
@ -1,86 +1,193 @@
|
|||
=begin
|
||||
|
||||
= net/smtp.rb version 1.2.0
|
||||
= net/smtp.rb version 1.2.1
|
||||
|
||||
Copyright (C) 1999-2001 Yukihiro Matsumoto
|
||||
Copyright (c) 1999-2001 Yukihiro Matsumoto
|
||||
|
||||
written & maintained by Minero Aoki <aamine@dp.u-netsurf.ne.jp>
|
||||
written & maintained by Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
GNU General Public License or Ruby License.
|
||||
This program is free software. You can re-distribute and/or
|
||||
modify this program under the same terms as Ruby itself,
|
||||
Ruby Distribute License or GNU General Public License.
|
||||
|
||||
Japanese version of this document is in "net" full package.
|
||||
You can get it from RAA (Ruby Application Archive). RAA is:
|
||||
http://www.ruby-lang.org/en/raa.html
|
||||
NOTE: You can get Japanese version of this document from
|
||||
Ruby Documentation Project (RDP):
|
||||
((<URL:http://www.ruby-lang.org/~rubikitch/RDP.cgi>))
|
||||
|
||||
== What is This Module?
|
||||
|
||||
== Net::SMTP
|
||||
This module provides your program the functions to send internet
|
||||
mail via SMTP, Simple Mail Transfer Protocol. For details of
|
||||
SMTP itself, refer [RFC2821] ((<URL:http://www.ietf.org/rfc/rfc2821.txt>)).
|
||||
|
||||
=== Super Class
|
||||
== What This Module is NOT?
|
||||
|
||||
Net::Protocol
|
||||
This module does NOT provide the functions to compose internet
|
||||
mail. You must create it by yourself. For details of internet mail
|
||||
format, see [RFC2822] ((<URL:http://www.ietf.org/rfc/rfc2822.txt>)).
|
||||
|
||||
== Examples
|
||||
|
||||
=== Sending Mail
|
||||
|
||||
You must open connection to SMTP server before sending mails.
|
||||
First argument is the address of SMTP server, and second argument
|
||||
is port number. Using SMTP.start with block is the most simple way
|
||||
to do it. SMTP Connection is closed automatically after block is
|
||||
executed.
|
||||
|
||||
require 'net/smtp'
|
||||
Net::SMTP.start( 'your.smtp.server', 25 ) {|smtp|
|
||||
# use smtp object only in this block
|
||||
}
|
||||
|
||||
Replace 'your.smtp.server' by your SMTP server. Normally
|
||||
your system manager or internet provider is supplying a server
|
||||
for you.
|
||||
|
||||
Then you can send mail.
|
||||
|
||||
require 'net/smtp'
|
||||
|
||||
Net::SMTP.start( 'your.smtp.server', 25 ) {|smtp|
|
||||
smtp.send_mail <<EndOfMail, 'your@mail.address', 'to@some.domain'
|
||||
From: Your Name <your@mail.address>
|
||||
To: Dest Address <to@some.domain>
|
||||
Subject: test mail
|
||||
Date: Sat, 23 Jun 2001 16:26:43 +0900
|
||||
Message-Id: <unique.message.id.string@some.domain>
|
||||
|
||||
This is test mail.
|
||||
EndOfMail
|
||||
}
|
||||
|
||||
=== Sending Mails from Any Sources
|
||||
|
||||
In an example above I sent mail from String (here document literal).
|
||||
SMTP#send_mail accepts any objects which has "each" method
|
||||
like File and Array.
|
||||
|
||||
require 'net/smtp'
|
||||
Net::SMTP.start( 'your.smtp.server', 25 ) {|smtp|
|
||||
File.open( 'Mail/draft/1' ) {|f|
|
||||
smtp.send_mail f, 'your@mail.address', 'to@some.domain'
|
||||
}
|
||||
}
|
||||
|
||||
=== Giving "Hello" Domain
|
||||
|
||||
If your machine does not have canonical host name, maybe you
|
||||
must designate the third argument of SMTP.start.
|
||||
|
||||
Net::SMTP.start( 'your.smtp.server', 25,
|
||||
'mail.from.domain' ) {|smtp|
|
||||
|
||||
This argument gives MAILFROM domain, the domain name that
|
||||
you send mail from. SMTP server might judge if he (or she?)
|
||||
send or reject SMTP session by this data.
|
||||
|
||||
== class Net::SMTP
|
||||
|
||||
=== Class Methods
|
||||
|
||||
: new( address = 'localhost', port = 25 )
|
||||
creates a new Net::SMTP object.
|
||||
|
||||
: start( address = 'localhost', port = 25, *protoargs )
|
||||
: start( address = 'localhost', port = 25, *protoargs ) {|smtp| .... }
|
||||
is equal to Net::SMTP.new( address, port ).start( *protoargs )
|
||||
: start( address = 'localhost', port = 25, helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil )
|
||||
: start( address = 'localhost', port = 25, helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil ) {|smtp| .... }
|
||||
is equal to
|
||||
Net::SMTP.new(address,port).start(helo_domain,account,password,authtype)
|
||||
|
||||
=== Methods
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {
|
||||
smtp.send_mail mail_string, 'from@mail.address', 'dest@mail.address'
|
||||
}
|
||||
|
||||
: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil )
|
||||
: start( helo_domain = Socket.gethostname, account = nil, password = nil, authtype = nil ) {|smtp| .... }
|
||||
=== Instance Methods
|
||||
|
||||
: start( helo_domain = <local host name>, account = nil, password = nil, authtype = nil )
|
||||
: start( helo_domain = <local host name>, account = nil, password = nil, authtype = nil ) {|smtp| .... }
|
||||
opens TCP connection and starts SMTP session.
|
||||
If protocol had been started, do nothing and return false.
|
||||
HELO_DOMAIN is a domain that you'll dispatch mails from.
|
||||
|
||||
When this methods is called with block, give a SMTP object to block and
|
||||
close session after block call finished.
|
||||
|
||||
If account and password are given, is trying to get authentication
|
||||
by using AUTH command. "authtype" is :plain (symbol) or :cram_md5.
|
||||
If both of account and password are given, is trying to get
|
||||
authentication by using AUTH command. :plain or :cram_md5 is
|
||||
allowed for AUTHTYPE.
|
||||
|
||||
: active?
|
||||
true if SMTP session is started.
|
||||
|
||||
: address
|
||||
the address to connect
|
||||
|
||||
: port
|
||||
the port number to connect
|
||||
|
||||
: open_timeout
|
||||
: open_timeout=(n)
|
||||
seconds to wait until connection is opened.
|
||||
If SMTP object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: read_timeout
|
||||
: read_timeout=(n)
|
||||
seconds to wait until reading one block (by one read(1) call).
|
||||
If SMTP object cannot open a conection in this seconds,
|
||||
it raises TimeoutError exception.
|
||||
|
||||
: finish
|
||||
finishes SMTP session.
|
||||
If SMTP session had not started, do nothing and return false.
|
||||
|
||||
: send_mail( mailsrc, from_addr, *to_addrs )
|
||||
: sendmail( mailsrc, from_addr, *to_addrs )
|
||||
This method sends 'mailsrc' as mail. SMTP read strings
|
||||
from 'mailsrc' by calling 'each' iterator, and convert them
|
||||
into "\r\n" terminated string when write.
|
||||
This method sends MAILSRC as mail. A SMTP object read strings
|
||||
from MAILSRC by calling "each" iterator, with converting them
|
||||
into CRLF ("\r\n") terminated string when write.
|
||||
|
||||
from_addr must be String.
|
||||
to_addrs must be a String(s) or an Array of String.
|
||||
FROM_ADDR must be a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
|
||||
Exceptions which SMTP raises are:
|
||||
* Net::ProtoSyntaxError: syntax error (errno.500)
|
||||
* Net::ProtoFatalError: fatal error (errno.550)
|
||||
* Net::ProtoUnknownError: unknown error
|
||||
* Net::ProtoServerBusy: temporary error (errno.420/450)
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {|smtp|
|
||||
smtp.send_mail mail_string,
|
||||
'from@mail.address',
|
||||
'dest@mail.address' 'dest2@mail.address'
|
||||
}
|
||||
|
||||
# usage example
|
||||
: ready( from_addr, *to_addrs ) {|adapter| .... }
|
||||
This method stands by the SMTP object for sending mail and
|
||||
give adapter object to the block. ADAPTER accepts only "write"
|
||||
method.
|
||||
|
||||
Net::SMTP.start( 'localhost', 25 ) do |smtp|
|
||||
smtp.send_mail mail_string, 'from-addr@foo.or.jp', 'to-addr@bar.or.jp'
|
||||
end
|
||||
FROM_ADDR must be a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
|
||||
: ready( from_addr, to_addrs ) {|adapter| .... }
|
||||
This method stands by the SMTP object for sending mail.
|
||||
"adapter" object accepts only "write" method.
|
||||
|
||||
# usage example
|
||||
|
||||
Net::SMTP.start( 'localhost', 25 ) do |smtp|
|
||||
smtp.ready( from, to ) do |adapter|
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server', 25 ) {|smtp|
|
||||
smtp.ready( 'from@mail.addr', 'dest@mail.addr' ) do |adapter|
|
||||
adapter.write str1
|
||||
adapter.write str2
|
||||
adapter.write str3
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
: finish
|
||||
finishes SMTP session.
|
||||
If SMTP session had not started, do nothing and return false.
|
||||
== Exceptions
|
||||
|
||||
SMTP objects raise these exceptions:
|
||||
: Net::ProtoSyntaxError
|
||||
syntax error (errno.500)
|
||||
: Net::ProtoFatalError
|
||||
fatal error (errno.550)
|
||||
: Net::ProtoUnknownError
|
||||
unknown error. (is probably bug)
|
||||
: Net::ProtoServerBusy
|
||||
temporary error (errno.420/450)
|
||||
|
||||
=end
|
||||
|
||||
|
@ -155,7 +262,7 @@ module Net
|
|||
|
||||
if user or secret then
|
||||
(user and secret) or
|
||||
raise ArgumentError, "both of account and password are required"
|
||||
raise ArgumentError, 'both of account and password are required'
|
||||
|
||||
mid = 'auth_' + (authtype || 'cram_md5').to_s
|
||||
@command.respond_to? mid or
|
||||
|
|
Loading…
Reference in a new issue