diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 95c1b207..89b0fcb5 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -23,12 +23,14 @@
module Net
- #
- # Net::IMAP implements Internet Message Access Protocol (IMAP) client
+ # Net::IMAP implements Internet Message Access Protocol (\IMAP) client
# functionality. The protocol is described in
- # [IMAP[https://tools.ietf.org/html/rfc3501]].
+ # [IMAP4rev1[https://tools.ietf.org/html/rfc3501]].
+ #--
+ # TODO: and [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
+ #++
#
- # == IMAP Overview
+ # == \IMAP Overview
#
# An \IMAP client connects to a server, and then authenticates
# itself using either #authenticate or #login. Having
@@ -41,12 +43,14 @@ module Net
# within a hierarchy of directories.
#
# To work on the messages within a mailbox, the client must
- # first select that mailbox, using either #select or (for
- # read-only access) #examine. Once the client has successfully
- # selected a mailbox, they enter _selected_ state, and that
+ # first select that mailbox, using either #select or #examine
+ # (for read-only access). Once the client has successfully
+ # selected a mailbox, they enter the "_selected_" state, and that
# mailbox becomes the _current_ mailbox, on which mail-item
# related commands implicitly operate.
#
+ # === Sequence numbers and UIDs
+ #
# Messages have two sorts of identifiers: message sequence
# numbers and UIDs.
#
@@ -57,15 +61,31 @@ module Net
# are expunged from the mailbox, remaining messages have their
# sequence numbers "shuffled down" to fill the gaps.
#
+ # To avoid sequence number race conditions, servers must not expunge messages
+ # when no command is in progress, nor when responding to #fetch, #store, or
+ # #search. Expunges _may_ be sent during any other command, including
+ # #uid_fetch, #uid_store, and #uid_search. The #noop and #idle commands are
+ # both useful for this side-effect: they allow the server to send all mailbox
+ # updates, including expunges.
+ #
# UIDs, on the other hand, are permanently guaranteed not to
# identify another message within the same mailbox, even if
# the existing message is deleted. UIDs are required to
# be assigned in ascending (but not necessarily sequential)
# order within a mailbox; this means that if a non-IMAP client
- # rearranges the order of mailitems within a mailbox, the
+ # rearranges the order of mail items within a mailbox, the
# UIDs have to be reassigned. An \IMAP client thus cannot
# rearrange message orders.
#
+ # === Server capabilities and protocol extensions
+ #
+ # Net::IMAP does not modify its behavior according to server
+ # #capability. Users of the class must check for required capabilities before
+ # issuing commands. Special care should be taken to follow all #capability
+ # requirements for #starttls, #login, and #authenticate.
+ #
+ # See the #capability method for more information.
+ #
# == Examples of Usage
#
# === List sender and subject of all recent messages in the default mailbox
@@ -108,7 +128,7 @@ module Net
#
# == Errors
#
- # An IMAP server can send three different types of responses to indicate
+ # An \IMAP server can send three different types of responses to indicate
# failure:
#
# NO:: the attempted command could not be successfully completed. For
@@ -116,7 +136,7 @@ module Net
# the selected mailbox does not exist; etc.
#
# BAD:: the request from the client does not follow the server's
- # understanding of the IMAP protocol. This includes attempting
+ # understanding of the \IMAP protocol. This includes attempting
# commands from the wrong client state; for instance, attempting
# to perform a SEARCH command without having SELECTed a current
# mailbox. It can also signal an internal server
@@ -150,6 +170,355 @@ module Net
# between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
# thrown if a server response is non-parseable.
#
+ # == What's here?
+ #
+ # * {Connection control}[rdoc-ref:Net::IMAP@Connection+control+methods]
+ # * {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands]
+ # * {...for any state}[rdoc-ref:Net::IMAP@IMAP+commands+for+any+state]
+ # * {...for the "not authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Not+Authenticated-22+state]
+ # * {...for the "authenticated" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Authenticated-22+state]
+ # * {...for the "selected" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Selected-22+state]
+ # * {...for the "logout" state}[rdoc-ref:Net::IMAP@IMAP+commands+for+the+-22Logout-22+state]
+ # * {Supported IMAP extensions}[rdoc-ref:Net::IMAP@Supported+IMAP+extensions]
+ # * {Handling server responses}[rdoc-ref:Net::IMAP@Handling+server+responses]
+ #
+ # === Connection control methods
+ #
+ # - Net::IMAP.new: A new client connects immediately and waits for a
+ # successful server greeting before returning the new client object.
+ # - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
+ # - #logout: Tells the server to end the session. Enters the "_logout_" state.
+ # - #disconnect: Disconnects the connection (without sending #logout first).
+ # - #disconnected?: True if the connection has been closed.
+ #
+ # === Core \IMAP commands
+ #
+ # The following commands are defined either by
+ # the [IMAP4rev1[https://tools.ietf.org/html/rfc3501]] base specification, or
+ # by one of the following extensions:
+ # [IDLE[https://tools.ietf.org/html/rfc2177]],
+ # [NAMESPACE[https://tools.ietf.org/html/rfc2342]],
+ # [UNSELECT[https://tools.ietf.org/html/rfc3691]],
+ #--
+ # TODO: [ENABLE[https://tools.ietf.org/html/rfc5161]],
+ # TODO: [LIST-EXTENDED[https://tools.ietf.org/html/rfc5258]],
+ # TODO: [LIST-STATUS[https://tools.ietf.org/html/rfc5819]],
+ #++
+ # [MOVE[https://tools.ietf.org/html/rfc6851]].
+ # These extensions are widely supported by modern IMAP4rev1 servers and have
+ # all been integrated into [IMAP4rev2[https://tools.ietf.org/html/rfc9051]].
+ # Note: Net::IMAP doesn't fully support IMAP4rev2 yet.
+ #
+ #--
+ # TODO: When IMAP4rev2 is supported, add the following to the each of the
+ # appropriate commands below.
+ # Note:: CHECK has been removed from IMAP4rev2.
+ # Note:: LSUB is obsoleted by +LIST-EXTENDED and has been removed from IMAP4rev2.
+ # Some arguments require the +LIST-EXTENDED+ or +IMAP4rev2+ capability.
+ # Requires either the +ENABLE+ or +IMAP4rev2+ capability.
+ # Requires either the +NAMESPACE+ or +IMAP4rev2+ capability.
+ # Requires either the +IDLE+ or +IMAP4rev2+ capability.
+ # Requires either the +UNSELECT+ or +IMAP4rev2+ capability.
+ # Requires either the +UIDPLUS+ or +IMAP4rev2+ capability.
+ # Requires either the +MOVE+ or +IMAP4rev2+ capability.
+ #++
+ #
+ # ==== \IMAP commands for any state
+ #
+ # - #capability: Returns the server's capabilities as an array of strings.
+ #
+ # Capabilities may change after #starttls, #authenticate, or #login
+ # and cached capabilities must be reloaded.
+ # - #noop: Allows the server to send unsolicited untagged #responses.
+ # - #logout: Tells the server to end the session. Enters the "_logout_" state.
+ #
+ # ==== \IMAP commands for the "Not Authenticated" state
+ #
+ # In addition to the universal commands, the following commands are valid in
+ # the "not authenticated" state:
+ #
+ # - #starttls: Upgrades a clear-text connection to use TLS.
+ #
+ # Requires the +STARTTLS+ capability.
+ # - #authenticate: Identifies the client to the server using a {SASL
+ # mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml].
+ # Enters the "_authenticated_" state.
+ #
+ # Requires the AUTH=#{mechanism} capability for the chosen
+ # mechanism.
+ # - #login: Identifies the client to the server using a plain text password.
+ # Using #authenticate is generally preferred. Enters the "_authenticated_"
+ # state.
+ #
+ # The +LOGINDISABLED+ capability must NOT be listed.
+ #
+ # ==== \IMAP commands for the "Authenticated" state
+ #
+ # In addition to the universal commands, the following commands are valid in
+ # the "_authenticated_" state:
+ #
+ #--
+ # - #enable: Not implemented by Net::IMAP, yet.
+ #
+ # Requires the +ENABLE+ capability.
+ #++
+ # - #select: Open a mailbox and enter the "_selected_" state.
+ # - #examine: Open a mailbox read-only, and enter the "_selected_" state.
+ # - #create: Creates a new mailbox.
+ # - #delete: Permanently remove a mailbox.
+ # - #rename: Change the name of a mailbox.
+ # - #subscribe: Adds a mailbox to the "subscribed" set.
+ # - #unsubscribe: Removes a mailbox from the "subscribed" set.
+ # - #list: Returns names and attributes of mailboxes matching a given pattern.
+ # - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
+ #
+ # Requires the +NAMESPACE+ capability.
+ # - #status: Returns mailbox information, e.g. message count, unseen message
+ # count, +UIDVALIDITY+ and +UIDNEXT+.
+ # - #append: Appends a message to the end of a mailbox.
+ # - #idle: Allows the server to send updates to the client, without the client
+ # needing to poll using #noop.
+ #
+ # Requires the +IDLE+ capability.
+ # - #lsub: Lists mailboxes the user has declared "active" or "subscribed".
+ #--
+ # Replaced by LIST-EXTENDED and removed from
+ # +IMAP4rev2+. However, Net::IMAP hasn't implemented
+ # LIST-EXTENDED _yet_.
+ #++
+ #
+ # ==== \IMAP commands for the "Selected" state
+ #
+ # In addition to the universal commands and the "authenticated" commands, the
+ # following commands are valid in the "_selected_" state:
+ #
+ # - #close: Closes the mailbox and returns to the "_authenticated_" state,
+ # expunging deleted messages, unless the mailbox was opened as read-only.
+ # - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
+ # without expunging any messages.
+ #
+ # Requires the +UNSELECT+ capability.
+ # - #expunge: Permanently removes messages which have the Deleted flag set.
+ # - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
+ #
+ # Requires the +UIDPLUS+ capability.
+ # - #search, #uid_search: Returns sequence numbers or UIDs of messages that
+ # match the given searching criteria.
+ # - #fetch, #uid_fetch: Returns data associated with a set of messages,
+ # specified by sequence number or UID.
+ # - #store, #uid_store: Alters a message's flags.
+ # - #copy, #uid_copy: Copies the specified messages to the end of the
+ # specified destination mailbox.
+ # - #move, #uid_move: Moves the specified messages to the end of the
+ # specified destination mailbox, expunging them from the current mailbox.
+ #
+ # Requires the +MOVE+ capability.
+ # - #check: Mostly obsolete. Can be replaced with #noop or #idle.
+ #--
+ # Removed from IMAP4rev2.
+ #++
+ #
+ # ==== \IMAP commands for the "Logout" state
+ #
+ # No \IMAP commands are valid in the +logout+ state. If the socket is still
+ # open, Net::IMAP will close it after receiving server confirmation.
+ # Exceptions will be raised by \IMAP commands that have already started and
+ # are waiting for a response, as well as any that are called after logout.
+ #
+ # === Supported \IMAP extensions
+ #
+ # ==== RFC9051: +IMAP4rev2+
+ #
+ # Although IMAP4rev2[https://tools.ietf.org/html/rfc9051] is not supported
+ # yet, Net::IMAP supports several extensions that have been folded into
+ # it: +IDLE+, +MOVE+, +NAMESPACE+, +UIDPLUS+, and +UNSELECT+.
+ #--
+ # TODO: RFC4466, ABNF extensions (automatic support for other extensions)
+ # TODO: +ESEARCH+, ExtendedSearchData
+ # TODO: +SEARCHRES+,
+ # TODO: +ENABLE+,
+ # TODO: +SASL-IR+,
+ # TODO: +LIST-EXTENDED+,
+ # TODO: +LIST-STATUS+,
+ # TODO: +LITERAL-+,
+ # TODO: +BINARY+ (only the FETCH side)
+ # TODO: +SPECIAL-USE+
+ # implicitly supported, but we can do better: Response codes: RFC5530, etc
+ # implicitly supported, but we can do better: STATUS=SIZE
+ # implicitly supported, but we can do better: STATUS DELETED
+ #++
+ # Commands for these extensions are included with the {Core IMAP
+ # commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above. Other supported
+ # extensons are listed below.
+ #
+ # ==== RFC2087: +QUOTA+
+ # - #getquota: returns the resource usage and limits for a quota root
+ # - #getquotaroot: returns the list of quota roots for a mailbox, as well as
+ # their resource usage and limits.
+ # - #setquota: sets the resource limits for a given quota root.
+ #
+ # ==== RFC2177: +IDLE+
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
+ # listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
+ # - #idle: Allows the server to send updates to the client, without the client
+ # needing to poll using #noop.
+ #
+ # ==== RFC2342: +NAMESPACE+
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
+ # listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
+ # - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
+ #
+ # ==== RFC2971: +ID+
+ # - #id: exchanges client and server implementation information.
+ #
+ #--
+ # ==== RFC3502: +MULTIAPPEND+
+ # TODO...
+ #++
+ #
+ #--
+ # ==== RFC3516: +BINARY+
+ # TODO...
+ #++
+ #
+ # ==== RFC3691: +UNSELECT+
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
+ # listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
+ # - #unselect: Closes the mailbox and returns to the "_authenticated_" state,
+ # without expunging any messages.
+ #
+ # ==== RFC4314: +ACL+
+ # - #getacl: lists the authenticated user's access rights to a mailbox.
+ # - #setacl: sets the access rights for a user on a mailbox
+ #--
+ # TODO: #deleteacl, #listrights, #myrights
+ #++
+ # - *_Note:_* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
+ #
+ # ==== RFC4315: +UIDPLUS+
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
+ # listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
+ # - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
+ # - Updates #select, #examine with the +UIDNOTSTICKY+ ResponseCode
+ # - Updates #append with the +APPENDUID+ ResponseCode
+ # - Updates #copy, #move with the +COPYUID+ ResponseCode
+ #
+ #--
+ # ==== RFC4466: Collected Extensions to IMAP4 ABNF
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this RFC updates
+ # the protocol to enable new optional parameters to many commands: #select,
+ # #examine, #create, #rename, #fetch, #uid_fetch, #store, #uid_store, #search,
+ # #uid_search, and #append. However, specific parameters are not defined.
+ # Extensions to these commands use this syntax whenever possible. Net::IMAP
+ # may be partially compatible with extensions to these commands, even without
+ # any explicit support.
+ #++
+ #
+ #--
+ # ==== RFC4731 +ESEARCH+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
+ # - Updates #search, #uid_search to accept result options: +MIN+, +MAX+,
+ # +ALL+, +COUNT+, and to return ExtendedSearchData.
+ #++
+ #
+ #--
+ # ==== RFC4959: +SASL-IR+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
+ # - Updates #authenticate to reduce round-trips for supporting mechanisms.
+ #++
+ #
+ #--
+ # ==== RFC4978: COMPRESS=DEFLATE
+ # TODO...
+ #++
+ #
+ #--
+ # ==== RFC5182 +SEARCHRES+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
+ # - Updates #search, #uid_search with the +SAVE+ result option.
+ # - Updates #copy, #uid_copy, #fetch, #uid_fetch, #move, #uid_move, #search,
+ # #uid_search, #store, #uid_store, and #uid_expunge with ability to
+ # reference the saved result of a previous #search or #uid_search command.
+ #++
+ #
+ # ==== RFC5256: +SORT+
+ # - #sort, #uid_sort: An alternate version of #search or #uid_search which
+ # sorts the results by specified keys.
+ # ==== RFC5256: +THREAD+
+ # - #thread, #uid_thread: An alternate version of #search or #uid_search,
+ # which arranges the results into ordered groups or threads according to a
+ # chosen algorithm.
+ #
+ #--
+ # ==== RFC5258 +LIST-EXTENDED+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], this updates the
+ # protocol with new optional parameters to the #list command, adding a few of
+ # its own. Net::IMAP may be forward-compatible with future #list extensions,
+ # even without any explicit support.
+ # - Updates #list to accept selection options: +SUBSCRIBED+, +REMOTE+, and
+ # +RECURSIVEMATCH+, and return options: +SUBSCRIBED+ and +CHILDREN+.
+ #++
+ #
+ #--
+ # ==== RFC5819 +LIST-STATUS+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
+ # - Updates #list with +STATUS+ return option.
+ #++
+ #
+ # ==== +XLIST+ (non-standard, deprecated)
+ # - #xlist: replaced by +SPECIAL-USE+ attributes in #list responses.
+ #
+ #--
+ # ==== RFC6154 +SPECIAL-USE+
+ # TODO...
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051].
+ # - Updates #list with the +SPECIAL-USE+ selection and return options.
+ #++
+ #
+ # ==== RFC6851: +MOVE+
+ # Folded into IMAP4rev2[https://tools.ietf.org/html/rfc9051], so it is also
+ # listed with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
+ # - #move, #uid_move: Moves the specified messages to the end of the
+ # specified destination mailbox, expunging them from the current mailbox.
+ #
+ #--
+ # ==== RFC6855: UTF8=ACCEPT
+ # TODO...
+ # ==== RFC6855: UTF8=ONLY
+ # TODO...
+ #++
+ #
+ #--
+ # ==== RFC7888: LITERAL+, +LITERAL-+
+ # TODO...
+ # ==== RFC7162: +QRESYNC+
+ # TODO...
+ # ==== RFC7162: +CONDSTORE+
+ # TODO...
+ # ==== RFC8474: +OBJECTID+
+ # TODO...
+ # ==== RFC9208: +QUOTA+
+ # TODO...
+ #++
+ #
+ # === Handling server responses
+ #
+ # - #greeting: The server's initial untagged response, which can indicate a
+ # pre-authenticated connection.
+ # - #responses: The untagged responses, as a hash. Keys are the untagged
+ # response type (e.g. "OK", "FETCH", "FLAGS") and response code (e.g.
+ # "ALERT", "UIDVALIDITY", "UIDNEXT", "TRYCREATE", etc). Values are arrays
+ # of UntaggedResponse or ResponseCode.
+ # - #add_response_handler: Add a block to be called inside the receiver thread
+ # with every server response.
+ # - #remove_response_handler: Remove a previously added response handler.
+ #
#
# == References
#--
@@ -340,10 +709,12 @@ class IMAP < Protocol
include SSL
end
- # Returns an initial greeting response from the server.
+ # Returns the initial greeting the server, an UntaggedResponse.
attr_reader :greeting
- # Returns recorded untagged responses. For example:
+ # Returns recorded untagged responses.
+ #
+ # For example:
#
# imap.select("inbox")
# p imap.responses["EXISTS"][-1]
@@ -392,6 +763,8 @@ class << self
end
# Disconnects from the server.
+ #
+ # Related: #logout
def disconnect
return if disconnected?
begin
@@ -415,20 +788,64 @@ def disconnect
end
# Returns true if disconnected from the server.
+ #
+ # Related: #logout, #disconnect
def disconnected?
return @sock.closed?
end
- # Sends a CAPABILITY command, and returns an array of
- # capabilities that the server supports. Each capability
- # is a string. See [IMAP] for a list of possible
- # capabilities.
+ # Sends a {CAPABILITY command [IMAP4rev1 §6.1.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.1]
+ # and returns an array of capabilities that the server supports. Each
+ # capability is a string.
+ #
+ # See the {IANA IMAP4 capabilities
+ # registry}[http://www.iana.org/assignments/imap4-capabilities] for a list
+ # of all standard capabilities, and their reference RFCs.
+ #
+ # >>>
+ # *Note* that Net::IMAP does not currently modify its
+ # behaviour according to the capabilities of the server;
+ # it is up to the user of the class to ensure that
+ # a certain capability is supported by a server before
+ # using it.
+ #
+ # Capability requirements—other than +IMAP4rev1+—are listed in the
+ # documentation for each command method.
+ #
+ # ===== Basic IMAP4rev1 capabilities
+ #
+ # All IMAP4rev1 servers must include +IMAP4rev1+ in their capabilities list.
+ # All IMAP4rev1 servers must _implement_ the +STARTTLS+,
+ # AUTH=PLAIN, and +LOGINDISABLED+ capabilities, and clients must
+ # respect their presence or absence. See the capabilites requirements on
+ # #starttls, #login, and #authenticate.
+ #
+ # ===== Using IMAP4rev1 extensions
+ #
+ # IMAP4rev1 servers must not activate incompatible behavior until an
+ # explicit client action invokes a capability, e.g. sending a command or
+ # command argument specific to that capability. Extensions with backward
+ # compatible behavior, such as response codes or mailbox attributes, may
+ # be sent at any time.
+ #
+ # Invoking capabilities which are unknown to Net::IMAP may cause unexpected
+ # behavior and errors, for example ResponseParseError is raised when unknown
+ # response syntax is received. Invoking commands or command parameters that
+ # are unsupported by the server may raise NoResponseError, BadResponseError,
+ # or cause other unexpected behavior.
+ #
+ # ===== Caching +CAPABILITY+ responses
+ #
+ # Servers may send their capability list, unsolicited, using the
+ # +CAPABILITY+ response code or an untagged +CAPABILITY+ response. These
+ # responses can be retrieved and cached using #responses or
+ # #add_response_handler.
+ #
+ # But cached capabilities _must_ be discarded after #starttls, #login, or
+ # #authenticate. The OK TaggedResponse to #login and #authenticate may
+ # include +CAPABILITY+ response code data, but the TaggedResponse for
+ # #starttls is sent clear-text and cannot be trusted.
#
- # Note that the Net::IMAP class does not modify its
- # behaviour according to the capabilities of the server;
- # it is up to the user of the class to ensure that
- # a certain capability is supported by a server before
- # using it.
def capability
synchronize do
send_command("CAPABILITY")
@@ -436,8 +853,9 @@ def capability
end
end
- # Sends an ID command, and returns a hash of the server's
- # response, or nil if the server does not identify itself.
+ # Sends an {ID command [RFC2971 §3.1]}[https://www.rfc-editor.org/rfc/rfc2971#section-3.1]
+ # and returns a hash of the server's response, or nil if the server does not
+ # identify itself.
#
# Note that the user should first check if the server supports the ID
# capability. For example:
@@ -453,6 +871,11 @@ def capability
# end
#
# See [ID[https://tools.ietf.org/html/rfc2971]] for field definitions.
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +ID+
+ # [RFC2971[https://tools.ietf.org/html/rfc2971]]
def id(client_id=nil)
synchronize do
send_command("ID", ClientID.new(client_id))
@@ -460,18 +883,60 @@ def id(client_id=nil)
end
end
- # Sends a NOOP command to the server. It does nothing.
+ # Sends a {NOOP command [IMAP4rev1 §6.1.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.2]
+ # to the server.
+ #
+ # This allows the server to send unsolicited untagged EXPUNGE #responses,
+ # but does not execute any client request. \IMAP servers are permitted to
+ # send unsolicited untagged responses at any time, except for `EXPUNGE`.
+ #
+ # * +EXPUNGE+ can only be sent while a command is in progress.
+ # * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
+ # * +EXPUNGE+ may be sent during #uid_fetch, #uid_store, or #uid_search.
+ #
+ # Related: #idle, #check
def noop
send_command("NOOP")
end
- # Sends a LOGOUT command to inform the server that the client is
- # done with the connection.
+ # Sends a {LOGOUT command [IMAP4rev1 §6.1.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.3]
+ # to inform the command to inform the server that the client is done with
+ # the connection.
+ #
+ # Related: #disconnect
def logout
send_command("LOGOUT")
end
- # Sends a STARTTLS command to start TLS session.
+ # Sends a {STARTTLS command [IMAP4rev1 §6.2.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.1]
+ # to start a TLS session.
+ #
+ # Any +options+ are forwarded to OpenSSL::SSL::SSLContext#set_params.
+ #
+ # This method returns after TLS negotiation and hostname verification are
+ # both successful. Any error indicates that the connection has not been
+ # secured.
+ #
+ # *Note:*
+ # >>>
+ # Any #response_handlers added before STARTTLS should be aware that the
+ # TaggedResponse to STARTTLS is sent clear-text, _before_ TLS negotiation.
+ # TLS negotiation starts immediately after that response.
+ #
+ # Related: Net::IMAP.new, #login, #authenticate
+ #
+ # ===== Capability
+ #
+ # The server's capabilities must include +STARTTLS+.
+ #
+ # Server capabilities may change after #starttls, #login, and #authenticate.
+ # Cached capabilities _must_ be invalidated after this method completes.
+ #
+ # The TaggedResponse to #starttls is sent clear-text, so the server must
+ # *not* send capabilities in the #starttls response and clients must
+ # not use them if they are sent. Servers will generally send an
+ # unsolicited untagged response immeditely _after_ #starttls completes.
+ #
def starttls(options = {}, verify = true)
send_command("STARTTLS") do |resp|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
@@ -486,43 +951,95 @@ def starttls(options = {}, verify = true)
end
end
- # Sends an AUTHENTICATE command to authenticate the client.
- # The +auth_type+ parameter is a string that represents
- # the authentication mechanism to be used. Currently Net::IMAP
- # supports the following mechanisms:
- #
- # PLAIN:: Login using cleartext user and password. Secure with TLS.
- # See Net::IMAP::PlainAuthenticator.
- # CRAM-MD5:: DEPRECATED: Use PLAIN (or DIGEST-MD5) with TLS.
- # DIGEST-MD5:: DEPRECATED by RFC6331. Must be secured using TLS.
- # See Net::IMAP::DigestMD5Authenticator.
- # LOGIN:: DEPRECATED: Use PLAIN.
- #
- # Most mechanisms require two args: authentication identity (e.g. username)
- # and credentials (e.g. a password). But each mechanism requires and allows
- # different arguments; please consult the documentation for the specific
- # mechanisms you are using. Several obsolete mechanisms are available
- # for backwards compatibility. Using deprecated mechanisms will issue
- # warnings.
- #
- # Servers do not support all mechanisms and clients must not attempt to use
- # a mechanism unless "AUTH=#{mechanism}" is listed as a #capability.
- # Clients must not attempt to authenticate or #login when +LOGINDISABLED+ is
- # listed with the capabilities. Server capabilities, especially auth
- # mechanisms, do change after calling #starttls so they need to be checked
- # again.
+ # :call-seq:
+ # authenticate(mechanism, ...) -> ok_resp
+ # authenticate(mech, *creds, **props) {|prop, auth| val } -> ok_resp
+ # authenticate(mechanism, authnid, credentials, authzid=nil) -> ok_resp
+ # authenticate(mechanism, **properties) -> ok_resp
+ # authenticate(mechanism) {|propname, authctx| prop_value } -> ok_resp
#
- # For example:
+ # Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
+ # to authenticate the client. If successful, the connection enters the
+ # "_authenticated_" state.
#
- # imap.authenticate('PLAIN', user, password)
+ # +mechanism+ is the name of the \SASL authentication mechanism to be used.
+ # All other arguments are forwarded to the authenticator for the requested
+ # mechanism. The listed call signatures are suggestions. The
+ # documentation for each individual mechanism must be consulted for its
+ # specific parameters.
#
- # A Net::IMAP::NoResponseError is raised if authentication fails.
+ # An exception Net::IMAP::NoResponseError is raised if authentication fails.
+ #
+ # Related: #login, #starttls
+ #
+ # ==== Supported SASL Mechanisms
+ #
+ # +PLAIN+:: See PlainAuthenticator.
+ # Login using clear-text username and password.
+ #
+ # +XOAUTH2+:: See XOauth2Authenticator.
+ # Login using a username and OAuth2 access token.
+ # Non-standard and obsoleted by +OAUTHBEARER+, but widely
+ # supported.
+ #
+ # >>>
+ # *Deprecated:* Obsolete mechanisms are available for backwards
+ # compatibility.
+ #
+ # For +DIGEST-MD5+ see DigestMD5Authenticator.
+ #
+ # For +LOGIN+, see LoginAuthenticator.
#
- # See +Net::IMAP::Authenticators+ for more information on plugging in your
- # own authenticator.
- def authenticate(auth_type, *args)
- authenticator = self.class.authenticator(auth_type, *args)
- send_command("AUTHENTICATE", auth_type) do |resp|
+ # For +CRAM-MD5+, see CramMD5Authenticator.
+ #
+ # Using a deprecated mechanism will print a warning.
+ #
+ # See Net::IMAP::Authenticators for information on plugging in
+ # authenticators for other mechanisms. See the {SASL mechanism
+ # registry}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
+ # for information on these and other SASL mechanisms.
+ #
+ # ===== Capabilities
+ #
+ # Clients MUST NOT attempt to authenticate with a mechanism unless
+ # "AUTH=#{mechanism}" for that mechanism is a server capability.
+ #
+ # Server capabilities may change after #starttls, #login, and #authenticate.
+ # Cached capabilities _must_ be invalidated after this method completes.
+ # The TaggedResponse to #authenticate may include updated capabilities in
+ # its ResponseCode.
+ #
+ # ===== Example
+ # If the authenticators ignore unhandled keyword arguments, the same config
+ # can be used for multiple mechanisms:
+ #
+ # password = nil # saved locally, so we don't ask more than once
+ # accesstok = nil # saved locally...
+ # creds = {
+ # authcid: username,
+ # password: proc { password ||= ui.prompt_for_password },
+ # oauth2_token: proc { accesstok ||= kms.fresh_access_token },
+ # }
+ # capa = imap.capability
+ # if capa.include? "AUTH=OAUTHBEARER"
+ # imap.authenticate "OAUTHBEARER", **creds # authcid, oauth2_token
+ # elsif capa.include? "AUTH=XOAUTH2"
+ # imap.authenticate "XOAUTH2", **creds # authcid, oauth2_token
+ # elsif capa.include? "AUTH=SCRAM-SHA-256"
+ # imap.authenticate "SCRAM-SHA-256", **creds # authcid, password
+ # elsif capa.include? "AUTH=PLAIN"
+ # imap.authenticate "PLAIN", **creds # authcid, password
+ # elsif capa.include? "AUTH=DIGEST-MD5"
+ # imap.authenticate "DIGEST-MD5", **creds # authcid, password
+ # elsif capa.include? "LOGINDISABLED"
+ # raise "the server has disabled login"
+ # else
+ # imap.login username, password
+ # end
+ #
+ def authenticate(mechanism, *args, **props, &cb)
+ authenticator = self.class.authenticator(mechanism, *args, **props, &cb)
+ send_command("AUTHENTICATE", mechanism) do |resp|
if resp.instance_of?(ContinuationRequest)
data = authenticator.process(resp.data.text.unpack("m")[0])
s = [data].pack("m0")
@@ -532,18 +1049,33 @@ def authenticate(auth_type, *args)
end
end
- # Sends a LOGIN command to identify the client and carries
- # the plaintext +password+ authenticating this +user+. Note
- # that, unlike calling #authenticate with an +auth_type+
- # of "LOGIN", #login does *not* use the login authenticator.
+ # Sends a {LOGIN command [IMAP4rev1 §6.2.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.3]
+ # to identify the client and carries the plaintext +password+ authenticating
+ # this +user+. If successful, the connection enters the "_authenticated_"
+ # state.
+ #
+ # Using #authenticate is generally preferred over #login. The LOGIN command
+ # is not the same as #authenticate with the "LOGIN" +mechanism+.
#
# A Net::IMAP::NoResponseError is raised if authentication fails.
+ #
+ # Related: #authenticate, #starttls
+ #
+ # ==== Capabilities
+ # Clients MUST NOT call #login if +LOGINDISABLED+ is listed with the
+ # capabilities.
+ #
+ # Server capabilities may change after #starttls, #login, and #authenticate.
+ # Cached capabilities _must_ be invalidated after this method completes.
+ # The TaggedResponse to #login may include updated capabilities in its
+ # ResponseCode.
+ #
def login(user, password)
send_command("LOGIN", user, password)
end
- # Sends a SELECT command to select a +mailbox+ so that messages
- # in the +mailbox+ can be accessed.
+ # Sends a {SELECT command [IMAP4rev1 §6.3.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.1]
+ # to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
#
# After you have selected a mailbox, you may retrieve the number of items in
# that mailbox from imap.responses["EXISTS"][-1], and the number of
@@ -555,7 +1087,9 @@ def login(user, password)
# A Net::IMAP::NoResponseError is raised if the mailbox does not
# exist or is for some reason non-selectable.
#
- # ==== Capabilities
+ # Related: #examine
+ #
+ # ===== Capabilities
#
# If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
# the server may return an untagged "NO" response with a "UIDNOTSTICKY"
@@ -569,12 +1103,15 @@ def select(mailbox)
end
end
- # Sends a EXAMINE command to select a +mailbox+ so that messages
- # in the +mailbox+ can be accessed. Behaves the same as #select,
- # except that the selected +mailbox+ is identified as read-only.
+ # Sends a {EXAMINE command [IMAP4rev1 §6.3.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.2]
+ # to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
+ # Behaves the same as #select, except that the selected +mailbox+ is
+ # identified as read-only.
#
# A Net::IMAP::NoResponseError is raised if the mailbox does not
# exist or is for some reason non-examinable.
+ #
+ # Related: #select
def examine(mailbox)
synchronize do
@responses.clear
@@ -582,69 +1119,86 @@ def examine(mailbox)
end
end
- # Sends a CREATE command to create a new +mailbox+.
+ # Sends a {CREATE command [IMAP4rev1 §6.3.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.3]
+ # to create a new +mailbox+.
#
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
# cannot be created.
+ #
+ # Related: #rename, #delete
def create(mailbox)
send_command("CREATE", mailbox)
end
- # Sends a DELETE command to remove the +mailbox+.
+ # Sends a {DELETE command [IMAP4rev1 §6.3.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.4]
+ # to remove the +mailbox+.
#
# A Net::IMAP::NoResponseError is raised if a mailbox with that name
# cannot be deleted, either because it does not exist or because the
# client does not have permission to delete it.
+ #
+ # Related: #create, #rename
def delete(mailbox)
send_command("DELETE", mailbox)
end
- # Sends a RENAME command to change the name of the +mailbox+ to
- # +newname+.
+ # Sends a {RENAME command [IMAP4rev1 §6.3.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.5]
+ # to change the name of the +mailbox+ to +newname+.
#
# A Net::IMAP::NoResponseError is raised if a mailbox with the
# name +mailbox+ cannot be renamed to +newname+ for whatever
# reason; for instance, because +mailbox+ does not exist, or
# because there is already a mailbox with the name +newname+.
+ #
+ # Related: #create, #delete
def rename(mailbox, newname)
send_command("RENAME", mailbox, newname)
end
- # Sends a SUBSCRIBE command to add the specified +mailbox+ name to
- # the server's set of "active" or "subscribed" mailboxes as returned
- # by #lsub.
+ # Sends a {SUBSCRIBE command [IMAP4rev1 §6.3.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.6]
+ # to add the specified +mailbox+ name to the server's set of "active" or
+ # "subscribed" mailboxes as returned by #lsub.
#
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
# subscribed to; for instance, because it does not exist.
+ #
+ # Related: #unsubscribe, #lsub, #list
def subscribe(mailbox)
send_command("SUBSCRIBE", mailbox)
end
- # Sends a UNSUBSCRIBE command to remove the specified +mailbox+ name
- # from the server's set of "active" or "subscribed" mailboxes.
+ # Sends an {UNSUBSCRIBE command [IMAP4rev1 §6.3.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.7]
+ # to remove the specified +mailbox+ name from the server's set of "active"
+ # or "subscribed" mailboxes.
#
# A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
# unsubscribed from; for instance, because the client is not currently
# subscribed to it.
+ #
+ # Related: #subscribe, #lsub, #list
def unsubscribe(mailbox)
send_command("UNSUBSCRIBE", mailbox)
end
- # Sends a LIST 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
- # in a directory-based mailbox hierarchy). +mailbox+ specifies
- # a mailbox or (via wildcards) mailboxes under that context.
- # Two wildcards may be used in +mailbox+: '*', which matches
- # all characters *including* the hierarchy delimiter (for instance,
- # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%',
- # which matches all characters *except* the hierarchy delimiter.
+ # Sends a {LIST command [IMAP4rev1 §6.3.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.8]
+ # 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 in a directory-based mailbox hierarchy). +mailbox+ specifies a
+ # mailbox or (via wildcards) mailboxes under that context. Two wildcards
+ # may be used in +mailbox+: '*', which matches all characters *including*
+ # the hierarchy delimiter (for instance, '/' on a UNIX-hosted
+ # directory-based mailbox hierarchy); and '%', which matches all characters
+ # *except* the hierarchy delimiter.
#
# If +refname+ is empty, +mailbox+ is used directly to determine
# which mailboxes to match. If +mailbox+ is empty, the root
# name of +refname+ and the hierarchy delimiter are returned.
#
- # The return value is an array of +Net::IMAP::MailboxList+. For example:
+ # The return value is an array of MailboxList.
+ #
+ # Related: #lsub, MailboxList
+ #
+ # ===== For example:
#
# imap.create("foo/bar")
# imap.create("foo/baz")
@@ -652,6 +1206,10 @@ def unsubscribe(mailbox)
# #=> [#, \\
# #, \\
# #]
+ #
+ #--
+ # TODO: support LIST-EXTENDED extension [RFC5258]. Needed for IMAP4rev2.
+ #++
def list(refname, mailbox)
synchronize do
send_command("LIST", refname, mailbox)
@@ -659,41 +1217,39 @@ def list(refname, mailbox)
end
end
- # Sends a NAMESPACE command and returns the namespaces that are available.
- # The NAMESPACE command allows a client to discover the prefixes of
- # namespaces used by a server for personal mailboxes, other users'
- # mailboxes, and shared mailboxes.
+ # Sends a {NAMESPACE command [RFC2342 §5]}[https://www.rfc-editor.org/rfc/rfc2342#section-5]
+ # and returns the namespaces that are available. The NAMESPACE command
+ # allows a client to discover the prefixes of namespaces used by a server
+ # for personal mailboxes, other users' mailboxes, and shared mailboxes.
#
- # The NAMESPACE extension predates [IMAP4rev1[https://tools.ietf.org/html/rfc2501]],
- # so most IMAP servers support it. Many popular IMAP servers are configured
- # with the default personal namespaces as `("" "/")`: no prefix and "/"
- # hierarchy delimiter. In that common case, the naive client may not have
- # any trouble naming mailboxes.
+ # The return value is a Namespaces object which has +personal+, +other+, and
+ # +shared+ fields, each an array of Namespace objects. These arrays will be
+ # empty when the server responds with +nil+.
#
+ # Many \IMAP servers are configured with the default personal namespaces as
+ # ("" "/"): no prefix and the "+/+" hierarchy delimiter. In that
+ # common case, the naive client may not have any trouble naming mailboxes.
# But many servers are configured with the default personal namespace as
- # e.g. `("INBOX." ".")`, placing all personal folders under INBOX, with "."
- # as the hierarchy delimiter. If the client does not check for this, but
- # naively assumes it can use the same folder names for all servers, then
- # folder creation (and listing, moving, etc) can lead to errors.
+ # e.g. ("INBOX." "."), placing all personal folders under INBOX,
+ # with "+.+" as the hierarchy delimiter. If the client does not check for
+ # this, but naively assumes it can use the same folder names for all
+ # servers, then folder creation (and listing, moving, etc) can lead to
+ # errors.
#
# From RFC2342:
#
# Although typically a server will support only a single Personal
# Namespace, and a single Other User's Namespace, circumstances exist
# where there MAY be multiples of these, and a client MUST be prepared
- # for them. If a client is configured such that it is required to create
+ # for them. If a client is configured such that it is required to create
# a certain mailbox, there can be circumstances where it is unclear which
- # Personal Namespaces it should create the mailbox in. In these
+ # Personal Namespaces it should create the mailbox in. In these
# situations a client SHOULD let the user select which namespaces to
# create the mailbox in.
#
- # The user of this method should first check if the server supports the
- # NAMESPACE capability. The return value is a +Net::IMAP::Namespaces+
- # object which has +personal+, +other+, and +shared+ fields, each an array
- # of +Net::IMAP::Namespace+ objects. These arrays will be empty when the
- # server responds with nil.
+ # Related: #list, Namespaces, Namespace
#
- # For example:
+ # ===== For example:
#
# capabilities = imap.capability
# if capabilities.include?("NAMESPACE")
@@ -708,7 +1264,10 @@ def list(refname, mailbox)
# end
# end
#
- # The NAMESPACE extension is described in [NAMESPACE[https://tools.ietf.org/html/rfc2342]]
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +NAMESPACE+
+ # [RFC2342[https://tools.ietf.org/html/rfc2342]].
def namespace
synchronize do
send_command("NAMESPACE")
@@ -733,7 +1292,7 @@ def namespace
# The XLIST command is like the LIST command except that the flags
# returned refer to the function of the folder/mailbox, e.g. :Sent
#
- # The return value is an array of +Net::IMAP::MailboxList+. For example:
+ # The return value is an array of MailboxList objects. For example:
#
# imap.create("foo/bar")
# imap.create("foo/baz")
@@ -741,6 +1300,18 @@ def namespace
# #=> [#, \\
# #, \\
# #]
+ #
+ # Related: #list, MailboxList
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +XLIST+,
+ # a deprecated Gmail extension (replaced by +SPECIAL-USE+).
+ #--
+ # TODO: Net::IMAP doesn't yet have full SPECIAL-USE support. Supporting
+ # servers MAY return SPECIAL-USE attributes, but are not *required* to
+ # unless the SPECIAL-USE return option is supplied.
+ #++
def xlist(refname, mailbox)
synchronize do
send_command("XLIST", refname, mailbox)
@@ -748,12 +1319,17 @@ def xlist(refname, mailbox)
end
end
- # Sends the GETQUOTAROOT command along with the specified +mailbox+.
- # This command is generally available to both admin and user.
- # If this mailbox exists, it returns an array containing objects of type
- # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota.
+ # Sends a {GETQUOTAROOT command [RFC2087 §4.3]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.3]
+ # along with the specified +mailbox+. This command is generally available
+ # to both admin and user. If this mailbox exists, it returns an array
+ # containing objects of type MailboxQuotaRoot and MailboxQuota.
+ #
+ # Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
+ #
+ # ===== Capabilities
#
- # The QUOTA extension is described in [QUOTA[https://tools.ietf.org/html/rfc2087]]
+ # The server's capabilities must include +QUOTA+
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
def getquotaroot(mailbox)
synchronize do
send_command("GETQUOTAROOT", mailbox)
@@ -764,12 +1340,17 @@ def getquotaroot(mailbox)
end
end
- # Sends the GETQUOTA command along with specified +mailbox+.
- # If this mailbox exists, then an array containing a
- # Net::IMAP::MailboxQuota object is returned. This
- # command is generally only available to server admin.
+ # Sends a {GETQUOTA command [RFC2087 §4.2]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.2]
+ # along with specified +mailbox+. If this mailbox exists, then an array
+ # containing a MailboxQuota object is returned. This command is generally
+ # only available to server admin.
#
- # The QUOTA extension is described in [QUOTA[https://tools.ietf.org/html/rfc2087]]
+ # Related: #getquotaroot, #setquota, MailboxQuota
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +QUOTA+
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
def getquota(mailbox)
synchronize do
send_command("GETQUOTA", mailbox)
@@ -777,12 +1358,17 @@ def getquota(mailbox)
end
end
- # Sends a SETQUOTA command along with the specified +mailbox+ and
- # +quota+. If +quota+ is nil, then +quota+ will be unset for that
- # mailbox. Typically one needs to be logged in as a server admin
- # for this to work.
+ # Sends a {SETQUOTA command [RFC2087 §4.1]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.1]
+ # along with the specified +mailbox+ and +quota+. If +quota+ is nil, then
+ # +quota+ will be unset for that mailbox. Typically one needs to be logged
+ # in as a server admin for this to work.
+ #
+ # Related: #getquota, #getquotaroot
+ #
+ # ===== Capabilities
#
- # The QUOTA extension is described in [QUOTA[https://tools.ietf.org/html/rfc2087]]
+ # The server's capabilities must include +QUOTA+
+ # [RFC2087[https://tools.ietf.org/html/rfc2087]].
def setquota(mailbox, quota)
if quota.nil?
data = '()'
@@ -792,11 +1378,17 @@ def setquota(mailbox, quota)
send_command("SETQUOTA", mailbox, RawData.new(data))
end
- # Sends the SETACL command along with +mailbox+, +user+ and the
- # +rights+ that user is to have on that mailbox. If +rights+ is nil,
- # then that user will be stripped of any rights to that mailbox.
+ # Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
+ # along with +mailbox+, +user+ and the +rights+ that user is to have on that
+ # mailbox. If +rights+ is nil, then that user will be stripped of any
+ # rights to that mailbox.
+ #
+ # Related: #getacl
#
- # The ACL extension is described in [ACL[https://tools.ietf.org/html/rfc4314]]
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +ACL+
+ # [RFC4314[https://tools.ietf.org/html/rfc4314]].
def setacl(mailbox, user, rights)
if rights.nil?
send_command("SETACL", mailbox, user, "")
@@ -805,11 +1397,16 @@ def setacl(mailbox, user, rights)
end
end
- # Send the GETACL command along with a specified +mailbox+.
- # If this mailbox exists, an array containing objects of
- # Net::IMAP::MailboxACLItem will be returned.
+ # Sends a {GETACL command [RFC4314 §3.3]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.3]
+ # along with a specified +mailbox+. If this mailbox exists, an array
+ # containing objects of MailboxACLItem will be returned.
+ #
+ # Related: #setacl, MailboxACLItem
#
- # The ACL extension is described in [ACL[https://tools.ietf.org/html/rfc4314]]
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +ACL+
+ # [RFC4314[https://tools.ietf.org/html/rfc4314]].
def getacl(mailbox)
synchronize do
send_command("GETACL", mailbox)
@@ -817,12 +1414,14 @@ def getacl(mailbox)
end
end
- # Sends a LSUB command, and returns a subset of names from the set
- # of names that the user has declared as being "active" or
- # "subscribed." +refname+ and +mailbox+ are interpreted as
- # for #list.
+ # Sends a {LSUB command [IMAP4rev1 §6.3.9]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.9]
+ # and returns a subset of names from the set of names that the user has
+ # declared as being "active" or "subscribed." +refname+ and +mailbox+ are
+ # interpreted as for #list.
+ #
+ # The return value is an array of MailboxList objects.
#
- # The return value is an array of +Net::IMAP::MailboxList+.
+ # Related: #subscribe, #unsubscribe, #list, MailboxList
def lsub(refname, mailbox)
synchronize do
send_command("LSUB", refname, mailbox)
@@ -830,9 +1429,10 @@ def lsub(refname, mailbox)
end
end
- # Sends a STATUS command, and returns the status of the indicated
- # +mailbox+. +attr+ is a list of one or more attributes whose
- # statuses are to be requested. Supported attributes include:
+ # Sends a {STATUS commands [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
+ # and returns the status of the indicated +mailbox+. +attr+ is a list of one
+ # or more attributes whose statuses are to be requested. Supported
+ # attributes include:
#
# MESSAGES:: the number of messages in the mailbox.
# RECENT:: the number of recent messages in the mailbox.
@@ -853,11 +1453,12 @@ def status(mailbox, attr)
end
end
- # Sends a APPEND command to append the +message+ to the end of
- # the +mailbox+. The optional +flags+ argument is an array of
- # flags initially passed to the new message. The optional
- # +date_time+ argument specifies the creation time to assign to the
+ # Sends an {APPEND command [IMAP4rev1 §6.3.11]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.11]
+ # to append the +message+ to the end of the +mailbox+. The optional +flags+
+ # argument is an array of flags initially passed to the new message. The
+ # optional +date_time+ argument specifies the creation time to assign to the
# new message; it defaults to the current time.
+ #
# For example:
#
# imap.append("inbox", <\\Deleted
+ # flag set.
+ #
+ # Related: #unselect
def close
send_command("CLOSE")
end
- # Sends an {UNSELECT command [IMAP4rev2
- # §6.4.2]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.2] to free the
- # session resources for a mailbox and return to the "_authenticated_" state.
- # This is the same as #close, except that \\Deleted messages are
- # not removed from the mailbox.
+ # Sends an {UNSELECT command [RFC3691 §2]}[https://www.rfc-editor.org/rfc/rfc3691#section-3]
+ # {[IMAP4rev2 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.2]
+ # to free the session resources for a mailbox and return to the
+ # "_authenticated_" state. This is the same as #close, except that
+ # \\Deleted messages are not removed from the mailbox.
+ #
+ # Related: #close
#
# ===== Capabilities
#
@@ -921,8 +1530,11 @@ def unselect
send_command("UNSELECT")
end
+ # Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
# Sends a EXPUNGE command to permanently remove from the currently
# selected mailbox all messages that have the \Deleted flag set.
+ #
+ # Related: #uid_expunge
def expunge
synchronize do
send_command("EXPUNGE")
@@ -930,27 +1542,31 @@ def expunge
end
end
- # Similar to #expunge, but takes a set of unique identifiers as
- # argument. Sends a UID EXPUNGE command to permanently remove all
- # messages that have both the \\Deleted flag set and a UID that is
- # included in +uid_set+.
+ # Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
+ # {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
+ # to permanently remove all messages that have both the \\Deleted
+ # flag set and a UID that is included in +uid_set+.
#
- # By using UID EXPUNGE instead of EXPUNGE when resynchronizing with
+ # By using #uid_expunge instead of #expunge when resynchronizing with
# the server, the client can ensure that it does not inadvertantly
- # remove any messages that have been marked as \\Deleted by other
+ # remove any messages that have been marked as \\Deleted by other
# clients between the time that the client was last connected and
# the time the client resynchronizes.
#
- # Note:: Although the command takes a +uid_set+ for its argument, the
+ # *Note:*
+ # >>>
+ # Although the command takes a set of UIDs for its argument, the
# server still returns regular EXPUNGE responses, which contain
# a sequence number. These will be deleted from
# #responses and this method returns them as an array of
# sequence number integers.
#
- # ==== Capability requirement
+ # Related: #expunge
+ #
+ # ===== Capabilities
#
- # +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] must be
- # supported by the server.
+ # The server's capabilities must include +UIDPLUS+
+ # [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
def uid_expunge(uid_set)
synchronize do
send_command("UID EXPUNGE", MessageSet.new(uid_set))
@@ -958,20 +1574,33 @@ def uid_expunge(uid_set)
end
end
- # Sends a SEARCH command to search the mailbox for messages that
- # match the given searching criteria, and returns message sequence
- # numbers. +keys+ can either be a string holding the entire
- # search string, or a single-dimension array of search keywords and
- # arguments. The following are some common search criteria;
- # see [IMAP] section 6.4.4 for a full list.
+ # Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
+ # to search the mailbox for messages that match the given searching
+ # criteria, and returns message sequence numbers. +keys+ can either be a
+ # string holding the entire search string, or a single-dimension array of
+ # search keywords and arguments.
+ #
+ # Related: #uid_search
+ #
+ # ===== Search criteria
#
- # :: a set of message sequence numbers. ',' indicates
- # an interval, ':' indicates a range. For instance,
- # '2,10:12,15' means "2,10,11,12,15".
+ # For a full list of search criteria,
+ # see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
+ # or [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]],
+ # in addition to documentation for
+ # any [CAPABILITIES[https://www.iana.org/assignments/imap-capabilities/imap-capabilities.xhtml]]
+ # reported by #capability which may define additional search filters, e.g:
+ # +CONDSTORE+, +WITHIN+, +FILTERS+, SEARCH=FUZZY, +OBJECTID+, or
+ # +SAVEDATE+. The following are some common search criteria:
+ #
+ # :: a set of message sequence numbers. "," indicates
+ # an interval, "+:+" indicates a range. For instance,
+ # "2,10:12,15" means "2,10,11,12,15".
#
# BEFORE :: messages with an internal date strictly before
- # . The date argument has a format similar
- # to 8-Aug-2002.
+ # . The date argument has a format similar
+ # to 8-Aug-2002, and can be formatted using
+ # Net::IMAP.format_date.
#
# BODY :: messages that contain within their body.
#
@@ -994,21 +1623,26 @@ def uid_expunge(uid_set)
#
# TO :: messages with in their TO field.
#
- # For example:
+ # ===== For example:
#
# p imap.search(["SUBJECT", "hello", "NOT", "NEW"])
# #=> [1, 6, 7, 8]
+ #
def search(keys, charset = nil)
return search_internal("SEARCH", keys, charset)
end
- # Similar to #search, but returns unique identifiers.
+ # Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
+ # to search the mailbox for messages that match the given searching
+ # criteria, and returns unique identifiers (UIDs).
+ #
+ # See #search for documentation of search criteria.
def uid_search(keys, charset = nil)
return search_internal("UID SEARCH", keys, charset)
end
- # Sends a FETCH command to retrieve data associated with a message
- # in the mailbox.
+ # Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
+ # to retrieve data associated with a message in the mailbox.
#
# The +set+ parameter is a number or a range between two numbers,
# or an array of those. The number is a message sequence number,
@@ -1020,12 +1654,14 @@ def uid_search(keys, charset = nil)
# equivalent to 1..5.
#
# +attr+ is a list of attributes to fetch; see the documentation
- # for Net::IMAP::FetchData for a list of valid attributes.
+ # for FetchData for a list of valid attributes.
#
- # The return value is an array of Net::IMAP::FetchData or nil
+ # The return value is an array of FetchData or nil
# (instead of an empty array) if there is no matching message.
#
- # For example:
+ # Related: #uid_search, FetchData
+ #
+ # ===== For example:
#
# p imap.fetch(6..8, "UID")
# #=> [#98}>, \\
@@ -1046,20 +1682,35 @@ def fetch(set, attr, mod = nil)
return fetch_internal("FETCH", set, attr, mod)
end
- # Similar to #fetch, but +set+ contains unique identifiers.
+ # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
+ # to retrieve data associated with a message in the mailbox.
+ #
+ # Similar to #fetch, but the +set+ parameter contains unique identifiers
+ # instead of message sequence numbers.
+ #
+ # >>>
+ # *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
+ # part of any +FETCH+ response caused by a +UID+ command, regardless of
+ # whether a +UID+ was specified as a message data item to the +FETCH+.
+ #
+ # Related: #fetch, FetchData
def uid_fetch(set, attr, mod = nil)
return fetch_internal("UID FETCH", set, attr, mod)
end
- # Sends a STORE command to alter data associated with messages
- # in the mailbox, in particular their flags. The +set+ parameter
- # is a number, an array of numbers, or a Range object. Each number
- # is a message sequence number. +attr+ is the name of a data item
- # to store: 'FLAGS' will replace the message's flag list
- # with the provided one, '+FLAGS' will add the provided flags,
- # and '-FLAGS' will remove them. +flags+ is a list of flags.
+ # Sends a {STORE command [IMAP4rev1 §6.4.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.6]
+ # to alter data associated with messages in the mailbox, in particular their
+ # flags. The +set+ parameter is a number, an array of numbers, or a Range
+ # object. Each number is a message sequence number. +attr+ is the name of a
+ # data item to store: 'FLAGS' will replace the message's flag list with the
+ # provided one, '+FLAGS' will add the provided flags, and '-FLAGS' will
+ # remove them. +flags+ is a list of flags.
+ #
+ # The return value is an array of FetchData
#
- # The return value is an array of Net::IMAP::FetchData. For example:
+ # Related: #uid_store
+ #
+ # ===== For example:
#
# p imap.store(6..8, "+FLAGS", [:Deleted])
# #=> [#[:Seen, :Deleted]}>, \\
@@ -1069,110 +1720,137 @@ def store(set, attr, flags)
return store_internal("STORE", set, attr, flags)
end
- # Similar to #store, but +set+ contains unique identifiers.
+ # Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
+ # to alter data associated with messages in the mailbox, in particular their
+ # flags.
+ #
+ # Similar to #store, but +set+ contains unique identifiers instead of
+ # message sequence numbers.
+ #
+ # Related: #store
def uid_store(set, attr, flags)
return store_internal("UID STORE", set, attr, flags)
end
- # Sends a COPY command to copy the specified message(s) to the end
- # of the specified destination +mailbox+. The +set+ parameter is
- # a number, an array of numbers, or a Range object. The number is
- # a message sequence number.
+ # Sends a {COPY command [IMAP4rev1 §6.4.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.7]
+ # to copy the specified message(s) to the end of the specified destination
+ # +mailbox+. The +set+ parameter is a number, an array of numbers, or a
+ # Range object. The number is a message sequence number.
#
- # ==== Capabilities
+ # Related: #uid_copy
+ #
+ # ===== Capabilities
#
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
# supported, the server's response should include a +COPYUID+ response code
- # with the UIDVALIDITY of the destination mailbox, the UID set of the source
- # messages, and the assigned UID set of the moved messages.
+ # with UIDPlusData. This will report the UIDVALIDITY of the destination
+ # mailbox, the UID set of the source messages, and the assigned UID set of
+ # the moved messages.
def copy(set, mailbox)
copy_internal("COPY", set, mailbox)
end
+ # Sends a {UID COPY command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
+ # to copy the specified message(s) to the end of the specified destination
+ # +mailbox+.
+ #
# Similar to #copy, but +set+ contains unique identifiers.
#
- # ==== Capabilities
+ # ===== Capabilities
#
# +UIDPLUS+ affects #uid_copy the same way it affects #copy.
def uid_copy(set, mailbox)
copy_internal("UID COPY", set, mailbox)
end
- # Sends a MOVE command to move the specified message(s) to the end
- # of the specified destination +mailbox+. The +set+ parameter is
- # a number, an array of numbers, or a Range object. The number is
- # a message sequence number.
+ # Sends a {MOVE command [RFC6851 §3.1]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.1]
+ # {[IMAP4rev2 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.8]
+ # to move the specified message(s) to the end of the specified destination
+ # +mailbox+. The +set+ parameter is a number, an array of numbers, or a
+ # Range object. The number is a message sequence number.
+ #
+ # Related: #uid_move
#
- # ==== Capabilities requirements
+ # ===== Capabilities
#
- # +MOVE+ [RFC6851[https://tools.ietf.org/html/rfc6851]] must be supported by
- # the server.
+ # The server's capabilities must include +MOVE+
+ # [RFC6851[https://tools.ietf.org/html/rfc6851]].
#
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
- # also supported, the server's response should include a +COPYUID+ response
- # code with the UIDVALIDITY of the destination mailbox, the UID set of the
- # source messages, and the assigned UID set of the moved messages.
+ # supported, the server's response should include a +COPYUID+ response code
+ # with UIDPlusData. This will report the UIDVALIDITY of the destination
+ # mailbox, the UID set of the source messages, and the assigned UID set of
+ # the moved messages.
#
def move(set, mailbox)
copy_internal("MOVE", set, mailbox)
end
+ # Sends a {UID MOVE command [RFC6851 §3.2]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.2]
+ # {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
+ # to move the specified message(s) to the end of the specified destination
+ # +mailbox+.
+ #
# Similar to #move, but +set+ contains unique identifiers.
#
- # ==== Capabilities requirements
+ # Related: #move
#
- # Same as #move: +MOVE+ [RFC6851[https://tools.ietf.org/html/rfc6851]] must
- # be supported by the server. +UIDPLUS+ also affects #uid_move the same way
- # it affects #move.
+ # ===== Capabilities
+ #
+ # Same as #move: The server's capabilities must include +MOVE+
+ # [RFC6851[https://tools.ietf.org/html/rfc6851]]. +UIDPLUS+ also affects
+ # #uid_move the same way it affects #move.
def uid_move(set, mailbox)
copy_internal("UID MOVE", set, mailbox)
end
- # Sends a SORT command to sort messages in the mailbox.
- # Returns an array of message sequence numbers. For example:
+ # Sends a {SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
+ # to search a mailbox for messages that match +search_keys+ and return an
+ # array of message sequence numbers, sorted by +sort_keys+. +search_keys+
+ # are interpreted the same as for #search.
+ #
+ #--
+ # TODO: describe +sort_keys+
+ #++
+ #
+ # Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
+ #
+ # ===== For example:
#
# p imap.sort(["FROM"], ["ALL"], "US-ASCII")
# #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
# #=> [6, 7, 8, 1]
#
- # The SORT extension is described in [SORT[https://tools.ietf.org/html/rfc5256]].
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +SORT+
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
def sort(sort_keys, search_keys, charset)
return sort_internal("SORT", sort_keys, search_keys, charset)
end
- # Similar to #sort, but returns an array of unique identifiers.
+ # Sends a {UID SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
+ # to search a mailbox for messages that match +search_keys+ and return an
+ # array of unique identifiers, sorted by +sort_keys+. +search_keys+ are
+ # interpreted the same as for #search.
#
- # The SORT extension is described in [SORT[https://tools.ietf.org/html/rfc5256]].
+ # Related: #sort, #search, #uid_search, #thread, #uid_thread
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +SORT+
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
def uid_sort(sort_keys, search_keys, charset)
return sort_internal("UID SORT", sort_keys, search_keys, charset)
end
- # Adds a response handler. For example, to detect when
- # the server sends a new EXISTS response (which normally
- # indicates new messages being added to the mailbox),
- # add the following handler after selecting the
- # mailbox:
+ # Sends a {THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
+ # to search a mailbox and return message sequence numbers in threaded
+ # format, as a ThreadMember tree. +search_keys+ are interpreted the same as
+ # for #search.
#
- # imap.add_response_handler { |resp|
- # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
- # puts "Mailbox now has #{resp.data} messages"
- # end
- # }
- #
- def add_response_handler(handler = nil, &block)
- raise ArgumentError, "two Procs are passed" if handler && block
- @response_handlers.push(block || handler)
- end
-
- # Removes the response handler.
- def remove_response_handler(handler)
- @response_handlers.delete(handler)
- end
-
- # Similar to #search, but returns message sequence numbers in threaded
- # format, as a Net::IMAP::ThreadMember tree. The supported algorithms
- # are:
+ # The supported algorithms are:
#
# ORDEREDSUBJECT:: split into single-level threads according to subject,
# ordered by date.
@@ -1182,21 +1860,34 @@ def remove_response_handler(handler)
# Unlike #search, +charset+ is a required argument. US-ASCII
# and UTF-8 are sample values.
#
- # The THREAD extension is described in [THREAD[https://tools.ietf.org/html/rfc5256]].
+ # Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +THREAD+
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
def thread(algorithm, search_keys, charset)
return thread_internal("THREAD", algorithm, search_keys, charset)
end
+ # Sends a {UID THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
# Similar to #thread, but returns unique identifiers instead of
# message sequence numbers.
#
- # The THREAD extension is described in [THREAD[https://tools.ietf.org/html/rfc5256]].
+ # Related: #thread, #search, #uid_search, #sort, #uid_sort
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +THREAD+
+ # [RFC5256[https://tools.ietf.org/html/rfc5256]].
def uid_thread(algorithm, search_keys, charset)
return thread_internal("UID THREAD", algorithm, search_keys, charset)
end
- # Sends an IDLE command that waits for notifications of new or expunged
- # messages. Yields responses from the server during the IDLE.
+ # Sends an {IDLE command [RFC2177 §3]}[https://www.rfc-editor.org/rfc/rfc6851#section-3]
+ # {[IMAP4rev2 §6.3.13]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.3.13]
+ # that waits for notifications of new or expunged messages. Yields
+ # responses from the server during the IDLE.
#
# Use #idle_done to leave IDLE.
#
@@ -1209,6 +1900,13 @@ def uid_thread(algorithm, search_keys, charset)
# ...
# end
# end
+ #
+ # Related: #idle_done, #noop, #check
+ #
+ # ===== Capabilities
+ #
+ # The server's capabilities must include +IDLE+
+ # [RFC2177[https://tools.ietf.org/html/rfc2177]].
def idle(timeout = nil, &response_handler)
raise LocalJumpError, "no block given" unless response_handler
@@ -1239,6 +1937,8 @@ def idle(timeout = nil, &response_handler)
end
# Leaves IDLE.
+ #
+ # Related: #idle
def idle_done
synchronize do
if @idle_done_cond.nil?
@@ -1248,6 +1948,28 @@ def idle_done
end
end
+ # Adds a response handler. For example, to detect when
+ # the server sends a new EXISTS response (which normally
+ # indicates new messages being added to the mailbox),
+ # add the following handler after selecting the
+ # mailbox:
+ #
+ # imap.add_response_handler { |resp|
+ # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
+ # puts "Mailbox now has #{resp.data} messages"
+ # end
+ # }
+ #
+ def add_response_handler(handler = nil, &block)
+ raise ArgumentError, "two Procs are passed" if handler && block
+ @response_handlers.push(block || handler)
+ end
+
+ # Removes the response handler.
+ def remove_response_handler(handler)
+ @response_handlers.delete(handler)
+ end
+
private
CRLF = "\r\n" # :nodoc:
diff --git a/lib/net/imap/authenticators.rb b/lib/net/imap/authenticators.rb
index d6f5ff69..44f781e5 100644
--- a/lib/net/imap/authenticators.rb
+++ b/lib/net/imap/authenticators.rb
@@ -3,22 +3,42 @@
# Registry for SASL authenticators used by Net::IMAP.
module Net::IMAP::Authenticators
- # Adds an authenticator for use with Net::IMAP#authenticate. +auth_type+ is the
+ # Adds an authenticator for Net::IMAP#authenticate to use. +mechanism+ is the
# {SASL mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
- # supported by +authenticator+ (for instance, "+PLAIN+"). The +authenticator+
- # is an object which defines a +#process+ method to handle authentication with
- # the server. See Net::IMAP::PlainAuthenticator, Net::IMAP::LoginAuthenticator,
- # Net::IMAP::CramMD5Authenticator, and Net::IMAP::DigestMD5Authenticator for
- # examples.
+ # implemented by +authenticator+ (for instance, "PLAIN").
+ #
+ # The +authenticator+ must respond to +#new+ (or #call), receiving the
+ # authenticator configuration and return a configured authentication session.
+ # The authenticator session must respond to +#process+, receiving the server's
+ # challenge and returning the client's response.
#
- # If +auth_type+ refers to an existing authenticator, it will be
- # replaced by the new one.
+ # See PlainAuthenticator, XOauth2Authenticator, and DigestMD5Authenticator for
+ # examples.
def add_authenticator(auth_type, authenticator)
authenticators[auth_type] = authenticator
end
- # Builds an authenticator for Net::IMAP#authenticate. +args+ will be passed
- # directly to the chosen authenticator's +#initialize+.
+ # :call-seq:
+ # authenticator(mechanism, ...) -> authenticator
+ # authenticator(mech, *creds, **props) {|prop, auth| val } -> authenticator
+ # authenticator(mechanism, authnid, creds, authzid=nil) -> authenticator
+ # authenticator(mechanism, **properties) -> authenticator
+ # authenticator(mechanism) {|propname, authctx| value } -> authenticator
+ #
+ # Builds a new authentication session context for +mechanism+.
+ #
+ # [Note]
+ # This method is intended for internal use by connection protocol code only.
+ # Protocol client users should see refer to their client's documentation,
+ # e.g. Net::IMAP#authenticate for Net::IMAP.
+ #
+ # The call signatures documented for this method are recommendations for
+ # authenticator implementors. All arguments (other than +mechanism+) are
+ # forwarded to the registered authenticator's +#new+ (or +#call+) method, and
+ # each authenticator must document its own arguments.
+ #
+ # The returned object represents a single authentication exchange and must
+ # not be reused for multiple authentication attempts.
def authenticator(mechanism, *authargs, **properties, &callback)
authenticator = authenticators.fetch(mechanism.upcase) do
raise ArgumentError, 'unknown auth type - "%s"' % mechanism
diff --git a/lib/net/imap/flags.rb b/lib/net/imap/flags.rb
index 68bb8b81..88091d01 100644
--- a/lib/net/imap/flags.rb
+++ b/lib/net/imap/flags.rb
@@ -257,5 +257,6 @@ class IMAP < Protocol
# special use is likely not to be supported.
TRASH = :Trash
+ # :section:
end
end
diff --git a/lib/net/imap/sasl/stringprep.rb b/lib/net/imap/sasl/stringprep.rb
index 32d25557..b352b368 100644
--- a/lib/net/imap/sasl/stringprep.rb
+++ b/lib/net/imap/sasl/stringprep.rb
@@ -26,6 +26,9 @@ def self.[](table)
#
# Also checks bidirectional characters, when bidi: true, which may
# raise a BidiStringError.
+ #
+ # +profile+ is an optional string which will be added to any exception that
+ # is raised (it does not affect behavior).
def check_prohibited!(string, *tables, bidi: false, profile: nil)
tables = TABLE_TITLES.keys.grep(/^C/) if tables.empty?
tables |= %w[C.8] if bidi
@@ -47,10 +50,11 @@ def check_prohibited!(string, *tables, bidi: false, profile: nil)
# RandALCat character MUST be the last character of the string.
#
# This is usually combined with #check_prohibited!, so table "C.8" is only
- # checked when +c_8: true+.
+ # checked when c_8: true.
#
# Raises either ProhibitedCodepoint or BidiStringError unless all
- # requirements are met.
+ # requirements are met. +profile+ is an optional string which will be
+ # added to any exception that is raised (it does not affect behavior).
def check_bidi!(string, c_8: false, profile: nil)
check_prohibited!(string, "C.8", profile: profile) if c_8
if BIDI_FAILS_REQ2.match?(string)
diff --git a/rakelib/rfcs.rake b/rakelib/rfcs.rake
index e22dee8c..d1b9bb7c 100644
--- a/rakelib/rfcs.rake
+++ b/rakelib/rfcs.rake
@@ -43,7 +43,8 @@ RFCS = {
2046 => "[MIME-IMT]: MIME Part Two: Media Types",
2047 => "[MIME-HDRS]: MIME Part Three: Header Extensions for Non-ASCII Text",
2183 => "[DISPOSITION]: The Content-Disposition Header",
- 2231 => "MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations",
+ 2231 => "MIME Parameter Value and Encoded Word Extensions: " \
+ "Character Sets, Languages, and Continuations",
2557 => "[LOCATION]: MIME Encapsulation of Aggregate Documents",
2978 => "[CHARSET]: IANA Charset Registration Procedures, BCP 19",
3282 => "[LANGUAGE-TAGS]: Content Language Headers",
@@ -146,6 +147,7 @@ RFCS = {
9208 => "IMAP QUOTA, QUOTA=, QUOTASET",
# etc...
+ 3629 => "UTF8",
6857 => "Post-Delivery Message Downgrading for I18n Email Messages",
}.freeze