1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
* 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:
aamine 2001-06-26 23:49:21 +00:00
parent 10e80b2402
commit c664027a34
5 changed files with 743 additions and 376 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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