diff --git a/lib/net/imap.rb b/lib/net/imap.rb index 02731bbe1..ec3c2479f 100644 --- a/lib/net/imap.rb +++ b/lib/net/imap.rb @@ -1949,12 +1949,15 @@ def ensure_mod_sequence_value(num) # Net::IMAP::ResponseCode represents response codes. # - # resp_text_code ::= "ALERT" / "PARSE" / - # "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" / + # resp_text_code ::= "ALERT" / + # "BADCHARSET" [SP "(" astring *(SP astring) ")" ] / + # capability_data / "PARSE" / + # "PERMANENTFLAGS" SP "(" + # [flag_perm *(SP flag_perm)] ")" / # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / - # "UIDVALIDITY" SPACE nz_number / - # "UNSEEN" SPACE nz_number / - # atom [SPACE 1*] + # "UIDNEXT" SP nz_number / "UIDVALIDITY" SP nz_number / + # "UNSEEN" SP nz_number / + # atom [SP 1*] # # ==== Fields: # @@ -3450,12 +3453,25 @@ def resp_text end end + # See https://www.rfc-editor.org/errata/rfc3501 + # + # resp-text-code = "ALERT" / + # "BADCHARSET" [SP "(" charset *(SP charset) ")" ] / + # capability-data / "PARSE" / + # "PERMANENTFLAGS" SP "(" + # [flag-perm *(SP flag-perm)] ")" / + # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" / + # "UIDNEXT" SP nz-number / "UIDVALIDITY" SP nz-number / + # "UNSEEN" SP nz-number / + # atom [SP 1*] def resp_text_code 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(?:BADCHARSET)\z/n + result = ResponseCode.new(name, charset_list) when /\A(?:CAPABILITY)\z/ni result = ResponseCode.new(name, capability_data) when /\A(?:PERMANENTFLAGS)\z/n @@ -3477,6 +3493,19 @@ def resp_text_code return result end + def charset_list + result = [] + if accept(T_SPACE) + match(T_LPAR) + result << charset + while accept(T_SPACE) + result << charset + end + match(T_RPAR) + end + result + end + def address_list token = lookahead if token.symbol == T_NIL @@ -3637,6 +3666,17 @@ def combine_adjacent(*tokens) result end + # See https://www.rfc-editor.org/errata/rfc3501 + # + # charset = atom / quoted + def charset + if token = accept(T_QUOTED) + token.value + else + atom + end + end + def number token = lookahead if token.symbol == T_NIL diff --git a/test/net/imap/test_imap_response_parser.rb b/test/net/imap/test_imap_response_parser.rb index a059c6ce8..5b519edef 100644 --- a/test/net/imap/test_imap_response_parser.rb +++ b/test/net/imap/test_imap_response_parser.rb @@ -330,6 +330,14 @@ def test_msg_rfc3501_response_text_with_T_LBRA assert_equal("[Gmail]/Sent Mail selected. (Success)", response.data.text) end + def test_msg_rfc3501_response_text_with_BADCHARSET_astrings + parser = Net::IMAP::ResponseParser.new + response = parser.parse("t BAD [BADCHARSET (US-ASCII \"[astring with brackets]\")] unsupported charset foo.\r\n") + assert_equal("t", response.tag) + assert_equal("unsupported charset foo.", response.data.text) + assert_equal("BADCHARSET", response.data.code.name) + end + def test_continuation_request_without_response_text parser = Net::IMAP::ResponseParser.new response = parser.parse("+\r\n")