2005-01-21 03:15:56 -05:00
|
|
|
require "net/imap"
|
|
|
|
require "test/unit"
|
|
|
|
|
|
|
|
class IMAPTest < Test::Unit::TestCase
|
2007-12-22 10:50:43 -05:00
|
|
|
CA_FILE = File.expand_path("cacert.pem", File.dirname(__FILE__))
|
|
|
|
SERVER_KEY = File.expand_path("server.key", File.dirname(__FILE__))
|
|
|
|
SERVER_CERT = File.expand_path("server.crt", File.dirname(__FILE__))
|
|
|
|
|
2010-05-08 20:16:48 -04:00
|
|
|
SERVER_ADDR = "127.0.0.1"
|
|
|
|
|
2009-07-24 05:09:04 -04:00
|
|
|
def setup
|
|
|
|
@do_not_reverse_lookup = Socket.do_not_reverse_lookup
|
|
|
|
Socket.do_not_reverse_lookup = true
|
|
|
|
end
|
|
|
|
|
|
|
|
def teardown
|
|
|
|
Socket.do_not_reverse_lookup = @do_not_reverse_lookup
|
|
|
|
end
|
|
|
|
|
2005-01-21 03:15:56 -05:00
|
|
|
def test_encode_utf7
|
2007-12-22 03:00:04 -05:00
|
|
|
utf8 = "\357\274\241\357\274\242\357\274\243".force_encoding("UTF-8")
|
|
|
|
s = Net::IMAP.encode_utf7(utf8)
|
|
|
|
assert_equal("&,yH,Iv8j-".force_encoding("UTF-8"), s)
|
2010-04-14 00:00:09 -04:00
|
|
|
|
|
|
|
utf8 = "\343\201\202&".force_encoding("UTF-8")
|
|
|
|
s = Net::IMAP.encode_utf7(utf8)
|
|
|
|
assert_equal("&MEI-&-".force_encoding("UTF-8"), s)
|
2005-01-21 03:15:56 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_decode_utf7
|
|
|
|
s = Net::IMAP.decode_utf7("&,yH,Iv8j-")
|
2007-12-22 03:00:04 -05:00
|
|
|
utf8 = "\357\274\241\357\274\242\357\274\243".force_encoding("UTF-8")
|
|
|
|
assert_equal(utf8, s)
|
2005-01-21 03:15:56 -05:00
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
|
2009-07-23 11:20:47 -04:00
|
|
|
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
|
|
|
|
|
2007-12-22 10:50:43 -05:00
|
|
|
def test_imaps_unknown_ca
|
2007-12-30 15:58:31 -05:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
assert_raise(OpenSSL::SSL::SSLError) do
|
|
|
|
imaps_test do |port|
|
|
|
|
Net::IMAP.new("localhost",
|
|
|
|
:port => port,
|
|
|
|
:ssl => true)
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_imaps_with_ca_file
|
2007-12-30 15:58:31 -05:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
assert_nothing_raised do
|
|
|
|
imaps_test do |port|
|
|
|
|
Net::IMAP.new("localhost",
|
|
|
|
:port => port,
|
|
|
|
:ssl => { :ca_file => CA_FILE })
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_imaps_verify_none
|
2007-12-30 15:58:31 -05:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
assert_nothing_raised do
|
|
|
|
imaps_test do |port|
|
|
|
|
Net::IMAP.new("localhost",
|
|
|
|
:port => port,
|
|
|
|
:ssl => { :verify_mode => OpenSSL::SSL::VERIFY_NONE })
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_imaps_post_connection_check
|
2007-12-30 15:58:31 -05:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
assert_raise(OpenSSL::SSL::SSLError) do
|
|
|
|
imaps_test do |port|
|
2010-05-08 20:16:48 -04:00
|
|
|
# SERVER_ADDR is different from the hostname in the certificate,
|
|
|
|
# so the following code should raise a SSLError.
|
|
|
|
Net::IMAP.new(SERVER_ADDR,
|
2007-12-30 15:58:31 -05:00
|
|
|
:port => port,
|
|
|
|
:ssl => { :ca_file => CA_FILE })
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_starttls
|
2008-05-05 13:18:09 -04:00
|
|
|
imap = nil
|
2007-12-30 15:58:31 -05:00
|
|
|
if defined?(OpenSSL)
|
|
|
|
starttls_test do |port|
|
|
|
|
imap = Net::IMAP.new("localhost", :port => port)
|
|
|
|
imap.starttls(:ca_file => CA_FILE)
|
|
|
|
imap
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
2008-05-05 13:18:09 -04:00
|
|
|
ensure
|
|
|
|
if imap && !imap.disconnected?
|
|
|
|
imap.disconnect
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
end
|
|
|
|
|
2008-05-21 13:47:33 -04:00
|
|
|
def test_unexpected_eof
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2008-05-21 13:47:33 -04:00
|
|
|
port = server.addr[1]
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = server.accept
|
|
|
|
begin
|
|
|
|
sock.print("* OK test server\r\n")
|
|
|
|
sock.gets
|
|
|
|
# sock.print("* BYE terminating connection\r\n")
|
|
|
|
# sock.print("RUBY0001 OK LOGOUT completed\r\n")
|
|
|
|
ensure
|
|
|
|
sock.close
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
imap = Net::IMAP.new("localhost", :port => port)
|
|
|
|
assert_raise(EOFError) do
|
|
|
|
imap.logout
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
imap.disconnect if imap
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
server.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2009-07-23 11:20:47 -04:00
|
|
|
def test_idle
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2009-07-23 11:20:47 -04:00
|
|
|
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
|
|
|
|
|
2009-07-24 05:09:04 -04:00
|
|
|
def test_exception_during_idle
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2009-07-24 05:09:04 -04:00
|
|
|
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)
|
|
|
|
begin
|
|
|
|
th = Thread.current
|
|
|
|
m = Monitor.new
|
2010-02-06 07:31:59 -05:00
|
|
|
in_idle = false
|
|
|
|
exception_raised = false
|
2009-07-24 05:09:04 -04:00
|
|
|
c = m.new_cond
|
|
|
|
Thread.start do
|
|
|
|
m.synchronize do
|
2010-02-06 07:31:59 -05:00
|
|
|
until in_idle
|
|
|
|
c.wait(0.1)
|
|
|
|
end
|
2009-07-24 05:09:04 -04:00
|
|
|
end
|
|
|
|
th.raise(Interrupt)
|
2010-02-06 07:31:59 -05:00
|
|
|
exception_raised = true
|
2009-07-24 05:09:04 -04:00
|
|
|
end
|
|
|
|
imap.idle do |res|
|
|
|
|
m.synchronize do
|
2010-02-06 07:31:59 -05:00
|
|
|
in_idle = true
|
2009-07-24 05:09:04 -04:00
|
|
|
c.signal
|
2010-02-06 07:31:59 -05:00
|
|
|
until exception_raised
|
|
|
|
c.wait(0.1)
|
|
|
|
end
|
2009-07-24 05:09:04 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
rescue Interrupt
|
|
|
|
end
|
|
|
|
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
|
|
|
|
|
|
|
|
def test_idle_done_not_during_idle
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2009-07-24 05:09:04 -04:00
|
|
|
port = server.addr[1]
|
|
|
|
requests = []
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = server.accept
|
|
|
|
begin
|
|
|
|
sock.print("* OK test server\r\n")
|
|
|
|
ensure
|
|
|
|
sock.close
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
imap = Net::IMAP.new("localhost", :port => port)
|
|
|
|
assert_raise(Net::IMAP::Error) do
|
|
|
|
imap.idle_done
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
imap.disconnect if imap
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
server.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-02-06 08:57:10 -05:00
|
|
|
def test_unexpected_bye
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2010-02-06 08:57:10 -05:00
|
|
|
port = server.addr[1]
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = server.accept
|
|
|
|
begin
|
|
|
|
sock.print("* OK Gimap ready for requests from 75.101.246.151 33if2752585qyk.26\r\n")
|
|
|
|
sock.gets
|
|
|
|
sock.print("* BYE System Error 33if2752585qyk.26\r\n")
|
|
|
|
ensure
|
|
|
|
sock.close
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
imap = Net::IMAP.new("localhost", :port => port)
|
|
|
|
assert_raise(Net::IMAP::ByeResponseError) do
|
|
|
|
imap.login("user", "password")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
server.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-05-08 19:25:54 -04:00
|
|
|
def test_exception_during_shutdown
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2010-05-08 19:25:54 -04:00
|
|
|
port = server.addr[1]
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = server.accept
|
|
|
|
begin
|
|
|
|
sock.print("* OK test server\r\n")
|
|
|
|
sock.gets
|
|
|
|
sock.print("* BYE terminating connection\r\n")
|
|
|
|
sock.print("RUBY0001 OK LOGOUT completed\r\n")
|
|
|
|
ensure
|
|
|
|
sock.close
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
begin
|
|
|
|
begin
|
|
|
|
imap = Net::IMAP.new("localhost", :port => port)
|
|
|
|
imap.instance_eval do
|
|
|
|
def @sock.shutdown(*args)
|
|
|
|
super
|
|
|
|
raise "error"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
imap.logout
|
|
|
|
ensure
|
|
|
|
assert_raise(RuntimeError) do
|
|
|
|
imap.disconnect
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ensure
|
|
|
|
server.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2007-12-22 10:50:43 -05:00
|
|
|
private
|
|
|
|
|
|
|
|
def imaps_test
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2007-12-22 10:50:43 -05:00
|
|
|
port = server.addr[1]
|
|
|
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
|
|
ctx.ca_file = CA_FILE
|
|
|
|
ctx.key = File.open(SERVER_KEY) { |f|
|
|
|
|
OpenSSL::PKey::RSA.new(f)
|
|
|
|
}
|
|
|
|
ctx.cert = File.open(SERVER_CERT) { |f|
|
|
|
|
OpenSSL::X509::Certificate.new(f)
|
|
|
|
}
|
|
|
|
ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx)
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = ssl_server.accept
|
|
|
|
begin
|
|
|
|
sock.print("* OK test server\r\n")
|
|
|
|
sock.gets
|
|
|
|
sock.print("* BYE terminating connection\r\n")
|
|
|
|
sock.print("RUBY0001 OK LOGOUT completed\r\n")
|
|
|
|
ensure
|
|
|
|
sock.close
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
begin
|
2008-05-05 13:18:09 -04:00
|
|
|
begin
|
|
|
|
imap = yield(port)
|
|
|
|
imap.logout
|
|
|
|
ensure
|
|
|
|
imap.disconnect if imap
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
ensure
|
|
|
|
ssl_server.close
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def starttls_test
|
2010-05-08 20:16:48 -04:00
|
|
|
server = create_tcp_server
|
2007-12-22 10:50:43 -05:00
|
|
|
port = server.addr[1]
|
|
|
|
Thread.start do
|
|
|
|
begin
|
|
|
|
sock = server.accept
|
|
|
|
sock.print("* OK test server\r\n")
|
|
|
|
sock.gets
|
|
|
|
sock.print("RUBY0001 OK completed\r\n")
|
|
|
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
|
|
ctx.ca_file = CA_FILE
|
|
|
|
ctx.key = File.open(SERVER_KEY) { |f|
|
|
|
|
OpenSSL::PKey::RSA.new(f)
|
|
|
|
}
|
|
|
|
ctx.cert = File.open(SERVER_CERT) { |f|
|
|
|
|
OpenSSL::X509::Certificate.new(f)
|
|
|
|
}
|
|
|
|
sock = OpenSSL::SSL::SSLSocket.new(sock, ctx)
|
|
|
|
begin
|
|
|
|
sock.accept
|
|
|
|
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
|
2008-05-05 13:18:09 -04:00
|
|
|
begin
|
|
|
|
imap = yield(port)
|
|
|
|
imap.logout
|
|
|
|
ensure
|
|
|
|
imap.disconnect if imap
|
|
|
|
end
|
2007-12-22 10:50:43 -05:00
|
|
|
ensure
|
|
|
|
server.close
|
|
|
|
end
|
|
|
|
end
|
2010-05-08 20:16:48 -04:00
|
|
|
|
|
|
|
def create_tcp_server
|
|
|
|
return TCPServer.new(SERVER_ADDR, 0)
|
|
|
|
end
|
2005-01-21 03:15:56 -05:00
|
|
|
end
|