summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <[email protected]>2021-04-22 14:35:52 +0900
committerHiroshi SHIBATA <[email protected]>2021-04-22 14:37:45 +0900
commit674760316ce5b68aa182c1b3b25665de250341b3 ()
tree3d0ee5c236607d926e5b169d1d291a620ea9b16d
parent01f131457ffac39f018b342fbd5f7598171d10fa (diff)
Merge net-imap-0.2.0
-rw-r--r--lib/net/imap.rb524
-rw-r--r--test/net/imap/test_imap.rb69
-rw-r--r--test/net/imap/test_imap_response_parser.rb78
3 files changed, 593 insertions, 78 deletions
@@ -201,7 +201,7 @@ module Net
# Unicode", RFC 2152, May 1997.
#
class IMAP < Protocol
- VERSION = "0.1.1"
include MonitorMixin
if defined?(OpenSSL::SSL)
@@ -304,6 +304,16 @@ module Net
@@authenticators[auth_type] = authenticator
end
# The default port for IMAP connections, port 143
def self.default_port
return PORT
@@ -365,6 +375,30 @@ module Net
end
end
# Sends a NOOP command to the server. It does nothing.
def noop
send_command("NOOP")
@@ -408,7 +442,7 @@ module Net
# the form "AUTH=LOGIN" or "AUTH=CRAM-MD5".
#
# Authentication is done using the appropriate authenticator object:
- # see @@authenticators for more information on plugging in your own
# authenticator.
#
# For example:
@@ -417,12 +451,7 @@ module Net
#
# A Net::IMAP::NoResponseError is raised if authentication fails.
def authenticate(auth_type, *args)
- auth_type = auth_type.upcase
- unless @@authenticators.has_key?(auth_type)
- raise ArgumentError,
- format('unknown auth type - "%s"', auth_type)
- end
- authenticator = @@authenticators[auth_type].new(*args)
send_command("AUTHENTICATE", auth_type) do |resp|
if resp.instance_of?(ContinuationRequest)
data = authenticator.process(resp.data.text.unpack("m")[0])
@@ -552,6 +581,60 @@ module Net
end
end
# Sends a XLIST command, and returns a subset of names from
# the complete set of all names available to the client.
# +refname+ provides a context (for instance, a base directory
@@ -1656,6 +1739,74 @@ module Net
end
end
# Common validators of number and nz_number types
module NumValidator # :nodoc
class << self
@@ -1747,6 +1898,18 @@ module Net
# raw_data:: Returns the raw data string.
UntaggedResponse = Struct.new(:name, :data, :raw_data)
# Net::IMAP::TaggedResponse represents tagged responses.
#
# The server completion result response indicates the success or
@@ -1774,8 +1937,7 @@ module Net
# Net::IMAP::ResponseText represents texts of responses.
# The text may be prefixed by the response code.
#
- # resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
- # ;; text SHOULD NOT begin with "[" or "="
#
# ==== Fields:
#
@@ -1787,12 +1949,15 @@ module Net
# Net::IMAP::ResponseCode represents response codes.
#
- # resp_text_code ::= "ALERT" / "PARSE" /
- # "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
# "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
- # "UIDVALIDITY" SPACE nz_number /
- # "UNSEEN" SPACE nz_number /
- # atom [SPACE 1*<any TEXT_CHAR except "]">]
#
# ==== Fields:
#
@@ -1872,6 +2037,39 @@ module Net
#
MailboxACLItem = Struct.new(:user, :rights, :mailbox)
# Net::IMAP::StatusData represents the contents of the STATUS response.
#
# ==== Fields:
@@ -2291,8 +2489,12 @@ module Net
return response_cond
when /\A(?:FLAGS)\z/ni
return flags_response
when /\A(?:LIST|LSUB|XLIST)\z/ni
return list_response
when /\A(?:QUOTA)\z/ni
return getquota_response
when /\A(?:QUOTAROOT)\z/ni
@@ -2307,6 +2509,8 @@ module Net
return status_response
when /\A(?:CAPABILITY)\z/ni
return capability_response
else
return text_response
end
@@ -2316,7 +2520,7 @@ module Net
end
def response_tagged
- tag = atom
match(T_SPACE)
token = match(T_ATOM)
name = token.value.upcase
@@ -2876,14 +3080,18 @@ module Net
return name, modseq
end
def text_response
token = match(T_ATOM)
name = token.value.upcase
match(T_SPACE)
- @lex_state = EXPR_TEXT
- token = match(T_TEXT)
- @lex_state = EXPR_BEG
- return UntaggedResponse.new(name, token.value)
end
def flags_response
@@ -3114,11 +3322,15 @@ module Net
token = match(T_ATOM)
name = token.value.upcase
match(T_SPACE)
data = []
while true
token = lookahead
case token.symbol
- when T_CRLF
break
when T_SPACE
shift_token
@@ -3126,30 +3338,142 @@ module Net
end
data.push(atom.upcase)
end
return UntaggedResponse.new(name, data, @str)
end
- def resp_text
- @lex_state = EXPR_RTEXT
token = lookahead
- if token.symbol == T_LBRA
- code = resp_text_code
else
- code = nil
end
- token = match(T_TEXT)
- @lex_state = EXPR_BEG
- return ResponseText.new(code, token.value)
end
def resp_text_code
- @lex_state = EXPR_BEG
- match(T_LBRA)
token = match(T_ATOM)
name = token.value.upcase
case name
when /\A(?:ALERT|PARSE|READ-ONLY|READ-WRITE|TRYCREATE|NOMODSEQ)\z/n
result = ResponseCode.new(name, nil)
when /\A(?:PERMANENTFLAGS)\z/n
match(T_SPACE)
result = ResponseCode.new(name, flag_list)
@@ -3160,19 +3484,28 @@ module Net
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
return result
end
def address_list
token = lookahead
if token.symbol == T_NIL
@@ -3269,7 +3602,7 @@ module Net
if string_token?(token)
return string
else
- return atom
end
end
@@ -3299,34 +3632,49 @@ module Net
return token.value.upcase
end
- def atom
- result = String.new
- while true
- token = lookahead
- if atom_token?(token)
- result.concat(token.value)
- shift_token
- else
- if result.empty?
- parse_error("unexpected token %s", token.symbol)
- else
- return result
- end
- end
- end
- end
-
ATOM_TOKENS = [
T_ATOM,
T_NUMBER,
T_NIL,
T_LBRA,
- T_RBRA,
T_PLUS
]
- def atom_token?(token)
- return ATOM_TOKENS.include?(token.symbol)
end
def number
@@ -3344,22 +3692,62 @@ module Net
return nil
end
- def match(*args)
token = lookahead
- unless args.include?(token.symbol)
- parse_error('unexpected token %s (expected %s)',
- token.symbol.id2name,
- args.collect {|i| i.id2name}.join(" or "))
end
- shift_token
- return token
end
def lookahead
- unless @token
- @token = next_token
- end
- return @token
end
def shift_token
@@ -578,23 +578,23 @@ class IMAPTest < Test::Unit::TestCase
begin
imap = Net::IMAP.new(server_addr, :port => port)
assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", -1)
end
- imap.send(:send_command, "TEST", 0)
- imap.send(:send_command, "TEST", 4294967295)
assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", 4294967296)
end
assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(-1))
end
assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(0))
end
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(1))
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967295))
assert_raise(Net::IMAP::DataFormatError) do
- imap.send(:send_command, "TEST", Net::IMAP::MessageSet.new(4294967296))
end
imap.logout
ensure
@@ -628,7 +628,7 @@ class IMAPTest < Test::Unit::TestCase
end
begin
imap = Net::IMAP.new(server_addr, :port => port)
- imap.send(:send_command, "TEST", ["\xDE\xAD\xBE\xEF".b])
assert_equal(2, requests.length)
assert_equal("RUBY0001 TEST ({4}\r\n", requests[0])
assert_equal("\xDE\xAD\xBE\xEF".b, literal)
@@ -753,6 +753,55 @@ EOF
end
end
private
def imaps_test
@@ -234,6 +234,27 @@ EOF
response = parser.parse("* CAPABILITY st11p00mm-iscream009 1Q49 XAPPLEPUSHSERVICE IMAP4 IMAP4rev1 SASL-IR AUTH=ATOKEN AUTH=PLAIN \r\n")
assert_equal("CAPABILITY", response.name)
assert_equal("AUTH=PLAIN", response.data.last)
end
def test_mixed_boundary
@@ -301,6 +322,22 @@ EOF
assert_equal(12345, response.data.attr["MODSEQ"])
end
def test_continuation_request_without_response_text
parser = Net::IMAP::ResponseParser.new
response = parser.parse("+\r\n")
@@ -308,4 +345,45 @@ EOF
assert_equal(nil, response.data.code)
assert_equal("", response.data.text)
end
end