Class: Net::NNTP
- Inherits:
-
Object
- Object
- Net::NNTP
- Defined in:
- lib/nntp.rb
Overview
Net::NNTP
What is This Library?
This library provides functionality to retrieve and, or post Usenet news articles via NNTP, the Network News Transfer Protocol. The Usenet is a world-wide distributed discussion system. It consists of a set of “newsgroups” with names that are classified hierarchically by topic. “articles” or “messages” are “posted” to these newsgroups by people on computers with the appropriate software – these articles are then broadcast to other interconnected NNTP servers via a wide variety of networks. For details of NNTP itself, see [RFC977] (www.ietf.org/rfc/rfc977.txt).
What is This Library NOT?
This library does NOT provide functions to compose Usenet news. You must create and, or format them yourself as per guidelines per Standard for Interchange of Usenet messages, see [RFC850], [RFC2047] and a fews other RFC’s (www.ietf.org/rfc/rfc850.txt), (www.ietf.org/rfc/rfc2047.txt).
FYI: the official documentation on Usenet news extentions is: [RFC2980] (www.ietf.org/rfc/rfc2980.txt).
Examples
Posting Messages
You must open a connection to an NNTP server before posting messages. The first argument is the address of your NNTP server, and the second argument is the port number. Using NNTP.start with a block is the simplest way to do this. This way, the NNTP connection is closed automatically after the block is executed.
require 'rubygems'
require 'nntp'
Net::NNTP.start('your.nntp.server', 119) do |nntp|
# Use the NNTP object nntp only in this block.
end
Replace ‘your.nntp.server’ with your NNTP server. Normally your system manager or internet provider supplies a server for you.
Then you can post messages.
require 'date'
date = DateTime.now().strftime(fmt='%a, %d %b %Y %T %z')
msgstr = <<END_OF_MESSAGE
From: Your Name <[email protected]>
Newsgroups: news.group.one, news.group.two ...
Subject: test message
Date: ##date
This is a test .
END_OF_MESSAGE
require 'rubygems'
require 'nntp'
Net::NNTP.start('your.nntp.server', 119) do |nntp|
nntp.post msgstr
end
NOTE: The NNTP message headers such as Date:
, Message-ID:
and, or Path:
if ommited, may also be generated and added by your Usenet news server; better you verify the behavior of your news server.
Closing the Session
You MUST close the NNTP session after posting messages, by calling the Net::NNTP#finish method:
# using NNTP#finish
nntp = Net::NNTP.start('your.nntp.server', 119)
nntp.post msgstr
nntp.finish
You can also use the block form of NNTP.start/NNTP#start. This closes the NNTP session automatically:
# using block form of NNTP.start
Net::NNTP.start('your.nntp.server', 119) do |nntp|
nntp.post msgstr
end
I strongly recommend this scheme. This form is simpler and more robust.
NNTP Authentication
The Net::NNTP class may support various authentication schemes depending on your news server’s reponse to CAPABILITIES command. To use NNTP authentication, pass extra arguments to NNTP.start/NNTP#start.
See NNTP Extension for Authentication: (www.ietf.org/internet-drafts/draft-ietf-nntpext-authinfo-07.txt)
Net::NNTP.start('your.nntp.server', 119,
'YourAccountName', 'YourPassword', :method)
Where :method
can be one of the ‘gassapi’, ‘digest_md5’, ‘cram_md5’, ‘starttls’, ‘external’, ‘plain’, ‘generic’, ‘simple’ or ‘original’; the later and, or unencrypted ones are less secure!
In the case of method :generic
argumnents should be passed to a format string as follows:
Net::NNTP.start('your.nntp.server', 119,
"format", *arguments, :generic)
NOTE: The Authentication mechanism will fallback to a lesser secure scheme, if your Usenet server does not supports method opted by you, except for the :generic
option.
Instance Attribute Summary collapse
-
#address ⇒ Object
readonly
The address of the NNTP server to connect to.
-
#open_timeout ⇒ Object
Seconds to wait while attempting to open a connection.
-
#port ⇒ Object
readonly
The port number of the NNTP server to connect to.
-
#read_timeout ⇒ Object
Seconds to wait while reading one block (by one read(2) call).
Class Method Summary collapse
-
.default_port ⇒ Object
The default NNTP port, port 119.
-
.start(address, port = nil, user = nil, secret = nil, method = nil, &block) ⇒ Object
Creates a new Net::NNTP object and connects to the server.
Instance Method Summary collapse
-
#article(id_num = nil) ⇒ Object
ARTICLE [<Message-ID>|<Number>].
-
#body(id_num = nil) ⇒ Object
BODY [<Message-ID>|<Number>].
-
#date ⇒ Object
DATE.
-
#finish ⇒ Object
Finishes the NNTP session and closes TCP connection.
-
#group(ng) ⇒ Object
GROUP <Newsgroup>.
-
#head(id_num = nil) ⇒ Object
HEAD [<Message-ID>|<Number>].
-
#help ⇒ Object
HELP.
-
#initialize(address, port = nil) ⇒ NNTP
constructor
Creates a new Net::NNTP object.
-
#inspect ⇒ Object
Provide human-readable stringification of class state.
-
#io_body(io_output, id_num = nil) ⇒ Object
IO_BODY <output IO object> [<Message-ID>|<Number>].
-
#last ⇒ Object
LAST.
-
#list(opts = nil) ⇒ Object
LIST [ACTIVE|NEWSGROUPS] [<Wildmat>]]:br: LIST [ACTIVE.TIMES|EXTENSIONS|SUBSCRIPTIONS|OVERVIEW.FMT].
-
#listgroup(ng) ⇒ Object
LISTGROUP <Newsgroup>.
-
#newgroups(date, time, tzone = nil) ⇒ Object
NEWGROUPS <yymmdd> <hhmmss> [GMT].
-
#next ⇒ Object
NEXT.
-
#open_message_stream(&block) ⇒ Object
Opens a message writer stream and gives it to the block.
-
#over(range) ⇒ Object
OVER <Range> # e.g first[-].
-
#post(msgstr) ⇒ Object
POST.
-
#set_debug_output(arg) ⇒ Object
Set an output stream for debug logging.
-
#slave ⇒ Object
SLAVE.
-
#start(user = nil, secret = nil, method = nil) ⇒ Object
Opens a TCP connection and starts the NNTP session.
-
#started? ⇒ Boolean
true
if the NNTP session has been started. -
#stat(id_num = nil) ⇒ Object
STAT [<Message-ID>|<Number>].
-
#xhdr(header, id_range) ⇒ Object
XHDR <Header> <Message-ID>|<Range> # e.g first[-].
-
#xover(range) ⇒ Object
XOVER <Range> # e.g first[-].
Constructor Details
#initialize(address, port = nil) ⇒ NNTP
Creates a new Net::NNTP object.
address
is the hostname or ip address of your NNTP server. port
is the port to connect to; it defaults to port 119.
This method does not opens any TCP connection. You can use NNTP.start instead of NNTP.new if you want to do everything at once. Otherwise, follow NNTP.new with optional changes to :open_timeout
, :read_timeout
and, or NNTP#set_debug_output and then NNTP#start.
215 216 217 218 219 220 221 222 223 224 |
# File 'lib/nntp.rb', line 215 def initialize(address, port = nil) @address = address @port = (port || NNTP.default_port) @socket = nil @started = false @open_timeout = 30 @read_timeout = 60 @error_occured = false @debug_output = nil end |
Instance Attribute Details
#address ⇒ Object (readonly)
The address of the NNTP server to connect to.
232 233 234 |
# File 'lib/nntp.rb', line 232 def address @address end |
#open_timeout ⇒ Object
Seconds to wait while attempting to open a connection. If the connection cannot be opened within this time, a TimeoutError is raised.
239 240 241 |
# File 'lib/nntp.rb', line 239 def open_timeout @open_timeout end |
#port ⇒ Object (readonly)
The port number of the NNTP server to connect to.
235 236 237 |
# File 'lib/nntp.rb', line 235 def port @port end |
#read_timeout ⇒ Object
Seconds to wait while reading one block (by one read(2) call). If the read(2) call does not complete within this time, a TimeoutError is raised.
244 245 246 |
# File 'lib/nntp.rb', line 244 def read_timeout @read_timeout end |
Class Method Details
.default_port ⇒ Object
The default NNTP port, port 119.
201 202 203 |
# File 'lib/nntp.rb', line 201 def NNTP.default_port 119 end |
.start(address, port = nil, user = nil, secret = nil, method = nil, &block) ⇒ Object
Creates a new Net::NNTP object and connects to the server.
This method is equivalent to:
Net::NNTP.new(address, port).start(account, password, :method)
Example
Net::NNTP.start('your.nntp.server') do |nntp|
nntp.post msgstr
end
Block Usage
If called with a block, the newly-opened Net::NNTP object is yielded to the block, and automatically closed when the block finishes. If called without a block, the newly-opened Net::NNTP object is returned to the caller, and it is the caller’s responsibility to close it when finished.
Parameters
address
is the hostname or ip address of your nntp server.
port
is the port to connect to; it defaults to port 119.
The remaining arguments are used for NNTP authentication, if required or desired. user
is the account name, secret
is your password or other authentication token, and method
is the authentication type; defaults to ‘original’. Please read the discussion of NNTP Authentication in the overview notes above.
Errors
This method may raise:
-
Net::NNTPAuthenticationError
-
Net::NNTPFatalError
-
Net::NNTPServerBusy
-
Net::NNTPSyntaxError
-
Net::NNTPUnknownError
-
IOError
-
TimeoutError
318 319 320 321 322 |
# File 'lib/nntp.rb', line 318 def NNTP.start(address, port = nil, user = nil, secret = nil, method = nil, &block) # :yield: nntp new(address, port).start(user, secret, method, &block) end |
Instance Method Details
#article(id_num = nil) ⇒ Object
ARTICLE [<Message-ID>|<Number>]
528 529 530 531 |
# File 'lib/nntp.rb', line 528 def article(id_num = nil) stat, text = longcmd("ARTICLE #{id_num}".strip) return stat[0..2], text end |
#body(id_num = nil) ⇒ Object
BODY [<Message-ID>|<Number>]
534 535 536 537 |
# File 'lib/nntp.rb', line 534 def body(id_num = nil) stat, text = longcmd("BODY #{id_num}".strip) return stat[0..2], text end |
#date ⇒ Object
DATE
546 547 548 549 550 551 552 553 |
# File 'lib/nntp.rb', line 546 def date text = [] stat = shortcmd("DATE") text << stat[4...12] text << stat[12...18] raise NNTPDataError, stat, caller unless text[0].length == 8 and text[1].length == 6 return stat[0..2], text end |
#finish ⇒ Object
Finishes the NNTP session and closes TCP connection. Raises IOError if not started.
432 433 434 435 |
# File 'lib/nntp.rb', line 432 def finish raise IOError, 'not yet started' unless started? do_finish end |
#group(ng) ⇒ Object
GROUP <Newsgroup>
556 557 558 559 |
# File 'lib/nntp.rb', line 556 def group(ng) stat = shortcmd("GROUP %s", ng) return stat[0..2], stat[4..-1].chop end |
#head(id_num = nil) ⇒ Object
HEAD [<Message-ID>|<Number>]
562 563 564 565 |
# File 'lib/nntp.rb', line 562 def head(id_num = nil) stat, text = longcmd("HEAD #{id_num}".strip) return stat[0..2], text end |
#help ⇒ Object
HELP
568 569 570 571 572 573 574 |
# File 'lib/nntp.rb', line 568 def help stat, text = longcmd('HELP') text.each_with_index do |line, index| text[index] = line.gsub(/\A\s+/, '') end return stat[0..2], text end |
#inspect ⇒ Object
Provide human-readable stringification of class state.
227 228 229 |
# File 'lib/nntp.rb', line 227 def inspect #:nodoc: "#<#{self.class} #{@address}:#{@port} started=#{@started}>" end |
#io_body(io_output, id_num = nil) ⇒ Object
IO_BODY <output IO object> [<Message-ID>|<Number>]
540 541 542 543 |
# File 'lib/nntp.rb', line 540 def io_body (io_output, id_num = nil) stat = io_longcmd(io_output, "BODY #{id_num}".strip) return stat[0..2], io_output end |
#last ⇒ Object
LAST
577 578 579 580 |
# File 'lib/nntp.rb', line 577 def last stat = shortcmd('LAST') return stat[0..2], stat[4..-1].chop end |
#list(opts = nil) ⇒ Object
LIST [ACTIVE|NEWSGROUPS] [<Wildmat>]]:br: LIST [ACTIVE.TIMES|EXTENSIONS|SUBSCRIPTIONS|OVERVIEW.FMT]
584 585 586 587 |
# File 'lib/nntp.rb', line 584 def list(opts = nil) stat, text = longcmd("LIST #{opts}".strip) return stat[0..2], text end |
#listgroup(ng) ⇒ Object
LISTGROUP <Newsgroup>
590 591 592 593 |
# File 'lib/nntp.rb', line 590 def listgroup(ng) stat, text = longcmd("LISTGROUP #{ng}".strip) return stat[0..2], text end |
#newgroups(date, time, tzone = nil) ⇒ Object
NEWGROUPS <yymmdd> <hhmmss> [GMT]
603 604 605 606 |
# File 'lib/nntp.rb', line 603 def newgroups(date, time, tzone = nil) stat, text = longcmd("NEWGROUPS #{date} #{time} #{tzone}".strip) return stat[0..2], text end |
#next ⇒ Object
NEXT
609 610 611 612 |
# File 'lib/nntp.rb', line 609 def next stat = shortcmd('NEXT') return stat[0..2], stat[4..-1].chop end |
#open_message_stream(&block) ⇒ Object
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.
If a single CR (“r”) or LF (“n”) is found in the message, it is converted to the CR LF pair. You cannot post a binary message with this method.
Parameters
Block
Example
Net::NNTP.start('nntp.example.com', 119) do |nntp|
nntp. do |f|
f.puts 'From: [email protected]'
f.puts 'Newsgroups: news.group.one, news.group.two ...'
f.puts 'Subject: test message'
f.puts
f.puts 'This is a test message.'
end
end
Errors
This method may raise:
-
Net::NNTPFatalError
-
Net::NNTPPostingNotAllowed
-
Net::NNTPServerBusy
-
Net::NNTPSyntaxError
-
Net::NNTPUnknownError
-
IOError
-
TimeoutError
523 524 525 |
# File 'lib/nntp.rb', line 523 def (&block) # :yield: stream post0 { @socket.(&block) } end |
#over(range) ⇒ Object
OVER <Range> # e.g first[-]
615 616 617 618 |
# File 'lib/nntp.rb', line 615 def over(range) stat, text = longcmd("OVER #{range}".strip) return stat[0..2], text end |
#post(msgstr) ⇒ Object
POST
Posts msgstr
as a message. Single CR (“r”) and LF (“n”) found in the msgstr
, are converted into the CR LF pair. You cannot post a binary message with this method. msgstr
_should include both the message headers and body_. All non US-ASCII, binary and, or multi-part messages should be submitted in an encoded form as per MIME standards.
Example
Net::NNTP.start('nntp.example.com') do |nntp|
nntp.post msgstr
end
Errors
This method may raise:
-
Net::NNTPFatalError
-
Net::NNTPPostingNotAllowed
-
Net::NNTPServerBusy
-
Net::NNTPSyntaxError
-
Net::NNTPUnknownError
-
IOError
-
TimeoutError
475 476 477 478 479 480 |
# File 'lib/nntp.rb', line 475 def post(msgstr) stat = post0 { @socket. msgstr } return stat[0..3], stat[4..-1].chop end |
#set_debug_output(arg) ⇒ Object
Set an output stream for debug logging. You must call this before #start.
Example
nntp = Net::NNTP.new(addr, port)
nntp.set_debug_output $stderr
nntp.start do |nntp|
....
end
WARNING: This method causes serious security holes. Use this method for only debugging.
266 267 268 |
# File 'lib/nntp.rb', line 266 def set_debug_output(arg) @debug_output = arg end |
#slave ⇒ Object
SLAVE
627 628 629 630 |
# File 'lib/nntp.rb', line 627 def slave stat = shortcmd('SLAVE') return stat[0..2], stat[4..-1].chop end |
#start(user = nil, secret = nil, method = nil) ⇒ Object
Opens a TCP connection and starts the NNTP session.
Parameters
If both of user
and secret
are given, NNTP authentication will be attempted using the AUTH command. The method
specifies the type of authentication to attempt; it must be one of :original, :simple, :generic, :plain, :starttls, :external, :cram_md5, :digest_md5 and, or :gassapi may be used. See the discussion of NNTP Authentication in the overview notes.
Block Usage
When this methods is called with a block, the newly-started NNTP 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.
Example
This is very similar to the class method NNTP.start.
require 'rubygems'
require 'nntp'
nntp = Net::NNTP.new('nntp.news.server', 119)
nntp.start(account, password, method) do |nntp|
nntp.post msgstr
end
The primary use of this method (as opposed to NNTP.start) is probably to set debugging (#set_debug_output), which must be done before the session is started.
Errors
If session has already been started, an IOError will be raised.
This method may raise:
-
Net::NNTPAuthenticationError
-
Net::NNTPFatalError
-
Net::NNTPServerBusy
-
Net::NNTPSyntaxError
-
Net::NNTPUnknownError
-
IOError
-
TimeoutError
377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/nntp.rb', line 377 def start(user = nil, secret = nil, method = nil) # :yield: nntp if block_given? begin do_start(user, secret, method) return yield(self) ensure do_finish end else do_start(user, secret, method) return self end end |
#started? ⇒ Boolean
true
if the NNTP session has been started.
325 326 327 |
# File 'lib/nntp.rb', line 325 def started? @started end |
#stat(id_num = nil) ⇒ Object
STAT [<Message-ID>|<Number>]
633 634 635 636 |
# File 'lib/nntp.rb', line 633 def stat(id_num = nil) stat = shortcmd("STAT #{id_num}".strip) return stat[0..2], stat[4..-1].chop end |
#xhdr(header, id_range) ⇒ Object
XHDR <Header> <Message-ID>|<Range> # e.g first[-]
639 640 641 642 |
# File 'lib/nntp.rb', line 639 def xhdr(header, id_range) stat, text = longcmd("XHDR #{header} #{id_range}".strip) return stat[0..2], text end |
#xover(range) ⇒ Object
XOVER <Range> # e.g first[-]
645 646 647 648 |
# File 'lib/nntp.rb', line 645 def xover(range) stat, text = longcmd("XOVER #{range}".strip) return stat[0..2], text end |