1require 'net/pop' 2require 'test/unit' 3require 'digest/md5' 4 5class TestPOP < Test::Unit::TestCase 6 def setup 7 @users = {'user' => 'pass' } 8 @ok_user = 'user' 9 @stamp_base = "#{$$}.#{Time.now.to_i}@localhost" 10 end 11 12 def test_pop_auth_ok 13 pop_test(false) do |pop| 14 assert_instance_of Net::POP3, pop 15 assert_nothing_raised do 16 pop.start(@ok_user, @users[@ok_user]) 17 end 18 end 19 end 20 21 def test_pop_auth_ng 22 pop_test(false) do |pop| 23 assert_instance_of Net::POP3, pop 24 assert_raise Net::POPAuthenticationError do 25 pop.start(@ok_user, 'bad password') 26 end 27 end 28 end 29 30 def test_apop_ok 31 pop_test(@stamp_base) do |pop| 32 assert_instance_of Net::APOP, pop 33 assert_nothing_raised do 34 pop.start(@ok_user, @users[@ok_user]) 35 end 36 end 37 end 38 39 def test_apop_ng 40 pop_test(@stamp_base) do |pop| 41 assert_instance_of Net::APOP, pop 42 assert_raise Net::POPAuthenticationError do 43 pop.start(@ok_user, 'bad password') 44 end 45 end 46 end 47 48 def test_apop_invalid 49 pop_test("\x80"+@stamp_base) do |pop| 50 assert_instance_of Net::APOP, pop 51 assert_raise Net::POPAuthenticationError do 52 pop.start(@ok_user, @users[@ok_user]) 53 end 54 end 55 end 56 57 def test_apop_invalid_at 58 pop_test(@stamp_base.sub('@', '.')) do |pop| 59 assert_instance_of Net::APOP, pop 60 e = assert_raise Net::POPAuthenticationError do 61 pop.start(@ok_user, @users[@ok_user]) 62 end 63 end 64 end 65 66 def pop_test(apop=false) 67 host = 'localhost' 68 server = TCPServer.new(host, 0) 69 port = server.addr[1] 70 thread = Thread.start do 71 sock = server.accept 72 begin 73 pop_server_loop(sock, apop) 74 ensure 75 sock.close 76 end 77 end 78 begin 79 pop = Net::POP3::APOP(apop).new(host, port) 80 #pop.set_debug_output $stderr 81 yield pop 82 ensure 83 begin 84 pop.finish 85 rescue IOError 86 raise unless $!.message == "POP session not yet started" 87 end 88 end 89 ensure 90 server.close 91 thread.value 92 end 93 94 def pop_server_loop(sock, apop) 95 if apop 96 sock.print "+OK ready <#{apop}>\r\n" 97 else 98 sock.print "+OK ready\r\n" 99 end 100 user = nil 101 while line = sock.gets 102 case line 103 when /^USER (.+)\r\n/ 104 user = $1 105 if @users.key?(user) 106 sock.print "+OK\r\n" 107 else 108 sock.print "-ERR unknown user\r\n" 109 end 110 when /^PASS (.+)\r\n/ 111 if @users[user] == $1 112 sock.print "+OK\r\n" 113 else 114 sock.print "-ERR invalid password\r\n" 115 end 116 when /^APOP (.+) (.+)\r\n/ 117 user = $1 118 if apop && Digest::MD5.hexdigest("<#{apop}>#{@users[user]}") == $2 119 sock.print "+OK\r\n" 120 else 121 sock.print "-ERR authentication failed\r\n" 122 end 123 when /^QUIT/ 124 sock.print "+OK bye\r\n" 125 return 126 else 127 sock.print "-ERR command not recognized\r\n" 128 return 129 end 130 end 131 end 132end 133