summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/net/imap.rb171
-rw-r--r--lib/net/imap/flags.rb20
-rw-r--r--lib/net/imap/response_data.rb56
3 files changed, 163 insertions, 84 deletions
@@ -32,12 +32,13 @@ module Net
#
# Net::IMAP implements Internet Message Access Protocol (IMAP) client
- # functionality. The protocol is described in [IMAP].
#
# == IMAP Overview
#
- # An IMAP client connects to a server, and then authenticates
- # itself using either #authenticate() or #login(). Having
# authenticated itself, there is a range of commands
# available to it. Most work with mailboxes, which may be
# arranged in an hierarchical namespace, and each of which
@@ -47,8 +48,8 @@ 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
# mailbox becomes the _current_ mailbox, on which mail-item
# related commands implicitly operate.
@@ -69,7 +70,7 @@ module Net
# 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
- # UIDs have to be reassigned. An IMAP client thus cannot
# rearrange message orders.
#
# == Examples of Usage
@@ -159,40 +160,61 @@ module Net
#
# == References
#
- # [[IMAP]]
- # M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
- # RFC 2060, December 1996. (Note: since obsoleted by RFC 3501)
#
- # [[LANGUAGE-TAGS]]
- # Alvestrand, H., "Tags for the Identification of
- # Languages", RFC 1766, March 1995.
#
- # [[MD5]]
- # Myers, J., and M. Rose, "The Content-MD5 Header Field", RFC
- # 1864, October 1995.
#
- # [[MIME-IMB]]
- # Freed, N., and N. Borenstein, "MIME (Multipurpose Internet
- # Mail Extensions) Part One: Format of Internet Message Bodies", RFC
- # 2045, November 1996.
#
- # [[RFC-822]]
- # Crocker, D., "Standard for the Format of ARPA Internet Text
- # Messages", STD 11, RFC 822, University of Delaware, August 1982.
#
- # [[RFC-2087]]
- # Myers, J., "IMAP4 QUOTA extension", RFC 2087, January 1997.
#
- # [[RFC-2086]]
- # Myers, J., "IMAP4 ACL extension", RFC 2086, January 1997.
#
- # [[RFC-2195]]
- # Klensin, J., Catoe, R., and Krumviede, P., "IMAP/POP AUTHorize Extension
- # for Simple Challenge/Response", RFC 2195, September 1997.
#
- # [[SORT-THREAD-EXT]]
- # Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD
- # Extensions", draft-ietf-imapext-sort, May 2003.
#
# [[OSSL]]
# http://www.openssl.org
@@ -200,9 +222,9 @@ module Net
# [[RSSL]]
# http://savannah.gnu.org/projects/rubypki
#
- # [[UTF7]]
# Goldsmith, D. and Davis, M., "UTF-7: A Mail-Safe Transformation Format of
- # Unicode", RFC 2152, May 1997.
#
class IMAP < Protocol
VERSION = "0.2.1"
@@ -326,7 +348,7 @@ module Net
# )
# end
#
- # See RFC 2971, Section 3.3, for defined fields.
def id(client_id=nil)
synchronize do
send_command("ID", ClientID.new(client_id))
@@ -373,7 +395,7 @@ module Net
#
# For both of these mechanisms, there should be two +args+: username
# and (cleartext) password. A server may not support one or the other
- # of these mechanisms; check #capability() for a capability of
# the form "AUTH=LOGIN" or "AUTH=CRAM-MD5".
#
# Authentication is done using the appropriate authenticator object:
@@ -399,8 +421,8 @@ module Net
# 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.
#
# A Net::IMAP::NoResponseError is raised if authentication fails.
def login(user, password)
@@ -414,7 +436,7 @@ module Net
# number of items in that mailbox from +@responses["EXISTS"][-1]+,
# and the number of recent messages from +@responses["RECENT"][-1]+.
# Note that these values can change if new messages arrive
- # during a session; see #add_response_handler() for a way of
# detecting this event.
#
# A Net::IMAP::NoResponseError is raised if the mailbox does not
@@ -427,7 +449,7 @@ module Net
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.
#
# A Net::IMAP::NoResponseError is raised if the mailbox does not
@@ -469,7 +491,7 @@ module Net
# Sends a SUBSCRIBE command 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.
@@ -516,15 +538,16 @@ module Net
end
end
- # Sends a NAMESPACE command [RFC2342] 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.
#
- # This extension predates IMAP4rev1 (RFC3501), 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.
#
# But many servers are configured with the default personal namespace as
# e.g. `("INBOX." ".")`, placing all personal folders under INBOX, with "."
@@ -563,6 +586,8 @@ module Net
# imap.create(prefix + %w[path to my folder].join(delim))
# end
# end
def namespace
synchronize do
send_command("NAMESPACE")
@@ -606,6 +631,8 @@ module Net
# 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.
def getquotaroot(mailbox)
synchronize do
send_command("GETQUOTAROOT", mailbox)
@@ -620,6 +647,8 @@ module Net
# If this mailbox exists, then an array containing a
# Net::IMAP::MailboxQuota object is returned. This
# command is generally only available to server admin.
def getquota(mailbox)
synchronize do
send_command("GETQUOTA", mailbox)
@@ -630,8 +659,9 @@ module Net
# 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. The IMAP quota commands are described in
- # [RFC-2087].
def setquota(mailbox, quota)
if quota.nil?
data = '()'
@@ -644,7 +674,8 @@ module Net
# 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.
- # The IMAP ACL commands are described in [RFC-2086].
def setacl(mailbox, user, rights)
if rights.nil?
send_command("SETACL", mailbox, user, "")
@@ -656,6 +687,8 @@ module Net
# Send the GETACL command along with a specified +mailbox+.
# If this mailbox exists, an array containing objects of
# Net::IMAP::MailboxACLItem will be returned.
def getacl(mailbox)
synchronize do
send_command("GETACL", mailbox)
@@ -666,7 +699,8 @@ module Net
# 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().
# The return value is an array of +Net::IMAP::MailboxList+.
def lsub(refname, mailbox)
synchronize do
@@ -794,7 +828,7 @@ module Net
return search_internal("SEARCH", keys, charset)
end
- # Similar to #search(), but returns unique identifiers.
def uid_search(keys, charset = nil)
return search_internal("UID SEARCH", keys, charset)
end
@@ -838,7 +872,7 @@ module Net
return fetch_internal("FETCH", set, attr, mod)
end
- # Similar to #fetch(), but +set+ contains unique identifiers.
def uid_fetch(set, attr, mod = nil)
return fetch_internal("UID FETCH", set, attr, mod)
end
@@ -861,7 +895,7 @@ module Net
return store_internal("STORE", set, attr, flags)
end
- # Similar to #store(), but +set+ contains unique identifiers.
def uid_store(set, attr, flags)
return store_internal("UID STORE", set, attr, flags)
end
@@ -874,7 +908,7 @@ module Net
copy_internal("COPY", set, mailbox)
end
- # Similar to #copy(), but +set+ contains unique identifiers.
def uid_copy(set, mailbox)
copy_internal("UID COPY", set, mailbox)
end
@@ -883,12 +917,15 @@ module Net
# 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.
- # The IMAP MOVE extension is described in [RFC-6851].
def move(set, mailbox)
copy_internal("MOVE", set, mailbox)
end
- # Similar to #move(), but +set+ contains unique identifiers.
def uid_move(set, mailbox)
copy_internal("UID MOVE", set, mailbox)
end
@@ -901,12 +938,14 @@ module Net
# p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
# #=> [6, 7, 8, 1]
#
- # See [SORT-THREAD-EXT] for more details.
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.
def uid_sort(sort_keys, search_keys, charset)
return sort_internal("UID SORT", sort_keys, search_keys, charset)
end
@@ -933,7 +972,7 @@ module Net
@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:
#
@@ -942,16 +981,18 @@ module Net
# REFERENCES:: split into threads by parent/child relationships determined
# by which message is a reply to which.
#
- # Unlike #search(), +charset+ is a required argument. US-ASCII
# and UTF-8 are sample values.
#
- # See [SORT-THREAD-EXT] for more details.
def thread(algorithm, search_keys, charset)
return thread_internal("THREAD", algorithm, search_keys, charset)
end
- # Similar to #thread(), but returns unique identifiers instead of
# message sequence numbers.
def uid_thread(algorithm, search_keys, charset)
return thread_internal("UID THREAD", algorithm, search_keys, charset)
end
@@ -959,7 +1000,7 @@ module Net
# Sends an IDLE command that waits for notifications of new or expunged
# messages. Yields responses from the server during the IDLE.
#
- # Use #idle_done() to leave IDLE.
#
# If +timeout+ is given, this method returns after +timeout+ seconds passed.
# +timeout+ can be used for keep-alive. For example, the following code
@@ -3,40 +3,60 @@
module Net
class IMAP < Protocol
# Flag indicating a message has been seen.
SEEN = :Seen
# Flag indicating a message has been answered.
ANSWERED = :Answered
# Flag indicating a message has been flagged for special or urgent
# attention.
FLAGGED = :Flagged
# Flag indicating a message has been marked for deletion. This
# will occur when the mailbox is closed or expunged.
DELETED = :Deleted
# Flag indicating a message is only a draft or work-in-progress version.
DRAFT = :Draft
# Flag indicating that the message is "recent," meaning that this
# session is the first session in which the client has been notified
# of this message.
RECENT = :Recent
# Flag indicating that a mailbox context name cannot contain
# children.
NOINFERIORS = :Noinferiors
# Flag indicating that a mailbox is not selected.
NOSELECT = :Noselect
# Flag indicating that a mailbox has been marked "interesting" by
# the server; this commonly indicates that the mailbox contains
# new messages.
MARKED = :Marked
# Flag indicating that the mailbox does not contains new messages.
UNMARKED = :Unmarked
@@ -17,7 +17,8 @@ module Net
# data:: Returns the data (Net::IMAP::ResponseText).
#
# raw_data:: Returns the raw data string.
- ContinuationRequest = Struct.new(:data, :raw_data)
# Net::IMAP::UntaggedResponse represents untagged responses.
#
@@ -36,7 +37,8 @@ module Net
# a ((<Net::IMAP::MailboxList>)) object.
#
# raw_data:: Returns the raw data string.
- UntaggedResponse = Struct.new(:name, :data, :raw_data)
# Net::IMAP::IgnoredResponse represents intentionally ignored responses.
#
@@ -48,7 +50,8 @@ module Net
# ==== Fields:
#
# raw_data:: Returns the raw data string.
- IgnoredResponse = Struct.new(:raw_data)
# Net::IMAP::TaggedResponse represents tagged responses.
#
@@ -72,7 +75,8 @@ module Net
#
# raw_data:: Returns the raw data string.
#
- TaggedResponse = Struct.new(:tag, :name, :data, :raw_data)
# Net::IMAP::ResponseText represents texts of responses.
# The text may be prefixed by the response code.
@@ -85,7 +89,8 @@ module Net
#
# text:: Returns the text.
#
- ResponseText = Struct.new(:code, :text)
# Net::IMAP::ResponseCode represents response codes.
#
@@ -105,7 +110,8 @@ module Net
#
# data:: Returns the data, if it exists.
#
- ResponseCode = Struct.new(:name, :data)
# Net::IMAP::MailboxList represents contents of the LIST response.
#
@@ -122,7 +128,8 @@ module Net
#
# name:: Returns the mailbox name.
#
- MailboxList = Struct.new(:attr, :delim, :name)
# Net::IMAP::MailboxQuota represents contents of GETQUOTA response.
# This object can also be a response to GETQUOTAROOT. In the syntax
@@ -143,7 +150,8 @@ module Net
#
# quota:: Quota limit imposed on the mailbox.
#
- MailboxQuota = Struct.new(:mailbox, :usage, :quota)
# Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
# response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
@@ -157,7 +165,8 @@ module Net
# quotaroots:: Zero or more quotaroots that affect the quota on the
# specified mailbox.
#
- MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots)
# Net::IMAP::MailboxACLItem represents the response from GETACL.
#
@@ -175,7 +184,8 @@ module Net
# rights:: The access rights the indicated user has to the
# mailbox.
#
- MailboxACLItem = Struct.new(:user, :rights, :mailbox)
# Net::IMAP::Namespace represents a single [RFC-2342] namespace.
#
@@ -191,7 +201,8 @@ module Net
# delim:: Returns nil or the hierarchy delimiter character.
# extensions:: Returns a hash of extension names to extension flag arrays.
#
- Namespace = Struct.new(:prefix, :delim, :extensions)
# Net::IMAP::Namespaces represents the response from [RFC-2342] NAMESPACE.
#
@@ -208,7 +219,8 @@ module Net
# other:: Returns an array of Other Users' Net::IMAP::Namespace objects.
# shared:: Returns an array of Shared Net::IMAP::Namespace objects.
#
- Namespaces = Struct.new(:personal, :other, :shared)
# Net::IMAP::StatusData represents the contents of the STATUS response.
#
@@ -219,7 +231,8 @@ module Net
# attr:: Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
# "UIDVALIDITY", "UNSEEN". Each value is a number.
#
- StatusData = Struct.new(:mailbox, :attr)
# Net::IMAP::FetchData represents the contents of the FETCH response.
#
@@ -260,7 +273,8 @@ module Net
# [UID]
# A number expressing the unique identifier of the message.
#
- FetchData = Struct.new(:seqno, :attr)
# Net::IMAP::Envelope represents envelope structures of messages.
#
@@ -286,8 +300,9 @@ module Net
#
# message_id:: Returns a string that represents the message-id.
#
- Envelope = Struct.new(:date, :subject, :from, :sender, :reply_to,
- :to, :cc, :bcc, :in_reply_to, :message_id)
#
# Net::IMAP::Address represents electronic mail addresses.
@@ -305,7 +320,8 @@ module Net
# host:: nil indicates [RFC-822] group syntax.
# Otherwise, returns [RFC-822] domain name.
#
- Address = Struct.new(:name, :route, :mailbox, :host)
#
# Net::IMAP::ContentDisposition represents Content-Disposition fields.
@@ -317,7 +333,8 @@ module Net
# param:: Returns a hash that represents parameters of the Content-Disposition
# field.
#
- ContentDisposition = Struct.new(:dsp_type, :param)
# Net::IMAP::ThreadMember represents a thread-node returned
# by Net::IMAP#thread.
@@ -329,7 +346,8 @@ module Net
# children:: An array of Net::IMAP::ThreadMember objects for mail
# items that are children of this in the thread.
#
- ThreadMember = Struct.new(:seqno, :children)
# Net::IMAP::BodyTypeBasic represents basic body structures of messages.
#