# frozen_string_literal: true
module Net
class IMAP < Protocol
autoload :FetchData, "#{__dir__}/fetch_data"
autoload :SearchResult, "#{__dir__}/search_result"
autoload :SequenceSet, "#{__dir__}/sequence_set"
# Net::IMAP::ContinuationRequest represents command continuation requests.
#
# The command continuation request response is indicated by a "+" token
# instead of a tag. This form of response indicates that the server is
# ready to accept the continuation of a command from the client. The
# remainder of this response is a line of text.
#
class ContinuationRequest < Struct.new(:data, :raw_data)
##
# method: data
# :call-seq: data -> ResponseText
#
# Returns a ResponseText object
##
# method: raw_data
# :call-seq: raw_data -> string
#
# the raw response data
end
# Net::IMAP::UntaggedResponse represents untagged responses.
#
# Data transmitted by the server to the client and status responses
# that do not indicate command completion are prefixed with the token
# "*", and are called untagged responses.
#
class UntaggedResponse < Struct.new(:name, :data, :raw_data)
##
# method: name
# :call-seq: name -> string
#
# The uppercase response name, e.g. "FLAGS", "LIST", "FETCH", etc.
##
# method: data
# :call-seq: data -> object or nil
#
# The parsed response data, e.g: an array of flag symbols, an array of
# capabilities strings, a ResponseText object, a MailboxList object, a
# FetchData object, a Namespaces object, etc. The response #name
# determines what form the data can take.
##
# method: raw_data
# :call-seq: raw_data -> string
#
# The raw response data.
end
# Net::IMAP::IgnoredResponse represents intentionally ignored responses.
#
# This includes untagged response "NOOP" sent by e.g. Zimbra to avoid
# some clients to close the connection.
#
# It matches no IMAP standard.
class IgnoredResponse < UntaggedResponse
end
# **Note:** This represents an intentionally _unstable_ API. Where
# instances of this class are returned, future releases may return a
# different (incompatible) object without deprecation or warning.
#
# Net::IMAP::UnparsedData represents data for unknown response types or
# unknown extensions to response types without a well-defined extension
# grammar.
#
# See also: UnparsedNumericResponseData, ExtensionData, IgnoredResponse
class UnparsedData < Struct.new(:unparsed_data)
##
# method: unparsed_data
# :call-seq: unparsed_data -> string
#
# The unparsed data
end
# **Note:** This represents an intentionally _unstable_ API. Where
# instances of this class are returned, future releases may return a
# different (incompatible) object without deprecation or warning.
#
# Net::IMAP::UnparsedNumericResponseData represents data for unhandled
# response types with a numeric prefix. See the documentation for #number.
#
# See also: UnparsedData, ExtensionData, IgnoredResponse
class UnparsedNumericResponseData < Struct.new(:number, :unparsed_data)
##
# method: number
# :call-seq: number -> integer
#
# Returns a numeric response data prefix, when available.
#
# Many response types are prefixed with a non-negative #number. For
# message data, #number may represent a sequence number or a UID. For
# mailbox data, #number may represent a message count.
##
# method: unparsed_data
# :call-seq: unparsed_data -> string
#
# The unparsed data, not including #number or UntaggedResponse#name.
end
# **Note:** This represents an intentionally _unstable_ API. Where
# instances of this class are returned, future releases may return a
# different (incompatible) object without deprecation or warning.
#
# Net::IMAP::ExtensionData represents data that is parsable according to the
# forward-compatible extension syntax in RFC3501, RFC4466, or RFC9051, but
# isn't directly known or understood by Net::IMAP yet.
#
# See also: UnparsedData, UnparsedNumericResponseData, IgnoredResponse
class ExtensionData < Struct.new(:data)
##
# method: data
# :call-seq: data -> string
#
# The parsed extension data.
end
# Net::IMAP::TaggedResponse represents tagged responses.
#
# The server completion result response indicates the success or
# failure of the operation. It is tagged with the same tag as the
# client command which began the operation.
#
class TaggedResponse < Struct.new(:tag, :name, :data, :raw_data)
##
# method: tag
# :call-seq: tag -> string
#
# Returns the command tag
##
# method: name
# :call-seq: name -> string
#
# Returns the name, one of "OK", "NO", or "BAD".
##
# method: data
# :call-seq: data -> ResponseText
#
# Returns a ResponseText object
##
# method: raw_data
# :call-seq: raw_data -> string
#
# The raw response data.
end
# Net::IMAP::ResponseText represents texts of responses.
#
# The text may be prefixed by a ResponseCode.
#
# ResponseText is returned from TaggedResponse#data, or from
# UntaggedResponse#data when the response type is a "condition" ("OK", "NO",
# "BAD", "PREAUTH", or "BYE").
class ResponseText < Struct.new(:code, :text)
# Used to avoid an allocation when ResponseText is empty
EMPTY = new(nil, "").freeze
##
# method: code
# :call-seq: code -> ResponseCode or nil
#
# Returns a ResponseCode, if the response contains one
##
# method: text
# :call-seq: text -> string
#
# Returns the response text, not including any response code
end
# Net::IMAP::ResponseCode represents response codes. Response codes can be
# retrieved from ResponseText#code and can be included in any "condition"
# response: any TaggedResponse and UntaggedResponse when the response type
# is a "condition" ("OK", "NO", "BAD", "PREAUTH", or "BYE").
#
# Some response codes come with additional data which will be parsed by
# Net::IMAP. Others return +nil+ for #data, but are used as a
# machine-readable annotation for the human-readable ResponseText#text in
# the same response. When Net::IMAP does not know how to parse response
# code text, #data returns the unparsed string.
#
# Untagged response code #data is pushed directly onto Net::IMAP#responses,
# keyed by #name, unless it is removed by the command that generated it.
# Use Net::IMAP#add_response_handler to view tagged response codes for
# command methods that do not return their TaggedResponse.
#
# \IMAP extensions may define new codes and the data that comes with them.
# The IANA {IMAP Response
# Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
# registry has links to specifications for all standard response codes.
# Response codes are backwards compatible: Servers are allowed to send new
# response codes even if the client has not enabled the extension that
# defines them. When unknown response code data is encountered, #data
# will return an unparsed string.
#
# ==== +IMAP4rev1+ Response Codes
# See [IMAP4rev1[https://www.rfc-editor.org/rfc/rfc3501]] {§7.1, "Server
# Responses - Status
# Responses"}[https://www.rfc-editor.org/rfc/rfc3501#section-7.1] for full
# definitions of the basic set of IMAP4rev1 response codes:
# * +ALERT+, the ResponseText#text contains a special alert that MUST be
# brought to the user's attention.
# * +BADCHARSET+, #data will be an array of charset strings, or +nil+.
# * +CAPABILITY+, #data will be an array of capability strings.
# * +PARSE+, the ResponseText#text presents an error parsing a message's
# \[RFC5322] or [MIME-IMB] headers.
# * +PERMANENTFLAGS+, followed by an array of flags. System flags will be
# symbols, and keyword flags will be strings. See
# rdoc-ref:Net::IMAP@System+flags
# * +READ-ONLY+, the mailbox was selected read-only, or changed to read-only
# * +READ-WRITE+, the mailbox was selected read-write, or changed to
# read-write
# * +TRYCREATE+, when #append or #copy fail because the target mailbox
# doesn't exist.
# * +UIDNEXT+, #data is an Integer, the next UID value of the mailbox. See
# [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501]],
# {§2.3.1.1, "Unique Identifier (UID) Message
# Attribute}[https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1].
# * +UIDVALIDITY+, #data is an Integer, the UID validity value of the
# mailbox. See [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501]],
# {§2.3.1.1, "Unique Identifier (UID) Message
# Attribute}[https://www.rfc-editor.org/rfc/rfc3501#section-2.3.1.1].
# * +UNSEEN+, #data is an Integer, the number of messages which do not have
# the \Seen flag set.
# DEPRECATED by IMAP4rev2.
#
# ==== +BINARY+ extension
# See {[RFC3516]}[https://www.rfc-editor.org/rfc/rfc3516].
# * +UNKNOWN-CTE+, with a tagged +NO+ response, when the server does not
# known how to decode a CTE (content-transfer-encoding). #data is +nil+.
# See IMAP#fetch.
#
# ==== +UIDPLUS+ extension
# See {[RFC4315 §3]}[https://www.rfc-editor.org/rfc/rfc4315#section-3].
# * +APPENDUID+, #data is UIDPlusData. See IMAP#append.
# * +COPYUID+, #data is UIDPlusData. See IMAP#copy.
# * +UIDNOTSTICKY+, #data is +nil+. See IMAP#select.
#
# ==== +SEARCHRES+ extension
# See {[RFC5182]}[https://www.rfc-editor.org/rfc/rfc5182].
# * +NOTSAVED+, with a tagged +NO+ response, when the search result variable
# is not saved. #data is +nil+.
#
# ==== +RFC5530+ Response Codes
# See {[RFC5530]}[https://www.rfc-editor.org/rfc/rfc5530], "IMAP Response
# Codes" for the definition of the following response codes, which are all
# machine-readable annotations for the human-readable ResponseText#text, and
# have +nil+ #data of their own:
# * +UNAVAILABLE+
# * +AUTHENTICATIONFAILED+
# * +AUTHORIZATIONFAILED+
# * +EXPIRED+
# * +PRIVACYREQUIRED+
# * +CONTACTADMIN+
# * +NOPERM+
# * +INUSE+
# * +EXPUNGEISSUED+
# * +CORRUPTION+
# * +SERVERBUG+
# * +CLIENTBUG+
# * +CANNOT+
# * +LIMIT+
# * +OVERQUOTA+
# * +ALREADYEXISTS+
# * +NONEXISTENT+
#
# ==== +QRESYNC+ extension
# See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
# * +CLOSED+, returned when the currently selected mailbox is closed
# implicitly by selecting or examining another mailbox. #data is +nil+.
#
# ==== +IMAP4rev2+ Response Codes
# See {[RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051] {§7.1, "Server
# Responses - Status
# Responses"}[https://www.rfc-editor.org/rfc/rfc9051#section-7.1] for full
# descriptions of IMAP4rev2 response codes. IMAP4rev2 includes all of the
# response codes listed above (except "UNSEEN") and adds the following:
# * +HASCHILDREN+, with a tagged +NO+ response, when a mailbox delete failed
# because the server doesn't allow deletion of mailboxes with children.
# #data is +nil+.
#
# ==== +CONDSTORE+ extension
# See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
# * +NOMODSEQ+, when selecting a mailbox that does not support
# mod-sequences. #data is +nil+. See IMAP#select.
# * +HIGHESTMODSEQ+, #data is an Integer, the highest mod-sequence value of
# all messages in the mailbox. See IMAP#select.
# * +MODIFIED+, #data is a SequenceSet, the messages that have been modified
# since the +UNCHANGEDSINCE+ mod-sequence given to +STORE+ or UID
# STORE.
#
# ==== +OBJECTID+ extension
# See {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
# * +MAILBOXID+, #data is a string
#
class ResponseCode < Struct.new(:name, :data)
##
# method: name
# :call-seq: name -> string
#
# Returns the response code name, such as "ALERT", "PERMANENTFLAGS", or
# "UIDVALIDITY".
##
# method: data
# :call-seq: data -> object or nil
#
# Returns the parsed response code data, e.g: an array of capabilities
# strings, an array of character set strings, a list of permanent flags,
# an Integer, etc. The response #code determines what form the response
# code data can take.
end
# Net::IMAP::UIDPlusData represents the ResponseCode#data that accompanies
# the +APPENDUID+ and +COPYUID+ response codes.
#
# See [[UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]].
#
# ==== Capability requirement
#
# The +UIDPLUS+ capability[rdoc-ref:Net::IMAP#capability] must be supported.
# A server that supports +UIDPLUS+ should send a UIDPlusData object inside
# every TaggedResponse returned by the append[rdoc-ref:Net::IMAP#append],
# copy[rdoc-ref:Net::IMAP#copy], move[rdoc-ref:Net::IMAP#move], {uid
# copy}[rdoc-ref:Net::IMAP#uid_copy], and {uid
# move}[rdoc-ref:Net::IMAP#uid_move] commands---unless the destination
# mailbox reports +UIDNOTSTICKY+.
#
#--
# TODO: support MULTIAPPEND
#++
#
class UIDPlusData < Struct.new(:uidvalidity, :source_uids, :assigned_uids)
##
# method: uidvalidity
# :call-seq: uidvalidity -> nonzero uint32
#
# The UIDVALIDITY of the destination mailbox.
##
# method: source_uids
# :call-seq: source_uids -> nil or an array of nonzero uint32
#
# The UIDs of the copied or moved messages.
#
# Note:: Returns +nil+ for Net::IMAP#append.
##
# method: assigned_uids
# :call-seq: assigned_uids -> an array of nonzero uint32
#
# The newly assigned UIDs of the copied, moved, or appended messages.
#
# Note:: This always returns an array, even when it contains only one UID.
##
# :call-seq: uid_mapping -> nil or a hash
#
# Returns a hash mapping each source UID to the newly assigned destination
# UID.
#
# Note:: Returns +nil+ for Net::IMAP#append.
def uid_mapping
source_uids&.zip(assigned_uids)&.to_h
end
end
# Net::IMAP::MailboxList represents contents of the LIST response,
# representing a single mailbox path.
#
# Net::IMAP#list returns an array of MailboxList objects.
#
class MailboxList < Struct.new(:attr, :delim, :name)
##
# method: attr
# :call-seq: attr -> array of Symbols
#
# Returns the name attributes. Each name attribute is a symbol capitalized
# by String#capitalize, such as :Noselect (not :NoSelect). For the
# semantics of each attribute, see:
# * rdoc-ref:Net::IMAP@Basic+Mailbox+Attributes
# * rdoc-ref:Net::IMAP@Mailbox+role+Attributes
# * Net::IMAP@SPECIAL-USE
# * The IANA {IMAP Mailbox Name Attributes
# registry}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
##
# method: delim
# :call-seq: delim -> single character string
#
# Returns the hierarchy delimiter for the mailbox path.
##
# method: name
# :call-seq: name -> string
#
# Returns the mailbox name.
end
# Net::IMAP::MailboxQuota represents contents of GETQUOTA response.
# This object can also be a response to GETQUOTAROOT. In the syntax
# specification below, the delimiter used with the "#" construct is a
# single space (SPACE).
#
# Net:IMAP#getquota returns an array of MailboxQuota objects.
#
# Net::IMAP#getquotaroot returns an array containing both MailboxQuotaRoot
# and MailboxQuota objects.
#
class MailboxQuota < Struct.new(:mailbox, :usage, :quota)
##
# method: mailbox
# :call-seq: mailbox -> string
#
# The mailbox with the associated quota.
##
# method: usage
# :call-seq: usage -> Integer
#
# Current storage usage of the mailbox.
##
# method: quota
# :call-seq: quota -> Integer
#
# Quota limit imposed on the mailbox.
#
end
# Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
# response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
#
# Net::IMAP#getquotaroot returns an array containing both MailboxQuotaRoot
# and MailboxQuota objects.
#
class MailboxQuotaRoot < Struct.new(:mailbox, :quotaroots)
##
# method: mailbox
# :call-seq: mailbox -> string
#
# The mailbox with the associated quota.
##
# method: mailbox
# :call-seq: quotaroots -> array of strings
#
# Zero or more quotaroots that affect the quota on the specified mailbox.
end
# Net::IMAP::MailboxACLItem represents the response from GETACL.
#
# Net::IMAP#getacl returns an array of MailboxACLItem objects.
#
# ==== Required capability
# +ACL+ - described in [ACL[https://tools.ietf.org/html/rfc4314]]
class MailboxACLItem < Struct.new(:user, :rights, :mailbox)
##
# method: mailbox
# :call-seq: mailbox -> string
#
# The mailbox to which the indicated #user has the specified #rights.
##
# method: user
# :call-seq: user -> string
#
# Login name that has certain #rights to the #mailbox that was specified
# with the getacl command.
##
# method: rights
# :call-seq: rights -> string
#
# The access rights the indicated #user has to the #mailbox.
end
# Net::IMAP::Namespace represents a single namespace contained inside a
# NAMESPACE response.
#
# Returned by Net::IMAP#namespace, contained inside a Namespaces object.
#
class Namespace < Struct.new(:prefix, :delim, :extensions)
##
# method: prefix
# :call-seq: prefix -> string
#
# Returns the namespace prefix string.
##
# method: delim
# :call-seq: delim -> single character string or nil
#
# Returns a hierarchy delimiter character, if it exists.
##
# method: extensions
# :call-seq: extensions -> Hash[String, Array[String]]
#
# A hash of parameters mapped to arrays of strings, for extensibility.
# Extension parameter semantics would be defined by the extension.
end
# Net::IMAP::Namespaces represents a +NAMESPACE+ server response, which
# contains lists of #personal, #shared, and #other namespaces.
#
# Net::IMAP#namespace returns a Namespaces object.
#
class Namespaces < Struct.new(:personal, :other, :shared)
##
# method: personal
# :call-seq: personal -> array of Namespace
#
# Returns an array of Personal Namespace objects.
##
# method: other
# :call-seq: other -> array of Namespace
#
# Returns an array of Other Users' Namespace objects.
##
# method: shared
# :call-seq: shared -> array of Namespace
#
# Returns an array of Shared Namespace objects.
end
# Net::IMAP::StatusData represents the contents of the STATUS response.
#
# Net::IMAP#status returns the contents of #attr.
class StatusData < Struct.new(:mailbox, :attr)
##
# method: mailbox
# :call-seq: mailbox -> string
#
# The mailbox name.
##
# method: attr
# :call-seq: attr -> Hash[String, Integer]
#
# A hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
# "UIDVALIDITY", "UNSEEN". Each value is a number.
end
# Net::IMAP::Envelope represents envelope structures of messages.
#
# [Note]
# When the #sender and #reply_to fields are absent or empty, they will
# return the same value as #from. Also, fields may return values that are
# invalid for well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# messages when the message is malformed or a draft message.
#
# 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]]
# for full description of the envelope fields, and
# Net::IMAP@Message+envelope+and+body+structure for other relevant RFCs.
#
# Returned by FetchData#envelope
class Envelope < Struct.new(:date, :subject, :from, :sender, :reply_to,
:to, :cc, :bcc, :in_reply_to, :message_id)
##
# method: date
# call-seq: date -> string
#
# Returns a string that represents the +Date+ header.
#
# [Note]
# For a well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# message, the #date field must not be +nil+. However it can be +nil+
# for a malformed or draft message.
##
# method: subject
# call-seq: subject -> string or nil
#
# Returns a string that represents the +Subject+ header, if it is present.
#
# [Note]
# Servers should return +nil+ when the header is absent and an empty
# string when it is present but empty. Some servers may return a +nil+
# envelope member in the "present but empty" case. Clients should treat
# +nil+ and empty string as identical.
##
# method: from
# call-seq: from -> array of Net::IMAP::Address or nil
#
# Returns an array of Address that represents the +From+ header.
#
# If the +From+ header is absent, or is present but empty, the server
# returns +nil+ for this envelope field.
#
# [Note]
# For a well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# message, the #from field must not be +nil+. However it can be +nil+
# for a malformed or draft message.
##
# method: sender
# call-seq: sender -> array of Net::IMAP::Address or nil
#
# Returns an array of Address that represents the +Sender+ header.
#
# [Note]
# If the Sender header is absent, or is present but empty, the
# server sets this field to be the same value as #from. Therefore, in a
# well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]] message,
# the #sender envelope field must not be +nil+. However it can be
# +nil+ for a malformed or draft message.
##
# method: reply_to
# call-seq: reply_to -> array of Net::IMAP::Address or nil
#
# Returns an array of Address that represents the Reply-To
# header.
#
# [Note]
# If the Reply-To header is absent, or is present but empty,
# the server sets this field to be the same value as #from. Therefore,
# in a well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# message, the #reply_to envelope field must not be +nil+. However it
# can be +nil+ for a malformed or draft message.
##
# method: to
# call-seq: to -> array of Net::IMAP::Address
#
# Returns an array of Address that represents the +To+ header.
##
# method: cc
# call-seq: cc -> array of Net::IMAP::Address
#
# Returns an array of Address that represents the +Cc+ header.
##
# method: bcc
# call-seq: bcc -> array of Net::IMAP::Address
#
# Returns an array of Address that represents the +Bcc+ header.
##
# method: in_reply_to
# call-seq: in_reply_to -> string
#
# Returns a string that represents the In-Reply-To header.
#
# [Note]
# For a well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# message, the #in_reply_to field, if present, must not be empty. But
# it can still return an empty string for malformed messages.
#
# Servers should return +nil+ when the header is absent and an empty
# string when it is present but empty. Some servers may return a +nil+
# envelope member in the "present but empty" case. Clients should treat
# +nil+ and empty string as identical.
##
# method: message_id
# call-seq: message_id -> string
#
# Returns a string that represents the Message-ID.
#
# [Note]
# For a well-formed [RFC5322[https://tools.ietf.org/html/rfc5322]]
# message, the #message_id field, if present, must not be empty. But it
# can still return an empty string for malformed messages.
#
# Servers should return +nil+ when the header is absent and an empty
# string when it is present but empty. Some servers may return a +nil+
# envelope member in the "present but empty" case. Clients should treat
# +nil+ and empty string as identical.
end
# Net::IMAP::Address represents an electronic mail address, which has been
# parsed into its component parts by the server. Address objects are
# returned within Envelope fields.
#
# === Group syntax
#
# When the #host field is +nil+, this is a special form of address structure
# that indicates the [RFC5322[https://tools.ietf.org/html/rfc5322]] group
# syntax. If the #mailbox name field is also +nil+, this is an end-of-group
# marker (semicolon in RFC-822 syntax). If the #mailbox name field is
# non-+NIL+, this is the start of a group marker, and the mailbox #name
# field holds the group name phrase.
class Address < Struct.new(:name, :route, :mailbox, :host)
##
# method: name
# :call-seq: name -> string or nil
#
# Returns the [RFC5322[https://tools.ietf.org/html/rfc5322]] address
# +display-name+ (or the mailbox +phrase+ in the RFC-822 grammar).
##
# method: route
# :call-seq: route -> string or nil
#
# Returns the route from RFC-822 route-addr.
#
# Note:: Generating this obsolete route addressing syntax is not allowed
# by [RFC5322[https://tools.ietf.org/html/rfc5322]]. However,
# addresses with this syntax must still be accepted and parsed.
##
# method: mailbox
# :call-seq: mailbox -> string or nil
#
# Returns the [RFC5322[https://tools.ietf.org/html/rfc5322]] address
# +local-part+, if #host is not +nil+.
#
# When #host is +nil+, this returns
# an [RFC5322[https://tools.ietf.org/html/rfc5322]] group name and a +nil+
# mailbox indicates the end of a group.
##
# method: host
# :call-seq: host -> string or nil
#
# Returns the [RFC5322[https://tools.ietf.org/html/rfc5322]] addr-spec
# +domain+ name.
#
# +nil+ indicates [RFC5322[https://tools.ietf.org/html/rfc5322]] group
# syntax.
end
# Net::IMAP::ContentDisposition represents Content-Disposition fields.
#
class ContentDisposition < Struct.new(:dsp_type, :param)
##
# 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]].
end
# Net::IMAP::ThreadMember represents a thread-node returned
# by Net::IMAP#thread.
#
class ThreadMember < Struct.new(:seqno, :children)
##
# method: seqno
# :call-seq: seqno -> Integer
#
# The message sequence number.
##
# method: children
# :call-seq: children -> array of ThreadMember
#
# An array of Net::IMAP::ThreadMember objects for mail items that are
# children of this in the thread.
# Returns a SequenceSet containing #seqno and all #children's seqno,
# recursively.
def to_sequence_set
SequenceSet.new all_seqnos
end
protected
def all_seqnos(node = self)
[node.seqno].concat node.children.flat_map { _1.all_seqnos }
end
end
# Net::IMAP::BodyStructure is included by all of the structs that can be
# returned from a "BODYSTRUCTURE" or "BODY"
# FetchData#attr value. Although these classes don't share a base class,
# this module can be used to pattern match all of them.
#
# 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]
# for full description of all +BODYSTRUCTURE+ fields, and also
# Net::IMAP@Message+envelope+and+body+structure for other relevant RFCs.
#
# === Classes that include BodyStructure
# BodyTypeBasic:: Represents any message parts that are not handled by
# BodyTypeText, BodyTypeMessage, or BodyTypeMultipart.
# BodyTypeText:: Used by text/* parts. Contains all of the
# BodyTypeBasic fields.
# BodyTypeMessage:: Used by message/rfc822 and
# message/global parts. Contains all of the
# BodyTypeBasic fields. Other message/* types
# should use BodyTypeBasic.
# BodyTypeMultipart:: for multipart/* parts
#
module BodyStructure
end
# 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]
# for full description of all +BODYSTRUCTURE+ fields, and also
# Net::IMAP@Message+envelope+and+body+structure for other relevant RFCs.
#
class BodyTypeBasic < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
:md5, :disposition, :language,
:location,
:extension)
include BodyStructure
##
# 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
# :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 the body structures of messages and
# message parts, when Content-Type is text/*.
#
# 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,
:description, :encoding, :size,
:lines,
:md5, :disposition, :language,
:location,
:extension)
include BodyStructure
##
# 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
# Obsolete: use +subtype+ instead. Calling this will
# generate a warning message to +stderr+, then return
# the value of +subtype+.
def media_subtype
warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
return subtype
end
end
# Net::IMAP::BodyTypeMessage represents the body structures of messages and
# message parts, when Content-Type is message/rfc822 or
# message/global.
#
# 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,
:description, :encoding, :size,
:envelope, :body, :lines,
:md5, :disposition, :language,
:location,
:extension)
include BodyStructure
##
# 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
# Obsolete: use +subtype+ instead. Calling this will
# generate a warning message to +stderr+, then return
# the value of +subtype+.
def media_subtype
warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
return subtype
end
end
# BodyTypeAttachment is not used and will be removed in an upcoming release.
#
# === Bug Analysis
#
# \IMAP body structures are parenthesized lists and assign their fields
# positionally, so missing fields change the interpretation of all
# following fields. Additionally, different body types have a different
# number of required fields, followed by optional "extension" fields.
#
# BodyTypeAttachment was previously returned when a "message/rfc822" part,
# which should be sent as body-type-msg with ten required fields,
# was actually sent as a body-type-basic with _seven_ required
# fields.
#
# basic => type, subtype, param, id, desc, enc, octets, md5=nil, dsp=nil, lang=nil, loc=nil, *ext
# msg => type, subtype, param, id, desc, enc, octets, envelope, body, lines, md5=nil, ...
#
# Normally, +envelope+ and +md5+ are incompatible, but Net::IMAP leniently
# allowed buggy servers to send +NIL+ for +envelope+. As a result, when a
# server sent a message/rfc822 part with +NIL+ for +md5+ and a
# non-NIL +dsp+, Net::IMAP misinterpreted the
# Content-Disposition as if it were a strange body type. In all
# reported cases, the Content-Disposition was "attachment", so
# BodyTypeAttachment was created as the workaround.
#
# === Current behavior
#
# When interpreted strictly, +envelope+ and +md5+ are incompatible. So the
# current parsing algorithm peeks ahead after it has received the seventh
# body field. If the next token is not the start of an +envelope+, we assume
# the server has incorrectly sent us a body-type-basic and return
# BodyTypeBasic. As a result, what was previously BodyTypeMessage#body =>
# BodyTypeAttachment is now BodyTypeBasic#disposition => ContentDisposition.
#
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
deprecate_constant :BodyTypeAttachment
# 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,
:location,
:extension)
include BodyStructure
##
# 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+.
def media_subtype
warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
return subtype
end
end
# === Obsolete
# BodyTypeExtension is not used and will be removed in an upcoming release.
#
# >>>
# BodyTypeExtension was (incorrectly) used for message/* parts
# (besides message/rfc822, which correctly uses BodyTypeMessage).
#
# Net::IMAP now (correctly) parses all message types (other than
# message/rfc822 or message/global) as BodyTypeBasic.
class BodyTypeExtension < Struct.new(:media_type, :subtype,
:params, :content_id,
:description, :encoding, :size)
def multipart?
return false
end
end
deprecate_constant :BodyTypeExtension
end
end