mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* protocol.rb,smtp.rb,pop.rb,http.rb: modify document.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1548 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
37b3f674a7
commit
cf37626401
3 changed files with 189 additions and 173 deletions
|
@ -27,7 +27,7 @@ For details of HTTP, refer [RFC2616]
|
|||
=== Getting Document From Server
|
||||
|
||||
Be care to ',' (comma) putted after "response".
|
||||
This is required for feature compatibility.
|
||||
This is required for compatibility.
|
||||
|
||||
require 'net/http'
|
||||
Net::HTTP.start( 'some.www.server', 80 ) {|http|
|
||||
|
@ -73,14 +73,17 @@ there's no need to change code if there's proxy or not.
|
|||
Net::HTTP.version_1_1
|
||||
|
||||
host = 'www.ruby-lang.org'
|
||||
path = '/'
|
||||
begin
|
||||
Net::HTTP.start( host, 80 ) {|http|
|
||||
response , = http.get('/')
|
||||
response , = http.get(path)
|
||||
print response.body
|
||||
}
|
||||
rescue Net::ProtoRetriableError => err
|
||||
if m = %r<http:([^/]+)>.match( err.response['location'] ) then
|
||||
host = m[1].strip
|
||||
retry
|
||||
if m = %r<http://([^/]+)>.match( err.response['location'] ) then
|
||||
host = m[1].strip
|
||||
path = m.post_match
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -131,8 +134,7 @@ Yes, this is not thread-safe.
|
|||
|
||||
: 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).
|
||||
If proxy_addr is given, creates an Net::HTTP object with proxy support.
|
||||
|
||||
: start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil )
|
||||
: start( address = 'localhost', port = 80, proxy_addr = nil, proxy_port = nil ) {|http| .... }
|
||||
|
@ -145,15 +147,14 @@ Yes, this is not thread-safe.
|
|||
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 output it to $stdout.
|
||||
|
||||
: 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.
|
||||
You can replace HTTP class with created proxy class.
|
||||
|
||||
If ADDRESS is nil, this method returns self (Net::HTTP class).
|
||||
If ADDRESS is nil, this method returns self (Net::HTTP).
|
||||
|
||||
# example
|
||||
proxy_class = Net::HTTP::Proxy( 'proxy.foo.org', 8080 )
|
||||
|
@ -168,7 +169,7 @@ Yes, this is not thread-safe.
|
|||
If self is a class which was created by HTTP::Proxy(), true.
|
||||
|
||||
: port
|
||||
HTTP default port (80).
|
||||
default HTTP port (80).
|
||||
|
||||
=== Instance Methods
|
||||
|
||||
|
@ -208,30 +209,32 @@ Yes, this is not thread-safe.
|
|||
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 does not use a proxy, nil.
|
||||
|
||||
: proxy_port
|
||||
port number of proxy host. If self is not a proxy, nil.
|
||||
port number of proxy host. If self does not use 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.
|
||||
gets data from PATH on the connecting host.
|
||||
HEADER must be a Hash like { 'Accept' => '*/*', ... }.
|
||||
Response body is written into DEST by using "<<" method.
|
||||
|
||||
This method returns Net::HTTPResponse object.
|
||||
|
||||
If called with block, give a part String of entity body.
|
||||
If called with block, gives entity body little by little
|
||||
to the block (as String).
|
||||
|
||||
In version 1.1, this method might raises exception for also
|
||||
3xx (redirect). On the case you can get response object by
|
||||
err.response.
|
||||
3xx (redirect). On the case you can get a HTTPResponse object
|
||||
by "anException.response".
|
||||
|
||||
In version 1.2, this method never raises exception.
|
||||
|
||||
# version 1.1 (Ruby 1.6)
|
||||
# version 1.1 (bundled with Ruby 1.6)
|
||||
response, body = http.get( '/index.html' )
|
||||
|
||||
# version 1.2 (Ruby 1.7 or later)
|
||||
# version 1.2 (bundled with Ruby 1.7 or later)
|
||||
response = http.get( '/index.html' )
|
||||
|
||||
# compatible in both version
|
||||
|
@ -244,16 +247,20 @@ Yes, this is not thread-safe.
|
|||
f.write str
|
||||
end
|
||||
}
|
||||
# some effect
|
||||
# same 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' => '*/*', ... }.
|
||||
gets only header from PATH on the connecting host.
|
||||
HEADER is a Hash like { 'Accept' => '*/*', ... }.
|
||||
|
||||
This method returns a Net::HTTPResponse object.
|
||||
You can http header from this object like:
|
||||
|
||||
In version 1.1, this method might raises exception for also
|
||||
3xx (redirect). On the case you can get a HTTPResponse object
|
||||
by "anException.response".
|
||||
|
||||
response = nil
|
||||
Net::HTTP.start( 'some.www.server', 80 ) {|http|
|
||||
|
@ -274,6 +281,10 @@ Yes, this is not thread-safe.
|
|||
|
||||
If called with block, gives a part of entity body string.
|
||||
|
||||
In version 1.1, this method might raises exception for also
|
||||
3xx (redirect). On the case you can get a HTTPResponse object
|
||||
by "anException.response".
|
||||
|
||||
# version 1.1
|
||||
response, body = http.post( '/index.html', 'querytype=subject&target=ruby' )
|
||||
# version 1.2
|
||||
|
@ -292,13 +303,15 @@ Yes, this is not thread-safe.
|
|||
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 DATA string if REQUEST is a post/put request.
|
||||
(giving DATA for get/head request causes ArgumentError.)
|
||||
: request( request [, data] )
|
||||
: request( request [, data] ) {|response| .... }
|
||||
sends a HTTPRequest object 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.
|
||||
If called with block, gives a HTTPResponse object to the block
|
||||
with connecting server.
|
||||
|
||||
== class Net::HTTP::Get, Head, Post
|
||||
|
||||
|
|
159
lib/net/pop.rb
159
lib/net/pop.rb
|
@ -28,64 +28,67 @@ 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.
|
||||
|
||||
require 'net/pop'
|
||||
|
||||
require 'net/pop'
|
||||
|
||||
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
|
||||
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' ) {|f|
|
||||
f.write m.pop
|
||||
}
|
||||
m.delete
|
||||
i += 1
|
||||
end
|
||||
m.delete
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
puts "#{pop.mails.size} mails popped."
|
||||
}
|
||||
puts "#{pop.mails.size} mails popped."
|
||||
}
|
||||
|
||||
=== Shorter Version
|
||||
|
||||
require 'net/pop'
|
||||
i = 0
|
||||
Net::POP3.start( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) {|pop|
|
||||
pop.delete_all do |m|
|
||||
require 'net/pop'
|
||||
Net::POP3.start( 'pop3.server.address', 110,
|
||||
'YourAccount', 'YourPassword' ) {|pop|
|
||||
if pop.mails.empty? then
|
||||
puts 'no mail.'
|
||||
else
|
||||
i = 0
|
||||
pop.delete_all do |m|
|
||||
File.open( 'inbox/' + i.to_s, 'w' ) {|f|
|
||||
f.write m.pop
|
||||
}
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
And here 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
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
@ -93,57 +96,57 @@ 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.
|
||||
}
|
||||
# (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.
|
||||
}
|
||||
# (2)
|
||||
require 'net/pop'
|
||||
Net::POP3.start( 'apop.server.address', 110,
|
||||
'YourAccount', 'YourPassword',
|
||||
true ####
|
||||
) {|pop|
|
||||
# Rest code is same.
|
||||
}
|
||||
|
||||
== Net::POP3 class
|
||||
|
||||
=== Class Methods
|
||||
|
||||
: new( address = 'localhost', port = 110, apop = false )
|
||||
creates a new Net::POP3 object.
|
||||
This method does not open TCP connection yet.
|
||||
creates a new Net::POP3 object.
|
||||
This method does not open TCP connection yet.
|
||||
|
||||
: start( address = 'localhost', port = 110, account, password )
|
||||
: start( address = 'localhost', port = 110, account, password ) {|pop| .... }
|
||||
equals to Net::POP3.new( address, port ).start( account, password )
|
||||
equals to Net::POP3.new( address, port ).start( account, password )
|
||||
|
||||
Net::POP3.start( addr, port, account, password ) do |pop|
|
||||
pop.each_mail do |m|
|
||||
file.write m.pop
|
||||
m.delete
|
||||
end
|
||||
end
|
||||
Net::POP3.start( addr, port, account, password ) do |pop|
|
||||
pop.each_mail do |m|
|
||||
file.write m.pop
|
||||
m.delete
|
||||
end
|
||||
end
|
||||
|
||||
: foreach( address = 'localhost', port = 110, account, password ) {|mail| .... }
|
||||
starts protocol and iterate for each POPMail object.
|
||||
This method equals to
|
||||
starts POP3 protocol and iterates for each POPMail object.
|
||||
This method equals to
|
||||
|
||||
Net::POP3.start( address, port, account, password ) do |pop|
|
||||
pop.each do |m|
|
||||
yield m
|
||||
end
|
||||
end
|
||||
Net::POP3.start( address, port, account, password ) {|pop|
|
||||
pop.each_mail do |m|
|
||||
yield m
|
||||
end
|
||||
}
|
||||
|
||||
Typical usage:
|
||||
|
||||
Net::POP3.foreach( addr, nil, acnt, pass ) do |m|
|
||||
m.pop file
|
||||
m.delete
|
||||
end
|
||||
# example
|
||||
Net::POP3.foreach( 'your.pop.server', 110,
|
||||
'YourAccount', 'YourPassword' ) do |m|
|
||||
file.write m.pop
|
||||
m.delete if $DELETE
|
||||
end
|
||||
|
||||
: delete_all( address = 'localhost', port = 110, account, password )
|
||||
: delete_all( address = 'localhost', port = 110, account, password ) {|mail| .... }
|
||||
|
@ -229,7 +232,7 @@ net/pop also supports APOP authentication. There's two way to use APOP:
|
|||
pop.auth_only 'YourAccount', 'YourPassword'
|
||||
|
||||
: reset
|
||||
reset the session. All "deleted mark" are removed.
|
||||
reset the session. All "deleted mark" are removed.
|
||||
|
||||
== Net::APOP
|
||||
|
||||
|
|
126
lib/net/smtp.rb
126
lib/net/smtp.rb
|
@ -36,10 +36,10 @@ 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
|
||||
}
|
||||
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
|
||||
|
@ -47,19 +47,19 @@ for you.
|
|||
|
||||
Then you can send mail.
|
||||
|
||||
require 'net/smtp'
|
||||
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>
|
||||
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
|
||||
}
|
||||
This is test mail.
|
||||
EndOfMail
|
||||
}
|
||||
|
||||
=== Sending Mails from Any Sources
|
||||
|
||||
|
@ -67,20 +67,20 @@ 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'
|
||||
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|
|
||||
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?)
|
||||
|
@ -91,32 +91,32 @@ send or reject SMTP session by this data.
|
|||
=== Class Methods
|
||||
|
||||
: new( address = 'localhost', port = 25 )
|
||||
creates a new Net::SMTP object.
|
||||
creates a new Net::SMTP object.
|
||||
|
||||
: 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)
|
||||
is equal to
|
||||
Net::SMTP.new(address,port).start(helo_domain,account,password,authtype)
|
||||
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {
|
||||
smtp.send_mail mail_string, 'from@mail.address', 'dest@mail.address'
|
||||
}
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {
|
||||
smtp.send_mail mail_string, 'from@mail.address', 'dest@mail.address'
|
||||
}
|
||||
|
||||
=== 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.
|
||||
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.
|
||||
When this methods is called with block, give a SMTP object to block and
|
||||
close session after block call finished.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
@ -144,38 +144,38 @@ send or reject SMTP session by this data.
|
|||
If SMTP session had not started, do nothing and return false.
|
||||
|
||||
: send_mail( mailsrc, from_addr, *to_addrs )
|
||||
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.
|
||||
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 a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
FROM_ADDR must be a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {|smtp|
|
||||
smtp.send_mail mail_string,
|
||||
'from@mail.address',
|
||||
'dest@mail.address' 'dest2@mail.address'
|
||||
}
|
||||
# example
|
||||
Net::SMTP.start( 'your.smtp.server' ) {|smtp|
|
||||
smtp.send_mail mail_string,
|
||||
'from@mail.address',
|
||||
'dest@mail.address' 'dest2@mail.address'
|
||||
}
|
||||
|
||||
: 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.
|
||||
This method stands by the SMTP object for sending mail and
|
||||
give adapter object to the block. ADAPTER accepts only "write"
|
||||
method.
|
||||
|
||||
FROM_ADDR must be a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
FROM_ADDR must be a String, representing source mail address.
|
||||
TO_ADDRS must be Strings or an Array of Strings, representing
|
||||
destination mail addresses.
|
||||
|
||||
# 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
|
||||
}
|
||||
# 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
|
||||
}
|
||||
|
||||
== Exceptions
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue