PageRenderTime 65ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Util/IronRuby/lib/ruby/1.8/net/pop.rb

http://github.com/IronLanguages/main
Ruby | 881 lines | 356 code | 92 blank | 433 comment | 21 complexity | 21721eee763dc1ea2f237c8a8fac438a MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. # = net/pop.rb
  2. #
  3. # Copyright (c) 1999-2003 Yukihiro Matsumoto.
  4. #
  5. # Copyright (c) 1999-2003 Minero Aoki.
  6. #
  7. # Written & maintained by Minero Aoki <aamine@loveruby.net>.
  8. #
  9. # Documented by William Webber and Minero Aoki.
  10. #
  11. # This program is free software. You can re-distribute and/or
  12. # modify this program under the same terms as Ruby itself,
  13. # Ruby Distribute License or GNU General Public License.
  14. #
  15. # NOTE: You can find Japanese version of this document in
  16. # the doc/net directory of the standard ruby interpreter package.
  17. #
  18. # $Id: pop.rb 22000 2009-02-03 05:34:11Z shyouhei $
  19. #
  20. # See Net::POP3 for documentation.
  21. #
  22. require 'net/protocol'
  23. require 'digest/md5'
  24. module Net
  25. # Non-authentication POP3 protocol error
  26. # (reply code "-ERR", except authentication).
  27. class POPError < ProtocolError; end
  28. # POP3 authentication error.
  29. class POPAuthenticationError < ProtoAuthError; end
  30. # Unexpected response from the server.
  31. class POPBadResponse < POPError; end
  32. #
  33. # = Net::POP3
  34. #
  35. # == What is This Library?
  36. #
  37. # This library provides functionality for retrieving
  38. # email via POP3, the Post Office Protocol version 3. For details
  39. # of POP3, see [RFC1939] (http://www.ietf.org/rfc/rfc1939.txt).
  40. #
  41. # == Examples
  42. #
  43. # === Retrieving Messages
  44. #
  45. # This example retrieves messages from the server and deletes them
  46. # on the server.
  47. #
  48. # Messages are written to files named 'inbox/1', 'inbox/2', ....
  49. # Replace 'pop.example.com' with your POP3 server address, and
  50. # 'YourAccount' and 'YourPassword' with the appropriate account
  51. # details.
  52. #
  53. # require 'net/pop'
  54. #
  55. # pop = Net::POP3.new('pop.example.com')
  56. # pop.start('YourAccount', 'YourPassword') # (1)
  57. # if pop.mails.empty?
  58. # puts 'No mail.'
  59. # else
  60. # i = 0
  61. # pop.each_mail do |m| # or "pop.mails.each ..." # (2)
  62. # File.open("inbox/#{i}", 'w') do |f|
  63. # f.write m.pop
  64. # end
  65. # m.delete
  66. # i += 1
  67. # end
  68. # puts "#{pop.mails.size} mails popped."
  69. # end
  70. # pop.finish # (3)
  71. #
  72. # 1. Call Net::POP3#start and start POP session.
  73. # 2. Access messages by using POP3#each_mail and/or POP3#mails.
  74. # 3. Close POP session by calling POP3#finish or use the block form of #start.
  75. #
  76. # === Shortened Code
  77. #
  78. # The example above is very verbose. You can shorten the code by using
  79. # some utility methods. First, the block form of Net::POP3.start can
  80. # be used instead of POP3.new, POP3#start and POP3#finish.
  81. #
  82. # require 'net/pop'
  83. #
  84. # Net::POP3.start('pop.example.com', 110,
  85. # 'YourAccount', 'YourPassword') do |pop|
  86. # if pop.mails.empty?
  87. # puts 'No mail.'
  88. # else
  89. # i = 0
  90. # pop.each_mail do |m| # or "pop.mails.each ..."
  91. # File.open("inbox/#{i}", 'w') do |f|
  92. # f.write m.pop
  93. # end
  94. # m.delete
  95. # i += 1
  96. # end
  97. # puts "#{pop.mails.size} mails popped."
  98. # end
  99. # end
  100. #
  101. # POP3#delete_all is an alternative for #each_mail and #delete.
  102. #
  103. # require 'net/pop'
  104. #
  105. # Net::POP3.start('pop.example.com', 110,
  106. # 'YourAccount', 'YourPassword') do |pop|
  107. # if pop.mails.empty?
  108. # puts 'No mail.'
  109. # else
  110. # i = 1
  111. # pop.delete_all do |m|
  112. # File.open("inbox/#{i}", 'w') do |f|
  113. # f.write m.pop
  114. # end
  115. # i += 1
  116. # end
  117. # end
  118. # end
  119. #
  120. # And here is an even shorter example.
  121. #
  122. # require 'net/pop'
  123. #
  124. # i = 0
  125. # Net::POP3.delete_all('pop.example.com', 110,
  126. # 'YourAccount', 'YourPassword') do |m|
  127. # File.open("inbox/#{i}", 'w') do |f|
  128. # f.write m.pop
  129. # end
  130. # i += 1
  131. # end
  132. #
  133. # === Memory Space Issues
  134. #
  135. # All the examples above get each message as one big string.
  136. # This example avoids this.
  137. #
  138. # require 'net/pop'
  139. #
  140. # i = 1
  141. # Net::POP3.delete_all('pop.example.com', 110,
  142. # 'YourAccount', 'YourPassword') do |m|
  143. # File.open("inbox/#{i}", 'w') do |f|
  144. # m.pop do |chunk| # get a message little by little.
  145. # f.write chunk
  146. # end
  147. # i += 1
  148. # end
  149. # end
  150. #
  151. # === Using APOP
  152. #
  153. # The net/pop library supports APOP authentication.
  154. # To use APOP, use the Net::APOP class instead of the Net::POP3 class.
  155. # You can use the utility method, Net::POP3.APOP(). For example:
  156. #
  157. # require 'net/pop'
  158. #
  159. # # Use APOP authentication if $isapop == true
  160. # pop = Net::POP3.APOP($is_apop).new('apop.example.com', 110)
  161. # pop.start(YourAccount', 'YourPassword') do |pop|
  162. # # Rest of the code is the same.
  163. # end
  164. #
  165. # === Fetch Only Selected Mail Using 'UIDL' POP Command
  166. #
  167. # If your POP server provides UIDL functionality,
  168. # you can grab only selected mails from the POP server.
  169. # e.g.
  170. #
  171. # def need_pop?( id )
  172. # # determine if we need pop this mail...
  173. # end
  174. #
  175. # Net::POP3.start('pop.example.com', 110,
  176. # 'Your account', 'Your password') do |pop|
  177. # pop.mails.select { |m| need_pop?(m.unique_id) }.each do |m|
  178. # do_something(m.pop)
  179. # end
  180. # end
  181. #
  182. # The POPMail#unique_id() method returns the unique-id of the message as a
  183. # String. Normally the unique-id is a hash of the message.
  184. #
  185. class POP3 < Protocol
  186. Revision = %q$Revision: 22000 $.split[1]
  187. #
  188. # Class Parameters
  189. #
  190. # The default port for POP3 connections, port 110
  191. def POP3.default_port
  192. 110
  193. end
  194. def POP3.socket_type #:nodoc: obsolete
  195. Net::InternetMessageIO
  196. end
  197. #
  198. # Utilities
  199. #
  200. # Returns the APOP class if +isapop+ is true; otherwise, returns
  201. # the POP class. For example:
  202. #
  203. # # Example 1
  204. # pop = Net::POP3::APOP($is_apop).new(addr, port)
  205. #
  206. # # Example 2
  207. # Net::POP3::APOP($is_apop).start(addr, port) do |pop|
  208. # ....
  209. # end
  210. #
  211. def POP3.APOP( isapop )
  212. isapop ? APOP : POP3
  213. end
  214. # Starts a POP3 session and iterates over each POPMail object,
  215. # yielding it to the +block+.
  216. # This method is equivalent to:
  217. #
  218. # Net::POP3.start(address, port, account, password) do |pop|
  219. # pop.each_mail do |m|
  220. # yield m
  221. # end
  222. # end
  223. #
  224. # This method raises a POPAuthenticationError if authentication fails.
  225. #
  226. # === Example
  227. #
  228. # Net::POP3.foreach('pop.example.com', 110,
  229. # 'YourAccount', 'YourPassword') do |m|
  230. # file.write m.pop
  231. # m.delete if $DELETE
  232. # end
  233. #
  234. def POP3.foreach( address, port = nil,
  235. account = nil, password = nil,
  236. isapop = false, &block ) # :yields: message
  237. start(address, port, account, password, isapop) {|pop|
  238. pop.each_mail(&block)
  239. }
  240. end
  241. # Starts a POP3 session and deletes all messages on the server.
  242. # If a block is given, each POPMail object is yielded to it before
  243. # being deleted.
  244. #
  245. # This method raises a POPAuthenticationError if authentication fails.
  246. #
  247. # === Example
  248. #
  249. # Net::POP3.delete_all('pop.example.com', 110,
  250. # 'YourAccount', 'YourPassword') do |m|
  251. # file.write m.pop
  252. # end
  253. #
  254. def POP3.delete_all( address, port = nil,
  255. account = nil, password = nil,
  256. isapop = false, &block )
  257. start(address, port, account, password, isapop) {|pop|
  258. pop.delete_all(&block)
  259. }
  260. end
  261. # Opens a POP3 session, attempts authentication, and quits.
  262. #
  263. # This method raises POPAuthenticationError if authentication fails.
  264. #
  265. # === Example: normal POP3
  266. #
  267. # Net::POP3.auth_only('pop.example.com', 110,
  268. # 'YourAccount', 'YourPassword')
  269. #
  270. # === Example: APOP
  271. #
  272. # Net::POP3.auth_only('pop.example.com', 110,
  273. # 'YourAccount', 'YourPassword', true)
  274. #
  275. def POP3.auth_only( address, port = nil,
  276. account = nil, password = nil,
  277. isapop = false )
  278. new(address, port, isapop).auth_only account, password
  279. end
  280. # Starts a pop3 session, attempts authentication, and quits.
  281. # This method must not be called while POP3 session is opened.
  282. # This method raises POPAuthenticationError if authentication fails.
  283. def auth_only( account, password )
  284. raise IOError, 'opening previously opened POP session' if started?
  285. start(account, password) {
  286. ;
  287. }
  288. end
  289. #
  290. # Session management
  291. #
  292. # Creates a new POP3 object and open the connection. Equivalent to
  293. #
  294. # Net::POP3.new(address, port, isapop).start(account, password)
  295. #
  296. # If +block+ is provided, yields the newly-opened POP3 object to it,
  297. # and automatically closes it at the end of the session.
  298. #
  299. # === Example
  300. #
  301. # Net::POP3.start(addr, port, account, password) do |pop|
  302. # pop.each_mail do |m|
  303. # file.write m.pop
  304. # m.delete
  305. # end
  306. # end
  307. #
  308. def POP3.start( address, port = nil,
  309. account = nil, password = nil,
  310. isapop = false, &block ) # :yield: pop
  311. new(address, port, isapop).start(account, password, &block)
  312. end
  313. # Creates a new POP3 object.
  314. #
  315. # +address+ is the hostname or ip address of your POP3 server.
  316. #
  317. # The optional +port+ is the port to connect to; it defaults to 110.
  318. #
  319. # The optional +isapop+ specifies whether this connection is going
  320. # to use APOP authentication; it defaults to +false+.
  321. #
  322. # This method does *not* open the TCP connection.
  323. def initialize( addr, port = nil, isapop = false )
  324. @address = addr
  325. @port = port || self.class.default_port
  326. @apop = isapop
  327. @command = nil
  328. @socket = nil
  329. @started = false
  330. @open_timeout = 30
  331. @read_timeout = 60
  332. @debug_output = nil
  333. @mails = nil
  334. @n_mails = nil
  335. @n_bytes = nil
  336. end
  337. # Does this instance use APOP authentication?
  338. def apop?
  339. @apop
  340. end
  341. # Provide human-readable stringification of class state.
  342. def inspect
  343. "#<#{self.class} #{@address}:#{@port} open=#{@started}>"
  344. end
  345. # *WARNING*: This method causes a serious security hole.
  346. # Use this method only for debugging.
  347. #
  348. # Set an output stream for debugging.
  349. #
  350. # === Example
  351. #
  352. # pop = Net::POP.new(addr, port)
  353. # pop.set_debug_output $stderr
  354. # pop.start(account, passwd) do |pop|
  355. # ....
  356. # end
  357. #
  358. def set_debug_output( arg )
  359. @debug_output = arg
  360. end
  361. # The address to connect to.
  362. attr_reader :address
  363. # The port number to connect to.
  364. attr_reader :port
  365. # Seconds to wait until a connection is opened.
  366. # If the POP3 object cannot open a connection within this time,
  367. # it raises a TimeoutError exception.
  368. attr_accessor :open_timeout
  369. # Seconds to wait until reading one block (by one read(1) call).
  370. # If the POP3 object cannot complete a read() within this time,
  371. # it raises a TimeoutError exception.
  372. attr_reader :read_timeout
  373. # Set the read timeout.
  374. def read_timeout=( sec )
  375. @command.socket.read_timeout = sec if @command
  376. @read_timeout = sec
  377. end
  378. # +true+ if the POP3 session has started.
  379. def started?
  380. @started
  381. end
  382. alias active? started? #:nodoc: obsolete
  383. # Starts a POP3 session.
  384. #
  385. # When called with block, gives a POP3 object to the block and
  386. # closes the session after block call finishes.
  387. #
  388. # This method raises a POPAuthenticationError if authentication fails.
  389. def start( account, password ) # :yield: pop
  390. raise IOError, 'POP session already started' if @started
  391. if block_given?
  392. begin
  393. do_start account, password
  394. return yield(self)
  395. ensure
  396. do_finish
  397. end
  398. else
  399. do_start account, password
  400. return self
  401. end
  402. end
  403. def do_start( account, password )
  404. @socket = self.class.socket_type.old_open(@address, @port,
  405. @open_timeout, @read_timeout, @debug_output)
  406. on_connect
  407. @command = POP3Command.new(@socket)
  408. if apop?
  409. @command.apop account, password
  410. else
  411. @command.auth account, password
  412. end
  413. @started = true
  414. ensure
  415. do_finish if not @started
  416. end
  417. private :do_start
  418. def on_connect
  419. end
  420. private :on_connect
  421. # Finishes a POP3 session and closes TCP connection.
  422. def finish
  423. raise IOError, 'POP session not yet started' unless started?
  424. do_finish
  425. end
  426. def do_finish
  427. @mails = nil
  428. @n_mails = nil
  429. @n_bytes = nil
  430. @command.quit if @command
  431. ensure
  432. @started = false
  433. @command = nil
  434. @socket.close if @socket and not @socket.closed?
  435. @socket = nil
  436. end
  437. private :do_finish
  438. def command
  439. raise IOError, 'POP session not opened yet' \
  440. if not @socket or @socket.closed?
  441. @command
  442. end
  443. private :command
  444. #
  445. # POP protocol wrapper
  446. #
  447. # Returns the number of messages on the POP server.
  448. def n_mails
  449. return @n_mails if @n_mails
  450. @n_mails, @n_bytes = command().stat
  451. @n_mails
  452. end
  453. # Returns the total size in bytes of all the messages on the POP server.
  454. def n_bytes
  455. return @n_bytes if @n_bytes
  456. @n_mails, @n_bytes = command().stat
  457. @n_bytes
  458. end
  459. # Returns an array of Net::POPMail objects, representing all the
  460. # messages on the server. This array is renewed when the session
  461. # restarts; otherwise, it is fetched from the server the first time
  462. # this method is called (directly or indirectly) and cached.
  463. #
  464. # This method raises a POPError if an error occurs.
  465. def mails
  466. return @mails.dup if @mails
  467. if n_mails() == 0
  468. # some popd raises error for LIST on the empty mailbox.
  469. @mails = []
  470. return []
  471. end
  472. @mails = command().list.map {|num, size|
  473. POPMail.new(num, size, self, command())
  474. }
  475. @mails.dup
  476. end
  477. # Yields each message to the passed-in block in turn.
  478. # Equivalent to:
  479. #
  480. # pop3.mails.each do |popmail|
  481. # ....
  482. # end
  483. #
  484. # This method raises a POPError if an error occurs.
  485. def each_mail( &block ) # :yield: message
  486. mails().each(&block)
  487. end
  488. alias each each_mail
  489. # Deletes all messages on the server.
  490. #
  491. # If called with a block, yields each message in turn before deleting it.
  492. #
  493. # === Example
  494. #
  495. # n = 1
  496. # pop.delete_all do |m|
  497. # File.open("inbox/#{n}") do |f|
  498. # f.write m.pop
  499. # end
  500. # n += 1
  501. # end
  502. #
  503. # This method raises a POPError if an error occurs.
  504. #
  505. def delete_all # :yield: message
  506. mails().each do |m|
  507. yield m if block_given?
  508. m.delete unless m.deleted?
  509. end
  510. end
  511. # Resets the session. This clears all "deleted" marks from messages.
  512. #
  513. # This method raises a POPError if an error occurs.
  514. def reset
  515. command().rset
  516. mails().each do |m|
  517. m.instance_eval {
  518. @deleted = false
  519. }
  520. end
  521. end
  522. def set_all_uids #:nodoc: internal use only (called from POPMail#uidl)
  523. command().uidl.each do |num, uid|
  524. @mails.find {|m| m.number == num }.uid = uid
  525. end
  526. end
  527. end # class POP3
  528. # class aliases
  529. POP = POP3
  530. POPSession = POP3
  531. POP3Session = POP3
  532. #
  533. # This class is equivalent to POP3, except that it uses APOP authentication.
  534. #
  535. class APOP < POP3
  536. # Always returns true.
  537. def apop?
  538. true
  539. end
  540. end
  541. # class aliases
  542. APOPSession = APOP
  543. #
  544. # This class represents a message which exists on the POP server.
  545. # Instances of this class are created by the POP3 class; they should
  546. # not be directly created by the user.
  547. #
  548. class POPMail
  549. def initialize( num, len, pop, cmd ) #:nodoc:
  550. @number = num
  551. @length = len
  552. @pop = pop
  553. @command = cmd
  554. @deleted = false
  555. @uid = nil
  556. end
  557. # The sequence number of the message on the server.
  558. attr_reader :number
  559. # The length of the message in octets.
  560. attr_reader :length
  561. alias size length
  562. # Provide human-readable stringification of class state.
  563. def inspect
  564. "#<#{self.class} #{@number}#{@deleted ? ' deleted' : ''}>"
  565. end
  566. #
  567. # This method fetches the message. If called with a block, the
  568. # message is yielded to the block one chunk at a time. If called
  569. # without a block, the message is returned as a String. The optional
  570. # +dest+ argument will be prepended to the returned String; this
  571. # argument is essentially obsolete.
  572. #
  573. # === Example without block
  574. #
  575. # POP3.start('pop.example.com', 110,
  576. # 'YourAccount, 'YourPassword') do |pop|
  577. # n = 1
  578. # pop.mails.each do |popmail|
  579. # File.open("inbox/#{n}", 'w') do |f|
  580. # f.write popmail.pop
  581. # end
  582. # popmail.delete
  583. # n += 1
  584. # end
  585. # end
  586. #
  587. # === Example with block
  588. #
  589. # POP3.start('pop.example.com', 110,
  590. # 'YourAccount, 'YourPassword') do |pop|
  591. # n = 1
  592. # pop.mails.each do |popmail|
  593. # File.open("inbox/#{n}", 'w') do |f|
  594. # popmail.pop do |chunk| ####
  595. # f.write chunk
  596. # end
  597. # end
  598. # n += 1
  599. # end
  600. # end
  601. #
  602. # This method raises a POPError if an error occurs.
  603. #
  604. def pop( dest = '', &block ) # :yield: message_chunk
  605. if block_given?
  606. @command.retr(@number, &block)
  607. nil
  608. else
  609. @command.retr(@number) do |chunk|
  610. dest << chunk
  611. end
  612. dest
  613. end
  614. end
  615. alias all pop #:nodoc: obsolete
  616. alias mail pop #:nodoc: obsolete
  617. # Fetches the message header and +lines+ lines of body.
  618. #
  619. # The optional +dest+ argument is obsolete.
  620. #
  621. # This method raises a POPError if an error occurs.
  622. def top( lines, dest = '' )
  623. @command.top(@number, lines) do |chunk|
  624. dest << chunk
  625. end
  626. dest
  627. end
  628. # Fetches the message header.
  629. #
  630. # The optional +dest+ argument is obsolete.
  631. #
  632. # This method raises a POPError if an error occurs.
  633. def header( dest = '' )
  634. top(0, dest)
  635. end
  636. # Marks a message for deletion on the server. Deletion does not
  637. # actually occur until the end of the session; deletion may be
  638. # cancelled for _all_ marked messages by calling POP3#reset().
  639. #
  640. # This method raises a POPError if an error occurs.
  641. #
  642. # === Example
  643. #
  644. # POP3.start('pop.example.com', 110,
  645. # 'YourAccount, 'YourPassword') do |pop|
  646. # n = 1
  647. # pop.mails.each do |popmail|
  648. # File.open("inbox/#{n}", 'w') do |f|
  649. # f.write popmail.pop
  650. # end
  651. # popmail.delete ####
  652. # n += 1
  653. # end
  654. # end
  655. #
  656. def delete
  657. @command.dele @number
  658. @deleted = true
  659. end
  660. alias delete! delete #:nodoc: obsolete
  661. # True if the mail has been deleted.
  662. def deleted?
  663. @deleted
  664. end
  665. # Returns the unique-id of the message.
  666. # Normally the unique-id is a hash string of the message.
  667. #
  668. # This method raises a POPError if an error occurs.
  669. def unique_id
  670. return @uid if @uid
  671. @pop.set_all_uids
  672. @uid
  673. end
  674. alias uidl unique_id
  675. def uid=( uid ) #:nodoc: internal use only (used from POP3#set_all_uids)
  676. @uid = uid
  677. end
  678. end # class POPMail
  679. class POP3Command #:nodoc: internal use only
  680. def initialize( sock )
  681. @socket = sock
  682. @error_occured = false
  683. res = check_response(critical { recv_response() })
  684. @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/)
  685. end
  686. def inspect
  687. "#<#{self.class} socket=#{@socket}>"
  688. end
  689. def auth( account, password )
  690. check_response_auth(critical {
  691. check_response_auth(get_response('USER %s', account))
  692. get_response('PASS %s', password)
  693. })
  694. end
  695. def apop( account, password )
  696. raise POPAuthenticationError, 'not APOP server; cannot login' \
  697. unless @apop_stamp
  698. check_response_auth(critical {
  699. get_response('APOP %s %s',
  700. account,
  701. Digest::MD5.hexdigest(@apop_stamp + password))
  702. })
  703. end
  704. def list
  705. critical {
  706. getok 'LIST'
  707. list = []
  708. @socket.each_list_item do |line|
  709. m = /\A(\d+)[ \t]+(\d+)/.match(line) or
  710. raise POPBadResponse, "bad response: #{line}"
  711. list.push [m[1].to_i, m[2].to_i]
  712. end
  713. return list
  714. }
  715. end
  716. def stat
  717. res = check_response(critical { get_response('STAT') })
  718. m = /\A\+OK\s+(\d+)\s+(\d+)/.match(res) or
  719. raise POPBadResponse, "wrong response format: #{res}"
  720. [m[1].to_i, m[2].to_i]
  721. end
  722. def rset
  723. check_response(critical { get_response 'RSET' })
  724. end
  725. def top( num, lines = 0, &block )
  726. critical {
  727. getok('TOP %d %d', num, lines)
  728. @socket.each_message_chunk(&block)
  729. }
  730. end
  731. def retr( num, &block )
  732. critical {
  733. getok('RETR %d', num)
  734. @socket.each_message_chunk(&block)
  735. }
  736. end
  737. def dele( num )
  738. check_response(critical { get_response('DELE %d', num) })
  739. end
  740. def uidl( num = nil )
  741. if num
  742. res = check_response(critical { get_response('UIDL %d', num) })
  743. return res.split(/ /)[1]
  744. else
  745. critical {
  746. getok('UIDL')
  747. table = {}
  748. @socket.each_list_item do |line|
  749. num, uid = line.split
  750. table[num.to_i] = uid
  751. end
  752. return table
  753. }
  754. end
  755. end
  756. def quit
  757. check_response(critical { get_response('QUIT') })
  758. end
  759. private
  760. def getok( fmt, *fargs )
  761. @socket.writeline sprintf(fmt, *fargs)
  762. check_response(recv_response())
  763. end
  764. def get_response( fmt, *fargs )
  765. @socket.writeline sprintf(fmt, *fargs)
  766. recv_response()
  767. end
  768. def recv_response
  769. @socket.readline
  770. end
  771. def check_response( res )
  772. raise POPError, res unless /\A\+OK/i === res
  773. res
  774. end
  775. def check_response_auth( res )
  776. raise POPAuthenticationError, res unless /\A\+OK/i === res
  777. res
  778. end
  779. def critical
  780. return '+OK dummy ok response' if @error_occured
  781. begin
  782. return yield()
  783. rescue Exception
  784. @error_occured = true
  785. raise
  786. end
  787. end
  788. end # class POP3Command
  789. end # module Net