summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--lib/net/imap.rb60
-rw-r--r--test/net/imap/test_imap.rb64
3 files changed, 130 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 938501b8d7..2a5d02a08c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri Jul 24 00:13:41 2009 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb (resp_text_code): accepts response codes without
+ text. [ruby-core:24194]
+
+ * lib/net/imap.rb (idle, idle_done): new methods for the IMAP4 IDLE
+ command (RFC 2177). Thanks, Eric Hodel.
+
+ * lib/net/imap.rb (format_date, format_datetime): new method to
+ format IMAP-style date/datetime. Thanks, Eric Hodel.
+
Thu Jul 23 17:31:02 2009 Keiju Ishitsuka <keiju@ruby-lang.org>
* lib/irb/ruby-lex.rb: make irb be able to parse
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index e67c294464..5741568034 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -838,6 +838,41 @@ module Net
return thread_internal("UID THREAD", algorithm, search_keys, charset)
end
+ # Sends an IDLE command that waits for notifications of new or expunged
+ # messages. Yields responses from the server during the IDLE.
+ #
+ # Use #idle_done() to leave IDLE.
+ def idle(&response_handler)
+ raise LocalJumpError, "no block given" unless response_handler
+
+ response = nil
+
+ synchronize do
+ tag = Thread.current[:net_imap_tag] = generate_tag
+ put_string("#{tag} IDLE#{CRLF}")
+
+ add_response_handler(response_handler)
+ @idle_done_cond = new_cond
+ @idle_done_cond.wait
+ @idle_done_cond = nil
+ remove_response_handler(response_handler)
+ put_string("DONE#{CRLF}")
+ response = get_tagged_response(tag, "IDLE")
+ end
+
+ return response
+ end
+
+ # Leaves IDLE.
+ def idle_done
+ if @idle_done_cond.nil?
+ raise Net::IMAP::Error, "not during IDLE"
+ end
+ synchronize do
+ @idle_done_cond.signal
+ end
+ end
+
# Decode a string from modified UTF-7 format to UTF-8.
#
# UTF-7 is a 7-bit encoding of Unicode [UTF7]. IMAP uses a
@@ -873,6 +908,16 @@ module Net
}.force_encoding("ASCII-8BIT")
end
+ # Formats +time+ as an IMAP-style date.
+ def self.format_date(time)
+ return time.strftime('%d-%b-%Y')
+ end
+
+ # Formats +time+ as an IMAP-style date-time.
+ def self.format_datetime(time)
+ return time.strftime('%d-%b-%Y %H:%M %z')
+ end
+
private
CRLF = "\r\n" # :nodoc:
@@ -2776,11 +2821,16 @@ module Net
match(T_SPACE)
result = ResponseCode.new(name, number)
else
- match(T_SPACE)
- @lex_state = EXPR_CTEXT
- token = match(T_TEXT)
- @lex_state = EXPR_BEG
- result = ResponseCode.new(name, token.value)
+ token = lookahead
+ if token.symbol == T_SPACE
+ shift_token
+ @lex_state = EXPR_CTEXT
+ token = match(T_TEXT)
+ @lex_state = EXPR_BEG
+ result = ResponseCode.new(name, token.value)
+ else
+ result = ResponseCode.new(name, nil)
+ end
end
match(T_RBRA)
@lex_state = EXPR_RTEXT
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
index cff09d3cbc..e4e1c25ca0 100644
--- a/test/net/imap/test_imap.rb
+++ b/test/net/imap/test_imap.rb
@@ -18,6 +18,18 @@ class IMAPTest < Test::Unit::TestCase
assert_equal(utf8, s)
end
+ def test_format_date
+ time = Time.mktime(2009, 7, 24)
+ s = Net::IMAP.format_date(time)
+ assert_equal("24-Jul-2009", s)
+ end
+
+ def test_format_datetime
+ time = Time.mktime(2009, 7, 24, 1, 23, 45)
+ s = Net::IMAP.format_datetime(time)
+ assert_match(/\A24-Jul-2009 01:23 [+\-]\d{4}\z/, s)
+ end
+
def test_imaps_unknown_ca
if defined?(OpenSSL)
assert_raise(OpenSSL::SSL::SSLError) do
@@ -112,6 +124,58 @@ class IMAPTest < Test::Unit::TestCase
end
end
+ def test_idle
+ server = TCPServer.new(0)
+ port = server.addr[1]
+ requests = []
+ Thread.start do
+ begin
+ sock = server.accept
+ begin
+ sock.print("* OK test server\r\n")
+ requests.push(sock.gets)
+ sock.print("+ idling\r\n")
+ sock.print("* 3 EXISTS\r\n")
+ sock.print("* 2 EXPUNGE\r\n")
+ requests.push(sock.gets)
+ sock.print("RUBY0001 OK IDLE terminated\r\n")
+ sock.gets
+ sock.print("* BYE terminating connection\r\n")
+ sock.print("RUBY0002 OK LOGOUT completed\r\n")
+ ensure
+ sock.close
+ end
+ rescue
+ end
+ end
+ begin
+ begin
+ imap = Net::IMAP.new("localhost", :port => port)
+ responses = []
+ imap.idle do |res|
+ responses.push(res)
+ if res.name == "EXPUNGE"
+ imap.idle_done
+ end
+ end
+ assert_equal(3, responses.length)
+ assert_instance_of(Net::IMAP::ContinuationRequest, responses[0])
+ assert_equal("EXISTS", responses[1].name)
+ assert_equal(3, responses[1].data)
+ assert_equal("EXPUNGE", responses[2].name)
+ assert_equal(2, responses[2].data)
+ assert_equal(2, requests.length)
+ assert_equal("RUBY0001 IDLE\r\n", requests[0])
+ assert_equal("DONE\r\n", requests[1])
+ imap.logout
+ ensure
+ imap.disconnect if imap
+ end
+ ensure
+ server.close
+ end
+ end
+
private
def imaps_test