From d31210ccbd28a7873aa5db8f34ea87275dc62269 Mon Sep 17 00:00:00 2001 From: gsinclair Date: Sun, 9 May 2004 13:42:05 +0000 Subject: * lib/net/ftp.rb: improved documentation * lib/net/imap.rb: ditto * lib/net/pop.rb: ditto * lib/net/smtp.rb: ditto * lib/net/telnet.rb: ditto git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6281 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 8 ++ lib/net/ftp.rb | 12 +- lib/net/imap.rb | 14 +- lib/net/pop.rb | 402 ++++++++++++++++++++++++++++-------------------------- lib/net/smtp.rb | 335 ++++++++++++++++++++++++++------------------- lib/net/telnet.rb | 162 +++++++++++----------- 6 files changed, 515 insertions(+), 418 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66daef0c45..57d3cbe78f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Sun May 9 22:37:00 2004 Gavin Sinclair + + * lib/net/ftp.rb: improved documentation + * lib/net/imap.rb: ditto + * lib/net/pop.rb: ditto + * lib/net/smtp.rb: ditto + * lib/net/telnet.rb: ditto + Fri May 7 21:50:21 2004 Dave Thomas * lib/rdoc/parsers/parse_rb.rb (RDoc::parse_include): Allow diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb index d236140056..2b94cde234 100644 --- a/lib/net/ftp.rb +++ b/lib/net/ftp.rb @@ -1,5 +1,5 @@ # -# = net/ftp.rb +# = net/ftp.rb - FTP Client Library # # Written by Shugo Maeda . # @@ -17,7 +17,7 @@ require "socket" require "monitor" -module Net # :nodoc: +module Net # :stopdoc: class FTPError < StandardError; end @@ -58,7 +58,7 @@ module Net # :nodoc: # == Major Methods # # The following are the methods most likely to be useful to users: - # - FTP::open + # - FTP.open # - #getbinaryfile # - #gettextfile # - #putbinaryfile @@ -81,7 +81,7 @@ module Net # :nodoc: # When +true+, transfers are performed in binary mode. Default: +true+. attr_accessor :binary - # When +true+, the connection is in passive mode. Default: false. + # When +true+, the connection is in passive mode. Default: +false+. attr_accessor :passive # When +true+, all traffic to and from the server is written @@ -103,7 +103,7 @@ module Net # :nodoc: attr_reader :last_response # - # A synonym for +FTP.new+, but with a mandatory host parameter. + # A synonym for FTP.new, but with a mandatory host parameter. # # If a block is given, it is passed the +FTP+ object, which will be closed # when the block finishes, or when an exception is raised. @@ -165,7 +165,7 @@ module Net # :nodoc: # Establishes an FTP connection to host, optionally overriding the default # port. If the environment variable +SOCKS_SERVER+ is set, sets up the # connection through a SOCKS proxy. Raises an exception (typically - # +Errno::ECONNREFUSED+) if the connection cannot be established. + # Errno::ECONNREFUSED) if the connection cannot be established. # def connect(host, port = FTP_PORT) if @debug_mode diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 0845009813..27936746c6 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -7,7 +7,9 @@ # You can freely distribute/modify this library. # # Documentation: Shugo Maeda, with RDoc conversion and overview by William -# Webber. +# Webber. +# +# See Net::IMAP for documentation. # @@ -19,13 +21,13 @@ begin rescue LoadError end -module Net # :nodoc: +module Net # # Net::IMAP implements Internet Message Access Protocol (IMAP) client # functionality. The protocol is described in [IMAP]. # - # == IMAP OVERVIEW + # == IMAP Overview # # An IMAP client connects to a server, and then authenticates # itself using either #authenticate() or #login(). Having @@ -63,7 +65,7 @@ module Net # :nodoc: # UIDs have to be reassigned. An IMAP client cannot thus # rearrange message orders. # - # == EXAMPLES OF USAGE + # == Examples of Usage # # === List sender and subject of all recent messages in the default mailbox # @@ -89,7 +91,7 @@ module Net # :nodoc: # end # imap.expunge # - # == THREAD-SAFENESS + # == Thread Safety # # Net::IMAP supports concurrent threads. For example, # @@ -103,7 +105,7 @@ module Net # :nodoc: # # This script invokes the FETCH command and the SEARCH command concurrently. # - # == ERRORS + # == Errors # # An IMAP server can send three different types of responses to indicate # failure: diff --git a/lib/net/pop.rb b/lib/net/pop.rb index eb61c29ca3..a4f50b002c 100644 --- a/lib/net/pop.rb +++ b/lib/net/pop.rb @@ -1,10 +1,12 @@ # = net/pop.rb # -#-- -# Copyright (c) 1999-2003 Yukihiro Matsumoto -# Copyright (c) 1999-2003 Minero Aoki +# Copyright (c) 1999-2003 Yukihiro Matsumoto. +# +# Copyright (c) 1999-2003 Minero Aoki. # -# written & maintained by Minero Aoki +# Written & maintained by Minero Aoki . +# +# Documented by William Webber and Minero Aoki. # # This program is free software. You can re-distribute and/or # modify this program under the same terms as Ruby itself, @@ -13,158 +15,10 @@ # NOTE: You can find Japanese version of this document in # the doc/net directory of the standard ruby interpreter package. # -# $Id$ -#++ +# $Id$ +# +# See Net::POP3 for documentation. # -# == What is This Library? -# -# This library provides functionality for retrieving -# email via POP3, the Post Office Protocol version 3. For details -# of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt). -# -# == Examples -# -# === Retrieving Messages -# -# This example retrieves messages from the server and deletes them -# on the server. -# Messages are written to files named 'inbox/1', 'inbox/2', .... -# Replace 'pop.example.com' with your POP3 server address, and -# 'YourAccount' and 'YourPassword' with the appropriate account -# details. -# -# require 'net/pop' -# -# pop = Net::POP3.new('pop.example.com') -# pop.start('YourAccount', 'YourPassword') # (1) -# if pop.mails.empty? -# puts 'no mail.' -# else -# i = 0 -# pop.each_mail do |m| # or "pop.mails.each ..." # (2) -# File.open("inbox/#{i}", 'w') {|f| -# f.write m.pop -# } -# m.delete -# i += 1 -# end -# puts "#{pop.mails.size} mails popped." -# end -# pop.finish # (3) -# -# 1. call Net::POP3#start and start POP session -# 2. access messages by using POP3#each_mail and/or POP3#mails -# 3. close POP session by calling POP3#finish or use the block form of #start. -# -# === Shortened Code -# -# The example above is very verbose. You can shorten the code by using -# some utility methods. First, the block form of Net::POP3.start can -# be used instead of POP3.new, POP3#start and POP3#finish. -# -# require 'net/pop' -# -# Net::POP3.start('pop.example.com', 110, -# 'YourAccount', 'YourPassword') {|pop| -# if pop.mails.empty? -# puts 'no mail.' -# else -# i = 0 -# pop.each_mail do |m| # or "pop.mails.each ..." -# File.open("inbox/#{i}", 'w') {|f| -# f.write m.pop -# } -# m.delete -# i += 1 -# end -# puts "#{pop.mails.size} mails popped." -# end -# } -# -# POP3#delete_all alternates #each_mail and m.delete. -# -# require 'net/pop' -# -# Net::POP3.start('pop.example.com', 110, -# 'YourAccount', 'YourPassword') {|pop| -# if pop.mails.empty? -# puts 'no mail.' -# else -# i = 1 -# pop.delete_all do |m| -# File.open("inbox/#{i}", 'w') {|f| -# f.write m.pop -# } -# i += 1 -# end -# end -# } -# -# And here is an even shorter example. -# -# require 'net/pop' -# -# i = 0 -# Net::POP3.delete_all('pop.example.com', 110, -# 'YourAccount', 'YourPassword') do |m| -# File.open("inbox/#{i}", 'w') {|f| -# f.write m.pop -# } -# i += 1 -# end -# -# === Memory Space Issues -# -# All the examples above get each message as one big string. -# This example avoids this. -# -# require 'net/pop' -# -# i = 1 -# Net::POP3.delete_all('pop.example.com', 110, -# 'YourAccount', 'YourPassword') do |m| -# File.open("inbox/#{i}", 'w') {|f| -# m.pop do |chunk| # get a message little by little. -# f.write chunk -# end -# i += 1 -# } -# end -# -# === Using APOP -# -# The net/pop library supports APOP authentication. -# To use APOP, use the Net::APOP class instead of the Net::POP3 class. -# You can use the utility method, Net::POP3.APOP(). For example: -# -# require 'net/pop' -# -# # Use APOP authentication if $isapop == true -# pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110) -# pop.start(YourAccount', 'YourPassword') {|pop| -# # Rest code is same. -# } -# -# === Fetch Only Selected Mail Using `UIDL' POP Command -# -# If your POP server provides UIDL functionality, -# you can grab only selected mails from the POP server. -# e.g. -# -# def need_pop?( id ) -# # determine if we need pop this mail... -# end -# -# Net::POP3.start('pop.example.com', 110, -# 'Your account', 'Your password') {|pop| -# pop.mails.select {|m| need_pop?(m.unique_id) }.each do |m| -# do_something(m.pop) -# end -# } -# -# The POPMail#unique_id() method returns the unique-id of the message as a -# String. Normally the unique-id is a hash of the message. -# require 'net/protocol' require 'digest/md5' @@ -181,12 +35,159 @@ module Net # Unexpected response from the server. class POPBadResponse < POPError; end - # - # Class providing POP3 client functionality. + # = Net::POP3 # - # See documentation for the file pop.rb for examples of usage. + # == What is This Library? + # + # This library provides functionality for retrieving + # email via POP3, the Post Office Protocol version 3. For details + # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt). + # + # == Examples + # + # === Retrieving Messages + # + # This example retrieves messages from the server and deletes them + # on the server. # + # Messages are written to files named 'inbox/1', 'inbox/2', .... + # Replace 'pop.example.com' with your POP3 server address, and + # 'YourAccount' and 'YourPassword' with the appropriate account + # details. + # + # require 'net/pop' + # + # pop = Net::POP3.new('pop.example.com') + # pop.start('YourAccount', 'YourPassword') # (1) + # if pop.mails.empty? + # puts 'No mail.' + # else + # i = 0 + # pop.each_mail do |m| # or "pop.mails.each ..." # (2) + # File.open("inbox/#{i}", 'w') do |f| + # f.write m.pop + # end + # m.delete + # i += 1 + # end + # puts "#{pop.mails.size} mails popped." + # end + # pop.finish # (3) + # + # 1. Call Net::POP3#start and start POP session. + # 2. Access messages by using POP3#each_mail and/or POP3#mails. + # 3. Close POP session by calling POP3#finish or use the block form of #start. + # + # === Shortened Code + # + # The example above is very verbose. You can shorten the code by using + # some utility methods. First, the block form of Net::POP3.start can + # be used instead of POP3.new, POP3#start and POP3#finish. + # + # require 'net/pop' + # + # Net::POP3.start('pop.example.com', 110, + # 'YourAccount', 'YourPassword') do |pop| + # if pop.mails.empty? + # puts 'No mail.' + # else + # i = 0 + # pop.each_mail do |m| # or "pop.mails.each ..." + # File.open("inbox/#{i}", 'w') do |f| + # f.write m.pop + # end + # m.delete + # i += 1 + # end + # puts "#{pop.mails.size} mails popped." + # end + # end + # + # POP3#delete_all is an alternative for #each_mail and #delete. + # + # require 'net/pop' + # + # Net::POP3.start('pop.example.com', 110, + # 'YourAccount', 'YourPassword') do |pop| + # if pop.mails.empty? + # puts 'No mail.' + # else + # i = 1 + # pop.delete_all do |m| + # File.open("inbox/#{i}", 'w') do |f| + # f.write m.pop + # end + # i += 1 + # end + # end + # end + # + # And here is an even shorter example. + # + # require 'net/pop' + # + # i = 0 + # Net::POP3.delete_all('pop.example.com', 110, + # 'YourAccount', 'YourPassword') do |m| + # File.open("inbox/#{i}", 'w') do |f| + # f.write m.pop + # end + # i += 1 + # end + # + # === Memory Space Issues + # + # All the examples above get each message as one big string. + # This example avoids this. + # + # require 'net/pop' + # + # i = 1 + # Net::POP3.delete_all('pop.example.com', 110, + # 'YourAccount', 'YourPassword') do |m| + # File.open("inbox/#{i}", 'w') do |f| + # m.pop do |chunk| # get a message little by little. + # f.write chunk + # end + # i += 1 + # end + # end + # + # === Using APOP + # + # The net/pop library supports APOP authentication. + # To use APOP, use the Net::APOP class instead of the Net::POP3 class. + # You can use the utility method, Net::POP3.APOP(). For example: + # + # require 'net/pop' + # + # # Use APOP authentication if $isapop == true + # pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110) + # pop.start(YourAccount', 'YourPassword') do |pop| + # # Rest of the code is the same. + # end + # + # === Fetch Only Selected Mail Using 'UIDL' POP Command + # + # If your POP server provides UIDL functionality, + # you can grab only selected mails from the POP server. + # e.g. + # + # def need_pop?( id ) + # # determine if we need pop this mail... + # end + # + # Net::POP3.start('pop.example.com', 110, + # 'Your account', 'Your password') do |pop| + # pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m| + # do_something(m.pop) + # end + # end + # + # The POPMail#unique_id() method returns the unique-id of the message as a + # String. Normally the unique-id is a hash of the message. + # class POP3 < Protocol Revision = %q$Revision$.split[1] @@ -215,9 +216,9 @@ module Net # pop = Net::POP3::APOP($is_apop).new(addr, port) # # # Example 2 - # Net::POP3::APOP($is_apop).start(addr, port) {|pop| + # Net::POP3::APOP($is_apop).start(addr, port) do |pop| # .... - # } + # end # def POP3.APOP( isapop ) isapop ? APOP : POP3 @@ -227,15 +228,16 @@ module Net # yielding it to the +block+. # This method is equivalent to: # - # Net::POP3.start(address, port, account, password) {|pop| + # Net::POP3.start(address, port, account, password) do |pop| # pop.each_mail do |m| # yield m # end - # } + # end # # This method raises a POPAuthenticationError if authentication fails. # - # # Typical usage + # === Example + # # Net::POP3.foreach('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # file.write m.pop @@ -256,7 +258,8 @@ module Net # # This method raises a POPAuthenticationError if authentication fails. # - # # Example + # === Example + # # Net::POP3.delete_all('pop.example.com', 110, # 'YourAccount', 'YourPassword') do |m| # file.write m.pop @@ -274,11 +277,13 @@ module Net # # This method raises POPAuthenticationError if authentication fails. # - # # Example 1: normal POP3 + # === Example: normal POP3 + # # Net::POP3.auth_only('pop.example.com', 110, # 'YourAccount', 'YourPassword') # - # # Example 2: APOP + # === Example: APOP + # # Net::POP3.auth_only('pop.example.com', 110, # 'YourAccount', 'YourPassword', true) # @@ -303,19 +308,20 @@ module Net # # Creates a new POP3 object and open the connection. Equivalent to - # Net::POP3.new(address, port, isapop).start(account, password) + # + # Net::POP3.new(address, port, isapop).start(account, password) # # If +block+ is provided, yields the newly-opened POP3 object to it, # and automatically closes it at the end of the session. # - # Typical usage: + # === Example # - # Net::POP3.start(addr, port, account, password) {|pop| + # Net::POP3.start(addr, port, account, password) do |pop| # pop.each_mail do |m| # file.write m.pop # m.delete # end - # } + # end # def POP3.start( address, port = nil, account = nil, password = nil, @@ -324,10 +330,14 @@ module Net end # Creates a new POP3 object. + # # +address+ is the hostname or ip address of your POP3 server. + # # The optional +port+ is the port to connect to; it defaults to 110. + # # The optional +isapop+ specifies whether this connection is going # to use APOP authentication; it defaults to +false+. + # # This method does *not* open the TCP connection. def initialize( addr, port = nil, isapop = false ) @address = addr @@ -361,12 +371,13 @@ module Net # # Set an output stream for debugging. # - # # Example + # === Example + # # pop = Net::POP.new(addr, port) # pop.set_debug_output $stderr - # pop.start(account, passwd) { + # pop.start(account, passwd) do |pop| # .... - # } + # end # def set_debug_output( arg ) @debug_output = arg @@ -523,16 +534,18 @@ module Net # # If called with a block, yields each message in turn before deleting it. # - # # Example + # === Example + # # n = 1 # pop.delete_all do |m| - # File.open("inbox/#{n}") {|f| + # File.open("inbox/#{n}") do |f| # f.write m.pop - # } + # end # n += 1 # end # # This method raises a POPError if an error occurs. + # def delete_all # :yield: message mails().each do |m| yield m if block_given? @@ -606,40 +619,44 @@ module Net "#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>" end + # # This method fetches the message. If called with a block, the # message is yielded to the block one chunk at a time. If called # without a block, the message is returned as a String. The optional # +dest+ argument will be prepended to the returned String; this # argument is essentially obsolete. # - # # Example without block + # === Example without block + # # POP3.start('pop.example.com', 110, - # 'YourAccount, 'YourPassword') {|pop| + # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') {|f| + # File.open("inbox/#{n}", 'w') do |f| # f.write popmail.pop - # } + # end # popmail.delete # n += 1 # end - # } + # end + # + # === Example with block # - # # Example with block # POP3.start('pop.example.com', 110, - # 'YourAccount, 'YourPassword') {|pop| + # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') {|f| + # File.open("inbox/#{n}", 'w') do |f| # popmail.pop do |chunk| #### # f.write chunk # end - # } + # end # n += 1 # end - # } + # end # # This method raises a POPError if an error occurs. + # def pop( dest = '', &block ) # :yield: message_chunk if block_given? @command.retr(@number, &block) @@ -656,6 +673,7 @@ module Net alias mail pop #:nodoc: obsolete # Fetches the message header and +lines+ lines of body. + # # The optional +dest+ argument is obsolete. # # This method raises a POPError if an error occurs. @@ -667,6 +685,7 @@ module Net end # Fetches the message header. + # # The optional +dest+ argument is obsolete. # # This method raises a POPError if an error occurs. @@ -680,18 +699,19 @@ module Net # # This method raises a POPError if an error occurs. # - # # Example + # === Example + # # POP3.start('pop.example.com', 110, - # 'YourAccount, 'YourPassword') {|pop| + # 'YourAccount, 'YourPassword') do |pop| # n = 1 # pop.mails.each do |popmail| - # File.open("inbox/#{n}", 'w') {|f| + # File.open("inbox/#{n}", 'w') do |f| # f.write popmail.pop - # } + # end # popmail.delete #### # n += 1 # end - # } + # end # def delete @command.dele @number diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index 62a5fc559b..db54b998c9 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -1,10 +1,12 @@ # = net/smtp.rb # -#-- -# Copyright (c) 1999-2003 Yukihiro Matsumoto -# Copyright (c) 1999-2003 Minero Aoki +# Copyright (c) 1999-2003 Yukihiro Matsumoto. +# +# Copyright (c) 1999-2003 Minero Aoki. # -# written & maintained by Minero Aoki +# Written & maintained by Minero Aoki . +# +# Documented by William Webber and Minero Aoki. # # This program is free software. You can re-distribute and/or # modify this program under the same terms as Ruby itself, @@ -14,115 +16,14 @@ # the doc/net directory of the standard ruby interpreter package. # # $Id$ -#++ +# +# See Net::SMTP for documentation. # -# == What is This Library? -# -# This library provides functionality to send internet -# mail via SMTP, the Simple Mail Transfer Protocol. For details of -# SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt). -# -# == What is This Library NOT? -# -# This library does NOT provide functions to compose internet mails. -# You must create them by yourself. If you want better mail support, -# try RubyMail or TMail. You can get both libraries from RAA. -# (http://www.ruby-lang.org/en/raa.html) -# -# FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt). -# -# == Examples -# -# === Sending Messages -# -# You must open a connection to an SMTP server before sending messages. -# The first argument is the address of your SMTP server, and the second -# argument is the port number. Using SMTP.start with a block is the simplest -# way to do this. This way, the SMTP connection is closed automatically -# after the block is executed. -# -# require 'net/smtp' -# Net::SMTP.start('your.smtp.server', 25) {|smtp| -# # use the SMTP object smtp only in this block -# } -# -# Replace 'your.smtp.server' with your SMTP server. Normally -# your system manager or internet provider supplies a server -# for you. -# -# Then you can send messages. -# -# msgstr = < -# To: Destination Address -# Subject: test message -# Date: Sat, 23 Jun 2001 16:26:43 +0900 -# Message-Id: -# -# This is a test message. -# END_OF_MESSAGE -# -# require 'net/smtp' -# Net::SMTP.start('your.smtp.server', 25) {|smtp| -# smtp.send_message msgstr, -# 'your@mail.address', -# 'his_addess@example.com' -# } -# -# === Closing the Session -# -# You MUST close the SMTP session after sending messages, by calling -# the #finish method: -# -# # using SMTP#finish -# smtp = Net::SMTP.start('your.smtp.server', 25) -# smtp.send_message msgstr, 'from@address', 'to@address' -# smtp.finish -# -# You can also use the block form of SMTP.start/SMTP#start. This closes -# the SMTP session automatically: -# -# # using block form of SMTP.start -# Net::SMTP.start('your.smtp.server', 25) {|smtp| -# smtp.send_message msgstr, 'from@address', 'to@address' -# } -# -# I strongly recommend this scheme. This form is simpler and more robust. -# -# === HELO domain -# -# In almost all situations, you must provide a third argument -# to SMTP.start/SMTP#start. This is the domain name which you are on -# (the host to send mail from). It is called the "HELO domain". -# The SMTP server will judge whether it should send or reject -# the SMTP session by inspecting the HELO domain. -# -# Net::SMTP.start('your.smtp.server', 25, -# 'mail.from.domain') {|smtp| ... } -# -# === SMTP Authentication -# -# The Net::SMTP class supports three authentication schemes; -# PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554]) -# To use SMTP authentication, pass extra arguments to -# SMTP.start/SMTP#start. -# -# # PLAIN -# Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain', -# 'Your Account', 'Your Password', :plain) -# # LOGIN -# Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain', -# 'Your Account', 'Your Password', :login) -# -# # CRAM MD5 -# Net::SMTP.start('your.smtp.server', 25, 'mail.from,domain', -# 'Your Account', 'Your Password', :cram_md5) require 'net/protocol' require 'digest/md5' - -module Net # :nodoc: +module Net # Module mixed in to all SMTP error classes module SMTPError @@ -156,9 +57,109 @@ module Net # :nodoc: end # - # Class providing SMTP client functionality. + # = Net::SMTP # - # See documentation for the file smtp.rb for examples of usage. + # == What is This Library? + # + # This library provides functionality to send internet + # mail via SMTP, the Simple Mail Transfer Protocol. For details of + # SMTP itself, see [RFC2821] (http://www.ietf.org/rfc/rfc2821.txt). + # + # == What is This Library NOT? + # + # This library does NOT provide functions to compose internet mails. + # You must create them by yourself. If you want better mail support, + # try RubyMail or TMail. You can get both libraries from RAA. + # (http://www.ruby-lang.org/en/raa.html) + # + # FYI: the official documentation on internet mail is: [RFC2822] (http://www.ietf.org/rfc/rfc2822.txt). + # + # == Examples + # + # === Sending Messages + # + # You must open a connection to an SMTP server before sending messages. + # The first argument is the address of your SMTP server, and the second + # argument is the port number. Using SMTP.start with a block is the simplest + # way to do this. This way, the SMTP connection is closed automatically + # after the block is executed. + # + # require 'net/smtp' + # Net::SMTP.start('your.smtp.server', 25) do |smtp| + # # Use the SMTP object smtp only in this block. + # end + # + # Replace 'your.smtp.server' with your SMTP server. Normally + # your system manager or internet provider supplies a server + # for you. + # + # Then you can send messages. + # + # msgstr = < + # To: Destination Address + # Subject: test message + # Date: Sat, 23 Jun 2001 16:26:43 +0900 + # Message-Id: + # + # This is a test message. + # END_OF_MESSAGE + # + # require 'net/smtp' + # Net::SMTP.start('your.smtp.server', 25) do |smtp| + # smtp.send_message msgstr, + # 'your@mail.address', + # 'his_addess@example.com' + # end + # + # === Closing the Session + # + # You MUST close the SMTP session after sending messages, by calling + # the #finish method: + # + # # using SMTP#finish + # smtp = Net::SMTP.start('your.smtp.server', 25) + # smtp.send_message msgstr, 'from@address', 'to@address' + # smtp.finish + # + # You can also use the block form of SMTP.start/SMTP#start. This closes + # the SMTP session automatically: + # + # # using block form of SMTP.start + # Net::SMTP.start('your.smtp.server', 25) do |smtp| + # smtp.send_message msgstr, 'from@address', 'to@address' + # end + # + # I strongly recommend this scheme. This form is simpler and more robust. + # + # === HELO domain + # + # In almost all situations, you must provide a third argument + # to SMTP.start/SMTP#start. This is the domain name which you are on + # (the host to send mail from). It is called the "HELO domain". + # The SMTP server will judge whether it should send or reject + # the SMTP session by inspecting the HELO domain. + # + # Net::SMTP.start('your.smtp.server', 25, + # 'mail.from.domain') { |smtp| ... } + # + # === SMTP Authentication + # + # The Net::SMTP class supports three authentication schemes; + # PLAIN, LOGIN and CRAM MD5. (SMTP Authentication: [RFC2554]) + # To use SMTP authentication, pass extra arguments to + # SMTP.start/SMTP#start. + # + # # PLAIN + # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', + # 'Your Account', 'Your Password', :plain) + # # LOGIN + # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', + # 'Your Account', 'Your Password', :login) + # + # # CRAM MD5 + # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain', + # 'Your Account', 'Your Password', :cram_md5) # class SMTP @@ -169,10 +170,17 @@ module Net # :nodoc: 25 end - # Creates a new Net::SMTP object. +address+ is the hostname - # or ip address of your SMTP server. +port+ is the port to - # connect to; it defaults to port 25. - # This method does not open the TCP connection. + # + # Creates a new Net::SMTP object. + # + # +address+ is the hostname or ip address of your SMTP + # server. +port+ is the port to connect to; it defaults to + # port 25. + # + # This method does not open the TCP connection. You can use + # SMTP.start instead of SMTP.new if you want to do everything + # at once. Otherwise, follow SMTP.new with SMTP#start. + # def initialize( address, port = nil ) @address = address @port = (port || SMTP.default_port) @@ -195,11 +203,13 @@ module Net # :nodoc: @esmtp end + # # Set whether to use ESMTP or not. This should be done before # calling #start. Note that if #start is called in ESMTP mode, # and the connection fails due to a ProtocolError, the SMTP # object will automatically switch to plain SMTP mode and # retry (but not vice versa). + # def esmtp=( bool ) @esmtp = bool end @@ -229,6 +239,7 @@ module Net # :nodoc: @read_timeout = sec end + # # WARNING: This method causes serious security holes. # Use this method for only debugging. # @@ -238,9 +249,10 @@ module Net # :nodoc: # # example # smtp = Net::SMTP.new(addr, port) # smtp.set_debug_output $stderr - # smtp.start { + # smtp.start do |smtp| # .... - # } + # end + # def set_debug_output( arg ) @debug_output = arg end @@ -249,16 +261,20 @@ module Net # :nodoc: # SMTP session control # + # # Creates a new Net::SMTP object and connects to the server. # # This method is equivalent to: # - # Net::SMTP.new(address,port).start(helo_domain,account,password,authtype) + # Net::SMTP.new(address, port).start(helo_domain, account, password, authtype) + # + # === Example # - # # example - # Net::SMTP.start('your.smtp.server') { + # Net::SMTP.start('your.smtp.server') do |smtp| # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] - # } + # end + # + # === Block Usage # # If called with a block, the newly-opened Net::SMTP object is yielded # to the block, and automatically closed when the block finishes. If called @@ -266,16 +282,23 @@ module Net # :nodoc: # the caller, and it is the caller's responsibility to close it when # finished. # + # === Parameters + # # +address+ is the hostname or ip address of your smtp server. + # # +port+ is the port to connect to; it defaults to port 25. + # # +helo+ is the _HELO_ _domain_ provided by the client to the # server (see overview comments); it defaults to 'localhost.localdomain'. + # # The remaining arguments are used for SMTP authentication, if required # or desired. +user+ is the account name; +secret+ is your password # or other authentication token; and +authtype+ is the authentication # type, one of :plain, :login, or :cram_md5. See the discussion of # SMTP Authentication in the overview notes. # + # === Errors + # # This method may raise: # # * Net::SMTPAuthenticationError @@ -285,6 +308,7 @@ module Net # :nodoc: # * Net::SMTPUnknownError # * IOError # * TimeoutError + # def SMTP.start( address, port = nil, helo = 'localhost.localdomain', user = nil, secret = nil, authtype = nil, @@ -297,21 +321,43 @@ module Net # :nodoc: @started end + # # Opens a TCP connection and starts the SMTP session. # + # === Parameters + # # +helo+ is the _HELO_ _domain_ that you'll dispatch mails from; see # the discussion in the overview notes. # + # If both of +user+ and +secret+ are given, SMTP authentication + # will be attempted using the AUTH command. +authtype+ specifies + # the type of authentication to attempt; it must be one of + # :login, :plain, and :cram_md5. See the notes on SMTP Authentication + # in the overview. + # + # === Block Usage + # # When this methods is called with a block, the newly-started SMTP # object is yielded to the block, and automatically closed after # the block call finishes. Otherwise, it is the caller's # responsibility to close the session when finished. # - # If both of +user+ and +secret+ are given, SMTP authentication - # will be attempted using the AUTH command. +authtype+ specifies - # the type of authentication to attempt; it must be one of - # :login, :plain, and :cram_md5. See the notes on SMTP Authentication - # in the overview. + # === Example + # + # This is very similar to the class method SMTP.start. + # + # require 'net/smtp' + # smtp = Net::SMTP.new('smtp.mail.server', 25) + # smtp.start(helo_domain, account, password, authtype) do |smtp| + # smtp.send_message msgstr, 'from@example.com', ['dest@example.com'] + # end + # + # The primary use of this method (as opposed to SMTP.start) + # is probably to set debugging (#set_debug_output) or ESMTP + # (#esmtp=), which must be done before the session is + # started. + # + # === Errors # # If session has already been started, an IOError will be raised. # @@ -324,6 +370,7 @@ module Net # :nodoc: # * Net::SMTPUnknownError # * IOError # * TimeoutError + # def start( helo = 'localhost.localdomain', user = nil, secret = nil, authtype = nil ) # :yield: smtp if block_given? @@ -391,21 +438,26 @@ module Net # :nodoc: public + # # Sends +msgstr+ as a message. Single CR ("\r") and LF ("\n") found # in the +msgstr+, are converted into the CR LF pair. You cannot send a # binary message with this method. +msgstr+ should include both # the message headers and body. # # +from_addr+ is a String representing the source mail address. + # # +to_addr+ is a String or Strings or Array of Strings, representing # the destination mail address or addresses. # - # # example - # Net::SMTP.start('smtp.example.com') {|smtp| + # === Example + # + # Net::SMTP.start('smtp.example.com') do |smtp| # smtp.send_message msgstr, # 'from@example.com', # ['dest@example.com', 'dest2@example.com'] - # } + # end + # + # === Errors # # This method may raise: # @@ -415,6 +467,7 @@ module Net # :nodoc: # * Net::SMTPUnknownError # * IOError # * TimeoutError + # def send_message( msgstr, from_addr, *to_addrs ) send0(from_addr, to_addrs.flatten) { @socket.write_message msgstr @@ -424,33 +477,40 @@ module Net # :nodoc: alias send_mail send_message alias sendmail send_message # obsolete + # # Opens a message writer stream and gives it to the block. # The stream is valid only in the block, and has these methods: # # puts(str = ''):: outputs STR and CR LF. - # print(str):: outputs STR. - # printf(fmt, *args):: outputs sprintf(fmt,*args). - # write(str):: outputs STR and returns the length of written bytes. - # <<(str):: outputs STR and returns self. + # print(str):: outputs STR. + # printf(fmt, *args):: outputs sprintf(fmt,*args). + # write(str):: outputs STR and returns the length of written bytes. + # <<(str):: outputs STR and returns self. # # If a single CR ("\r") or LF ("\n") is found in the message, # it is converted to the CR LF pair. You cannot send a binary # message with this method. # + # === Parameters + # # +from_addr+ is a String representing the source mail address. + # # +to_addr+ is a String or Strings or Array of Strings, representing # the destination mail address or addresses. # - # # example - # Net::SMTP.start('smtp.example.com', 25) {|smtp| - # smtp.open_message_stream('from@example.com', ['dest@example.com']) {|f| + # === Example + # + # Net::SMTP.start('smtp.example.com', 25) do |smtp| + # smtp.open_message_stream('from@example.com', ['dest@example.com']) do |f| # f.puts 'From: from@example.com' # f.puts 'To: dest@example.com' # f.puts 'Subject: test message' # f.puts # f.puts 'This is a test message.' - # } - # } + # end + # end + # + # === Errors # # This method may raise: # @@ -460,6 +520,7 @@ module Net # :nodoc: # * Net::SMTPUnknownError # * IOError # * TimeoutError + # def open_message_stream( from_addr, *to_addrs, &block ) # :yield: stream send0(from_addr, to_addrs.flatten) { @socket.write_message_by_block(&block) diff --git a/lib/net/telnet.rb b/lib/net/telnet.rb index 4dfab5853d..1df488ca0b 100644 --- a/lib/net/telnet.rb +++ b/lib/net/telnet.rb @@ -1,94 +1,98 @@ -# = net/telnet.rb - simple telnet client library +# = net/telnet.rb - Simple Telnet Client Library # -# Wakou Aoyama -# -# == Overview +# Author:: Wakou Aoyama +# Documentation:: William Webber and Wakou Aoyama # # This file holds the class Net::Telnet, which provides client-side # telnet functionality. # -# The telnet protocol allows a client to login remotely to a user -# account on a server and execute commands via a shell. The equivalent -# is done by creating a Net::Telnet class with the Host option -# set to your host, calling #login() with your user and password, -# issuing one or more #cmd() calls, and then calling #close() -# to end the session. The #waitfor(), #print(), #puts(), and -# #write() methods, which #cmd() is implemented on top of, are -# only needed if you are doing something more complicated. -# -# A Net::Telnet object can also be used to connect to non-telnet -# services, such as SMTP or HTTP. In this case, you normally -# want to provide the Port option to specify the port to -# connect to, and set the Telnetmode option to false to prevent -# the client from attempting to interpret telnet command sequences. -# Generally, #login() will not work with other protocols, and you -# have to handle authentication yourself. -# For some protocols, it will be possible to specify the Prompt -# option once when you create the Telnet object and use #cmd() calls; -# for others, you will have to specify the response sequence to -# look for as the Match option to every #cmd() call, or call -# #puts() and #waitfor() directly; for yet others, you will have -# to use #sysread() instead of #waitfor() and parse server -# responses yourself. -# -# It is worth noting that when you create a new Net::Telnet object, -# you can supply a proxy IO channel via the Proxy option. This -# can be used to attach the Telnet object to other Telnet objects, -# to already open sockets, or to any read-write IO object. This -# can be useful, for instance, for setting up a test fixture for -# unit testing. -# -# == Examples of use. -# -# === Log in and send a command, echoing all output to stdout. -# -# localhost = Net::Telnet::new({"Host" => "localhost", -# "Timeout" => 10, -# "Prompt" => /[$%#>] \z/n}) -# localhost.login("username", "password"){|c| print c } -# localhost.cmd("command"){|c| print c } -# localhost.close -# -# -# === Check a POP server to see if you have mail. -# -# pop = Net::Telnet::new({"Host" => "your_destination_host_here", -# "Port" => 110, -# "Telnetmode" => false, -# "Prompt" => /^\+OK/n}) -# pop.cmd("user " + "your_username_here"){|c| print c} -# pop.cmd("pass " + "your_password_here"){|c| print c} -# pop.cmd("list"){|c| print c} -# -# == References. +# For documentation, see Net::Telnet. # -# There are a large number of RFCs relevant to the Telnet protocol. -# RFCs 854-861 define the base protocol. For a complete listing -# of relevant RFCs, see -# http://www.omnifarious.org/~hopper/technical/telnet-rfc.html - require "socket" require "delegate" require "timeout" require "English" + +module Net -module Net # :nodoc: - + # + # == Net::Telnet + # # Provides telnet client functionality. # - # This class also has, through delegation, all the methods of - # a socket object (by default, a TCPSocket, but can be set - # by the Proxy option to new()). This provides methods - # such as #close() to end the session and #sysread() to - # read data directly from the host, instead of via the - # #waitfor() mechanism. Note that if you do use #sysread() - # directly when in telnet mode, you should probably pass - # the output through #preprocess() to extract telnet command - # sequences. + # This class also has, through delegation, all the methods of a + # socket object (by default, a +TCPSocket+, but can be set by the + # +Proxy+ option to new()). This provides methods such as + # close() to end the session and sysread() to read + # data directly from the host, instead of via the waitfor() + # mechanism. Note that if you do use sysread() directly + # when in telnet mode, you should probably pass the output through + # preprocess() to extract telnet command sequences. + # + # == Overview + # + # The telnet protocol allows a client to login remotely to a user + # account on a server and execute commands via a shell. The equivalent + # is done by creating a Net::Telnet class with the +Host+ option + # set to your host, calling #login() with your user and password, + # issuing one or more #cmd() calls, and then calling #close() + # to end the session. The #waitfor(), #print(), #puts(), and + # #write() methods, which #cmd() is implemented on top of, are + # only needed if you are doing something more complicated. + # + # A Net::Telnet object can also be used to connect to non-telnet + # services, such as SMTP or HTTP. In this case, you normally + # want to provide the +Port+ option to specify the port to + # connect to, and set the +Telnetmode+ option to false to prevent + # the client from attempting to interpret telnet command sequences. + # Generally, #login() will not work with other protocols, and you + # have to handle authentication yourself. + # + # For some protocols, it will be possible to specify the +Prompt+ + # option once when you create the Telnet object and use #cmd() calls; + # for others, you will have to specify the response sequence to + # look for as the Match option to every #cmd() call, or call + # #puts() and #waitfor() directly; for yet others, you will have + # to use #sysread() instead of #waitfor() and parse server + # responses yourself. + # + # It is worth noting that when you create a new Net::Telnet object, + # you can supply a proxy IO channel via the Proxy option. This + # can be used to attach the Telnet object to other Telnet objects, + # to already open sockets, or to any read-write IO object. This + # can be useful, for instance, for setting up a test fixture for + # unit testing. + # + # == Examples + # + # === Log in and send a command, echoing all output to stdout + # + # localhost = Net::Telnet::new("Host" => "localhost", + # "Timeout" => 10, + # "Prompt" => /[$%#>] \z/n) + # localhost.login("username", "password") { |c| print c } + # localhost.cmd("command") { |c| print c } + # localhost.close + # + # + # === Check a POP server to see if you have mail + # + # pop = Net::Telnet::new("Host" => "your_destination_host_here", + # "Port" => 110, + # "Telnetmode" => false, + # "Prompt" => /^\+OK/n) + # pop.cmd("user " + "your_username_here") { |c| print c } + # pop.cmd("pass " + "your_password_here") { |c| print c } + # pop.cmd("list") { |c| print c } + # + # == References + # + # There are a large number of RFCs relevant to the Telnet protocol. + # RFCs 854-861 define the base protocol. For a complete listing + # of relevant RFCs, see + # http://www.omnifarious.org/~hopper/technical/telnet-rfc.html # - # See the documentation to the telnet.rb file for an overview - # and examples of usage. class Telnet < SimpleDelegator # :stopdoc: @@ -163,6 +167,7 @@ module Net # :nodoc: REVISION = '$Id$' # :startdoc: + # # Creates a new Net::Telnet object. # # Attempts to connect to the host (unless the Proxy option is @@ -176,7 +181,7 @@ module Net # :nodoc: # +options+ is a hash of options. The following example lists # all options and their default values. # - # host = Net::Telnet::new({ + # host = Net::Telnet::new( # "Host" => "localhost", # default: "localhost" # "Port" => 23, # default: 23 # "Binmode" => false, # default: false @@ -189,7 +194,7 @@ module Net # :nodoc: # "Waittime" => 0, # default: 0 # "Proxy" => proxy # default: nil # # proxy is Net::Telnet or IO object - # }) + # ) # # The options have the following meanings: # @@ -266,6 +271,7 @@ module Net # :nodoc: # instance will use that one's socket for communication. If an # IO object, it is used directly for communication. Any other # kind of object will cause an error to be raised. + # def initialize(options) # :yield: mesg @options = options @options["Host"] = "localhost" unless @options.has_key?("Host") -- cgit v1.2.3