diff --git a/lib/net/imap/response_data.rb b/lib/net/imap/response_data.rb index b68736d0..c1049c7c 100644 --- a/lib/net/imap/response_data.rb +++ b/lib/net/imap/response_data.rb @@ -870,37 +870,9 @@ class ThreadMember < Struct.new(:seqno, :children) # children of this in the thread. end - # Net::IMAP::BodyTypeBasic represents basic body structures of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name as defined in [MIME-IMB]. - # - # subtype:: Returns the content subtype name as defined in [MIME-IMB]. - # - # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. - # - # content_id:: Returns a string giving the content id as defined in [MIME-IMB]. - # - # description:: Returns a string giving the content description as defined in - # [MIME-IMB]. - # - # encoding:: Returns a string giving the content transfer encoding as defined in - # [MIME-IMB]. - # - # size:: Returns a number giving the size of the body in octets. - # - # md5:: Returns a string giving the body MD5 value as defined in [MD5]. - # - # disposition:: Returns a Net::IMAP::ContentDisposition object giving - # the content disposition. - # - # language:: Returns a string or an array of strings giving the body - # language value as defined in [LANGUAGE-TAGS]. - # - # extension:: Returns extension data. - # - # multipart?:: Returns false. + # Net::IMAP::BodyTypeBasic represents basic body structures of messages and + # message parts, unless they have a Content-Type that is handled by + # BodyTypeText, BodyTypeMessage, or BodyTypeMultipart. # # See {[IMAP4rev1] §7.4.2}[https://www.rfc-editor.org/rfc/rfc3501.html#section-7.4.2] # and {[IMAP4rev2] §7.5.2}[https://www.rfc-editor.org/rfc/rfc9051.html#section-7.5.2-4.9] @@ -912,26 +884,133 @@ class BodyTypeBasic < Struct.new(:media_type, :subtype, :description, :encoding, :size, :md5, :disposition, :language, :extension) + + ## + # method: media_type + # :call-seq: media_type -> string + # + # The top-level media type as defined in + # [MIME-IMB[https://tools.ietf.org/html/rfc2045]]. + + ## + # method: subtype + # :call-seq: subtype -> string + # + # The media subtype name as defined in + # [MIME-IMB[https://tools.ietf.org/html/rfc2045]]. + + ## + # method: param + # :call-seq: param -> string + # + # Returns a hash that represents parameters as defined in + # [MIME-IMB[https://tools.ietf.org/html/rfc2045]]. + + ## + # method: content_id + # :call-seq: content_id -> string + # + # Returns a string giving the content id as defined + # in [MIME-IMB[https://tools.ietf.org/html/rfc2045]] + # {§7}[https://tools.ietf.org/html/rfc2045#section-7]. + + ## + # method: description + # :call-seq: description -> string + # + # Returns a string giving the content description as defined + # in [MIME-IMB[https://tools.ietf.org/html/rfc2045]] + # {§8}[https://tools.ietf.org/html/rfc2045#section-8]. + + ## + # method: encoding + # :call-seq: encoding -> string + # + # Returns a string giving the content transfer encoding as defined + # in [MIME-IMB[https://tools.ietf.org/html/rfc2045]] + # {§6}[https://tools.ietf.org/html/rfc2045#section-6]. + + ## + # method: size + # :call-seq: size -> integer + # + # Returns a number giving the size of the body in octets. + + ## + # method: md5 + # :call-seq: md5 -> string + # + # Returns a string giving the body MD5 value as defined in + # [MD5[https://tools.ietf.org/html/rfc1864]]. + + ## + # method: disposition + # :call-seq: disposition -> ContentDisposition + # + # Returns a ContentDisposition object giving the content + # disposition, as defined by + # [DISPOSITION[https://tools.ietf.org/html/rfc2183]]. + + ## + # method: language + # :call-seq: language -> string + # + # Returns a string or an array of strings giving the body + # language value as defined in + # [LANGUAGE-TAGS[https://www.rfc-editor.org/info/rfc3282]]. + + #-- + ## + # method: location + # :call-seq: location -> string + # + # A string list giving the body content URI as defined in + # [LOCATION[https://www.rfc-editor.org/info/rfc2557]]. + #++ + + ## + # method: extension + # :call-seq: extension -> string + # + # Returns extension data. The +BODYSTRUCTURE+ fetch attribute + # contains extension data, but +BODY+ does not. + + ## + # :call-seq: multipart? -> false + # + # BodyTypeBasic is not used for multipart MIME parts. def multipart? return false end - # Obsolete: use +subtype+ instead. Calling this will - # generate a warning message to +stderr+, then return - # the value of +subtype+. + # :call-seq: media_subtype -> subtype + # + # >>> + # [Obsolete] + # Use +subtype+ instead. Calling this will generate a warning message + # to +stderr+, then return the value of +subtype+. + #-- + # TODO: why not just keep this as an alias? Would "media_subtype" be used + # for something else? + #++ def media_subtype warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1) return subtype end end - # Net::IMAP::BodyTypeText represents TEXT body structures of messages. + # Net::IMAP::BodyTypeText represents the body structures of messages and + # message parts, when Content-Type is text/*. # - # ==== Fields: - # - # lines:: Returns the size of the body in text lines. - # - # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic. + # BodyTypeText contains all of the fields of BodyTypeBasic. See + # BodyTypeBasic for documentation of the following: + # * {media_type}[rdoc-ref:BodyTypeBasic#media_type] + # * subtype[rdoc-ref:BodyTypeBasic#subtype] + # * param[rdoc-ref:BodyTypeBasic#param] + # * {content_id}[rdoc-ref:BodyTypeBasic#content_id] + # * description[rdoc-ref:BodyTypeBasic#description] + # * encoding[rdoc-ref:BodyTypeBasic#encoding] + # * size[rdoc-ref:BodyTypeBasic#size] # class BodyTypeText < Struct.new(:media_type, :subtype, :param, :content_id, @@ -939,6 +1018,17 @@ class BodyTypeText < Struct.new(:media_type, :subtype, :lines, :md5, :disposition, :language, :extension) + + ## + # method: lines + # :call-seq: lines -> Integer + # + # Returns the size of the body in text lines. + + ## + # :call-seq: multipart? -> false + # + # BodyTypeText is not used for multipart MIME parts. def multipart? return false end @@ -952,15 +1042,19 @@ def media_subtype end end - # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages. + # Net::IMAP::BodyTypeMessage represents the body structures of messages and + # message parts, when Content-Type is message/rfc822 or + # message/global. # - # ==== Fields: - # - # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure. - # - # body:: Returns an object giving the body structure. - # - # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText. + # BodyTypeMessage contains all of the fields of BodyTypeBasic. See + # BodyTypeBasic for documentation of the following fields: + # * {media_type}[rdoc-ref:BodyTypeBasic#media_type] + # * subtype[rdoc-ref:BodyTypeBasic#subtype] + # * param[rdoc-ref:BodyTypeBasic#param] + # * {content_id}[rdoc-ref:BodyTypeBasic#content_id] + # * description[rdoc-ref:BodyTypeBasic#description] + # * encoding[rdoc-ref:BodyTypeBasic#encoding] + # * size[rdoc-ref:BodyTypeBasic#size] # class BodyTypeMessage < Struct.new(:media_type, :subtype, :param, :content_id, @@ -968,6 +1062,23 @@ class BodyTypeMessage < Struct.new(:media_type, :subtype, :envelope, :body, :lines, :md5, :disposition, :language, :extension) + + ## + # method: envelope + # :call-seq: envelope -> Envelope + # + # Returns a Net::IMAP::Envelope giving the envelope structure. + + ## + # method: body + # :call-seq: body -> BodyStructure + # + # Returns a Net::IMAP::BodyStructure for the message's body structure. + + ## + # :call-seq: multipart? -> false + # + # BodyTypeMessage is not used for multipart MIME parts. def multipart? return false end @@ -981,57 +1092,134 @@ def media_subtype end end - # Net::IMAP::BodyTypeAttachment represents attachment body structures - # of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name. - # - # subtype:: Returns +nil+. - # - # param:: Returns a hash that represents parameters. - # - # multipart?:: Returns false. - # - class BodyTypeAttachment < Struct.new(:media_type, :subtype, - :param) + # === WARNING + # BodyTypeAttachment represents a body-fld-dsp that is + # incorrectly in a position where the IMAP4rev1 grammar expects a nested + # +body+ structure. + # + # >>> + # \IMAP body structures are parenthesized lists and assign their fields + # positionally, so missing fields change the intepretation of all + # following fields. Buggy \IMAP servers sometimes leave fields missing + # rather than empty, which inevitably confuses parsers. + # BodyTypeAttachment was an attempt to parse a common type of buggy body + # structure without crashing. + # + # Currently, when Net::IMAP::ResponseParser sees "attachment" as the first + # entry in a body-type-1part, which is where the MIME type should + # be, it uses BodyTypeAttachment to capture the rest. "attachment" is not + # a valid MIME type, but _is_ a common Content-Disposition. What + # might have happened was that buggy server could not parse the message + # (which might have been incorrectly formatted) and output a + # body-type-dsp where a Net::IMAP::ResponseParser expected to see + # a +body+. + # + # A future release will replace this, probably with a ContentDisposition + # nested inside another body structure object, maybe BodyTypeBasic, or + # perhaps a new body structure class that represents any unparsable body + # structure. + # + class BodyTypeAttachment < Struct.new(:dsp_type, :_unused_, :param) + + # *invalid for BodyTypeAttachment* + def media_type + warn(<<~WARN, uplevel: 1) + BodyTypeAttachment#media_type is obsolete. Use dsp_type instead. + WARN + dsp_type + end + + # *invalid for BodyTypeAttachment* + def subtype + warn("BodyTypeAttachment#subtype is obsolete.\n", uplevel: 1) + nil + end + + ## + # method: dsp_type + # :call-seq: dsp_type -> string + # + # Returns the content disposition type, as defined by + # [DISPOSITION[https://tools.ietf.org/html/rfc2183]]. + + ## + # method: param + # :call-seq: param -> hash + # + # Returns a hash representing parameters of the Content-Disposition + # field, as defined by [DISPOSITION[https://tools.ietf.org/html/rfc2183]]. + + ## def multipart? return false end end - # Net::IMAP::BodyTypeMultipart represents multipart body structures - # of messages. - # - # ==== Fields: - # - # media_type:: Returns the content media type name as defined in [MIME-IMB]. - # - # subtype:: Returns the content subtype name as defined in [MIME-IMB]. - # - # parts:: Returns multiple parts. - # - # param:: Returns a hash that represents parameters as defined in [MIME-IMB]. - # - # disposition:: Returns a Net::IMAP::ContentDisposition object giving - # the content disposition. - # - # language:: Returns a string or an array of strings giving the body - # language value as defined in [LANGUAGE-TAGS]. - # - # extension:: Returns extension data. - # - # multipart?:: Returns true. - # + # Net::IMAP::BodyTypeMultipart represents body structures of messages and + # message parts, when Content-Type is multipart/*. class BodyTypeMultipart < Struct.new(:media_type, :subtype, :parts, :param, :disposition, :language, :extension) + + ## + # method: media_type + # call-seq: media_type -> "multipart" + # + # BodyTypeMultipart is only used with multipart/* media types. + + ## + # method: subtype + # call-seq: subtype -> string + # + # Returns the content subtype name + # as defined in [MIME-IMB[https://tools.ietf.org/html/rfc2045]]. + + ## + # method: parts + # call-seq: parts -> array of BodyStructure objects + # + # Returns an array with a BodyStructure object for each part contained in + # this part. + + ## + # method: param + # call-seq: param -> hash + # + # Returns a hash that represents parameters + # as defined in [MIME-IMB[https://tools.ietf.org/html/rfc2045]]. + + ## + # method: disposition + # call-seq: disposition -> ContentDisposition + # + # Returns a Net::IMAP::ContentDisposition object giving the content + # disposition. + + ## + # method: language + # :call-seq: language -> string + # + # Returns a string or an array of strings giving the body + # language value as defined in + # [LANGUAGE-TAGS[https://www.rfc-editor.org/info/rfc3282]]. + + ## + # method: extension + # call-seq: extension -> array + # + # Returns extension data as an array of numbers strings, and nested + # arrays (of numbers, strings, etc). + + ## + # :call-seq: multipart? -> true + # + # BodyTypeMultipart is used for multipart MIME parts. def multipart? return true end + ## # Obsolete: use +subtype+ instead. Calling this will # generate a warning message to +stderr+, then return # the value of +subtype+. @@ -1041,6 +1229,14 @@ def media_subtype end end + # === WARNING: + # >>> + # BodyTypeExtension is (incorrectly) used for message/* parts + # (besides message/rfc822, which correctly uses BodyTypeMessage). + # + # A future release will replace this class with: + # * BodyTypeMessage for message/rfc822 and message/global + # * BodyTypeBasic for any other message/* class BodyTypeExtension < Struct.new(:media_type, :subtype, :params, :content_id, :description, :encoding, :size)