summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-04 00:46:06 +0000
committershugo <shugo@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-08-04 00:46:06 +0000
commit79c0605534b0db23ec715ebfa30f8645e46b9fcb (patch)
tree794da6fd025ebcf0f7e15e96622d9d59f37c98e3
parentefd9ddc8a9bda406e5e544c68d8d7a41f6d47697 (diff)
* lib/net/imap.rb: convert RD to RDoc.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4309 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--lib/net/imap.rb1683
1 files changed, 871 insertions, 812 deletions
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 2cbb408168..e3f6902e98 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -1,806 +1,53 @@
-=begin
-
-= net/imap.rb
-
-Copyright (C) 2000 Shugo Maeda <shugo@ruby-lang.org>
-
-This library is distributed under the terms of the Ruby license.
-You can freely distribute/modify this library.
-
-== Net::IMAP
-
-Net::IMAP implements Internet Message Access Protocol (IMAP) clients.
-(The protocol is described in ((<[IMAP]>)).)
-
-Net::IMAP supports multiple commands. For example,
-
- imap = Net::IMAP.new("imap.foo.net", "imap2")
- imap.authenticate("cram-md5", "bar", "password")
- imap.select("inbox")
- fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
- search_result = imap.search(["BODY", "hello"])
- fetch_result = fetch_thread.value
- imap.disconnect
-
-This script invokes the FETCH command and the SEARCH command concurrently.
-
-=== Super Class
-
-Object
-
-=== Class Methods
-
-: new(host, port = 143, usessl = false, certs = nil, verify = false)
- Creates a new Net::IMAP object and connects it to the specified
- port on the named host. If usessl is true, then an attempt will
- be made to use SSL (now TLS) to connect to the server. For this
- to work OpenSSL((<[OSSL]>)) and the Ruby OpenSSL((<[RSSL]>))
- extension need to be installed. The certs parameter indicates
- the path or file containing the CA cert of the server, and the
- verify parameter is for the OpenSSL verification callback.
-
-: debug
- Returns the debug mode.
-
-: debug = val
- Sets the debug mode.
-
-: add_authenticator(auth_type, authenticator)
- Adds an authenticator for Net::IMAP#authenticate.
-
-=== Methods
-
-: greeting
- Returns an initial greeting response from the server.
-
-: responses
- Returns recorded untagged responses.
-
- ex).
- imap.select("inbox")
- p imap.responses["EXISTS"][-1]
- #=> 2
- p imap.responses["UIDVALIDITY"][-1]
- #=> 968263756
-
-: disconnect
- Disconnects from the server.
-
-: capability
- Sends a CAPABILITY command, and returns a listing of
- capabilities that the server supports.
-
-: noop
- Sends a NOOP command to the server. It does nothing.
-
-: logout
- Sends a LOGOUT command to inform the server that the client is
- done with the connection.
-
-: authenticate(auth_type, arg...)
- Sends an AUTEHNTICATE command to authenticate the client.
- The auth_type parameter is a string that represents
- the authentication mechanism to be used. Currently Net::IMAP
- supports "LOGIN" and "CRAM-MD5" for the auth_type.
-
- ex).
- imap.authenticate('LOGIN', user, password)
-
-: login(user, password)
- Sends a LOGIN command to identify the client and carries
- the plaintext password authenticating this user.
-
-: select(mailbox)
- Sends a SELECT command to select a mailbox so that messages
- in the mailbox can be accessed.
-
-: examine(mailbox)
- Sends a EXAMINE command to select a mailbox so that messages
- in the mailbox can be accessed. However, the selected mailbox
- is identified as read-only.
-
-: create(mailbox)
- Sends a CREATE command to create a new mailbox.
-
-: delete(mailbox)
- Sends a DELETE command to remove the mailbox.
-
-: rename(mailbox, newname)
- Sends a RENAME command to change the name of the mailbox to
- the newname.
-
-: subscribe(mailbox)
- Sends a SUBSCRIBE command to add the specified mailbox name to
- the server's set of "active" or "subscribed" mailboxes.
-
-: unsubscribe(mailbox)
- Sends a UNSUBSCRIBE command to remove the specified mailbox name
- from the server's set of "active" or "subscribed" mailboxes.
-
-: list(refname, mailbox)
- Sends a LIST command, and returns a subset of names from
- the complete set of all names available to the client.
- The return value is an array of ((<Net::IMAP::MailboxList>)).
-
- ex).
- imap.create("foo/bar")
- imap.create("foo/baz")
- p imap.list("", "foo/%")
- #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
-
-: lsub(refname, mailbox)
- 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".
- The return value is an array of ((<Net::IMAP::MailboxList>)).
-
-: status(mailbox, attr)
- Sends a STATUS command, and returns the status of the indicated
- mailbox.
- The return value is a hash of attributes.
-
- ex).
- p imap.status("inbox", ["MESSAGES", "RECENT"])
- #=> {"RECENT"=>0, "MESSAGES"=>44}
-
-: append(mailbox, message, flags = nil, date_time = nil)
- Sends a APPEND command to append the message to the end of
- the mailbox.
-
- ex).
- imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
- Subject: hello
- From: shugo@ruby-lang.org
- To: shugo@ruby-lang.org
-
- hello world
- EOF
-
-: check
- Sends a CHECK command to request a checkpoint of the currently
- selected mailbox.
-
-: close
- Sends a CLOSE command to close the currently selected mailbox.
- The CLOSE command permanently removes from the mailbox all
- messages that have the \Deleted flag set.
-
-: expunge
- Sends a EXPUNGE command to permanently remove from the currently
- selected mailbox all messages that have the \Deleted flag set.
-
-: search(keys, charset = nil)
-: uid_search(keys, charset = nil)
- Sends a SEARCH command to search the mailbox for messages that
- match the given searching criteria, and returns message sequence
- numbers (search) or unique identifiers (uid_search).
-
- ex).
- p imap.search(["SUBJECT", "hello"])
- #=> [1, 6, 7, 8]
- p imap.search('SUBJECT "hello"')
- #=> [1, 6, 7, 8]
-
-: fetch(set, attr)
-: uid_fetch(set, attr)
- Sends a FETCH command to retrieve data associated with a message
- in the mailbox. the set parameter is a number or an array of
- numbers or a Range object. the number is a message sequence
- number (fetch) or a unique identifier (uid_fetch).
- The return value is an array of ((<Net::IMAP::FetchData>)).
-
- ex).
- p imap.fetch(6..8, "UID")
- #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, #<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
- p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
- #=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
- data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0]
- p data.seqno
- #=> 6
- p data.attr["RFC822.SIZE"]
- #=> 611
- p data.attr["INTERNALDATE"]
- #=> "12-Oct-2000 22:40:59 +0900"
- p data.attr["UID"]
- #=> 98
-
-: store(set, attr, flags)
-: uid_store(set, attr, flags)
- Sends a STORE command to alter data associated with a message
- in the mailbox. the set parameter is a number or an array of
- numbers or a Range object. the number is a message sequence
- number (store) or a unique identifier (uid_store).
- The return value is an array of ((<Net::IMAP::FetchData>)).
-
- ex).
- p imap.store(6..8, "+FLAGS", [:Deleted])
- #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
-
-: copy(set, mailbox)
-: uid_copy(set, mailbox)
- Sends a COPY command to copy the specified message(s) to the end
- of the specified destination mailbox. the set parameter is
- a number or an array of numbers or a Range object. the number is
- a message sequence number (copy) or a unique identifier (uid_copy).
-
-: sort(sort_keys, search_keys, charset)
-: uid_sort(sort_keys, search_keys, charset)
- Sends a SORT command to sort messages in the mailbox.
-
- ex).
- 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]
-
-: setquota(mailbox, quota)
- 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 server admin
- for this to work. The IMAP quota commands are described in
- ((<[RFC-2087]>)).
-
-: getquota(mailbox)
- 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 generally is only available to server admin.
-
-: getquotaroot(mailbox)
- Sends the GETQUOTAROOT command along with specified mailbox.
- This command is generally available to both admin and user.
- If mailbox exists, returns an array containing objects of
- ((<Net::IMAP::MailboxQuotaRoot>)) and ((<Net::IMAP::MailboxQuota>)).
-
-: setacl(mailbox, user, rights)
- 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]>)).
-
-: getacl(mailbox)
- Send the GETACL command along with specified mailbox.
- If this mailbox exists, an array containing objects of
- ((<Net::IMAP::MailboxACLItem>)) will be returned.
-
-: add_response_handler(handler = Proc.new)
- Adds a response handler.
-
- ex).
- imap.add_response_handler do |resp|
- p resp
- end
-
-: remove_response_handler(handler)
- Removes the response handler.
-
-: response_handlers
- Returns all response handlers.
-
-== Net::IMAP::ContinuationRequest
-
-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.
-
- continue_req ::= "+" SPACE (resp_text / base64)
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: data
- Returns the data (Net::IMAP::ResponseText).
-
-: raw_data
- Returns the raw data string.
-
-== Net::IMAP::UntaggedResponse
-
-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.
-
- response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
- mailbox_data / message_data / capability_data)
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: name
- Returns the name such as "FLAGS", "LIST", "FETCH"....
-
-: data
- Returns the data such as an array of flag symbols,
- a ((<Net::IMAP::MailboxList>)) object....
-
-: raw_data
- Returns the raw data string.
-
-== Net::IMAP::TaggedResponse
-
-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.
-
- response_tagged ::= tag SPACE resp_cond_state CRLF
-
- tag ::= 1*<any ATOM_CHAR except "+">
-
- resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: tag
- Returns the tag.
-
-: name
- Returns the name. the name is one of "OK", "NO", "BAD".
-
-: data
- Returns the data. See ((<Net::IMAP::ResponseText>)).
-
-: raw_data
- Returns the raw data string.
-
-== Net::IMAP::ResponseText
-
-Net::IMAP::ResponseText represents texts of responses.
-The text may be prefixed by the response code.
-
- resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
- ;; text SHOULD NOT begin with "[" or "="
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: code
- Returns the response code. See ((<Net::IMAP::ResponseCode>)).
-
-: text
- Returns the text.
-
-== Net::IMAP::ResponseCode
-
-Net::IMAP::ResponseCode represents response codes.
-
- resp_text_code ::= "ALERT" / "PARSE" /
- "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
- "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
- "UIDVALIDITY" SPACE nz_number /
- "UNSEEN" SPACE nz_number /
- atom [SPACE 1*<any TEXT_CHAR except "]">]
-
-=== SuperClass
-
-Struct
-
-=== Methods
-
-: name
- Returns the name such as "ALERT", "PERMANENTFLAGS", "UIDVALIDITY"....
-
-: data
- Returns the data if it exists.
-
-== Net::IMAP::MailboxList
-
-Net::IMAP::MailboxList represents contents of the LIST response.
-
- mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
- "\Noselect" / "\Unmarked" / flag_extension) ")"
- SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: attr
- Returns the name attributes. Each name attribute is a symbol
- capitalized by String#capitalize, such as :Noselect (not :NoSelect).
-
-: delim
- Returns the hierarchy delimiter
-
-: name
- Returns the mailbox name.
-
-== Net::IMAP::MailboxQuota
-
-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).
-
- quota_list ::= "(" #quota_resource ")"
-
- quota_resource ::= atom SPACE number SPACE number
-
- quota_response ::= "QUOTA" SPACE astring SPACE quota_list
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: mailbox
- The mailbox with the associated quota.
-
-: usage
- Current storage usage of mailbox.
-
-: quota
- Quota limit imposed on mailbox.
-
-== Net::IMAP::MailboxQuotaRoot
-
-Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
-response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
-
- quotaroot_response
- ::= "QUOTAROOT" SPACE astring *(SPACE astring)
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: mailbox
- The mailbox with the associated quota.
-
-: quotaroots
- Zero or more quotaroots that effect the quota on the
- specified mailbox.
-
-== Net::IMAP::MailboxACLItem
-
-Net::IMAP::MailboxACLItem represents response from GETACL.
-
- acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE
- rights)
-
- identifier ::= astring
-
- rights ::= astring
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: user
- Login name that has certain rights to the mailbox
- that was specified with the getacl command.
-
-: rights
- The access rights the indicated user has to the
- mailbox.
-
-== Net::IMAP::StatusData
-
-Net::IMAP::StatusData represents contents of the STATUS response.
-
-=== Super Class
-
-Object
-
-=== Methods
-
-: mailbox
- Returns the mailbox name.
-
-: attr
- Returns a hash. Each key is one of "MESSAGES", "RECENT", "UIDNEXT",
- "UIDVALIDITY", "UNSEEN". Each value is a number.
-
-== Net::IMAP::FetchData
-
-Net::IMAP::FetchData represents contents of the FETCH response.
-
-=== Super Class
-
-Object
-
-=== Methods
-
-: seqno
- Returns the message sequence number.
- (Note: not the unique identifier, even for the UID command response.)
-
-: attr
- Returns a hash. Each key is a data item name, and each value is
- its value.
-
- The current data items are:
-
- : BODY
- A form of BODYSTRUCTURE without extension data.
- : BODY[<section>]<<origin_octet>>
- A string expressing the body contents of the specified section.
- : BODYSTRUCTURE
- An object that describes the ((<[MIME-IMB]>)) body structure of a message.
- See ((<Net::IMAP::BodyTypeBasic>)), ((<Net::IMAP::BodyTypeText>)),
- ((<Net::IMAP::BodyTypeMessage>)), ((<Net::IMAP::BodyTypeMultipart>)).
- : ENVELOPE
- A ((<Net::IMAP::Envelope>)) object that describes the envelope
- structure of a message.
- : FLAGS
- A array of flag symbols that are set for this message. flag symbols
- are capitalized by String#capitalize.
- : INTERNALDATE
- A string representing the internal date of the message.
- : RFC822
- Equivalent to BODY[].
- : RFC822.HEADER
- Equivalent to BODY.PEEK[HEADER].
- : RFC822.SIZE
- A number expressing the ((<[RFC-822]>)) size of the message.
- : RFC822.TEXT
- Equivalent to BODY[TEXT].
- : UID
- A number expressing the unique identifier of the message.
-
-== Net::IMAP::Envelope
-
-Net::IMAP::Envelope represents envelope structures of messages.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: date
- Retunns a string that represents the date.
-
-: subject
- Retunns a string that represents the subject.
-
-: from
- Retunns an array of ((<Net::IMAP::Address>)) that represents the from.
-
-: sender
- Retunns an array of ((<Net::IMAP::Address>)) that represents the sender.
-
-: reply_to
- Retunns an array of ((<Net::IMAP::Address>)) that represents the reply-to.
-
-: to
- Retunns an array of ((<Net::IMAP::Address>)) that represents the to.
-
-: cc
- Retunns an array of ((<Net::IMAP::Address>)) that represents the cc.
-
-: bcc
- Retunns an array of ((<Net::IMAP::Address>)) that represents the bcc.
-
-: in_reply_to
- Retunns a string that represents the in-reply-to.
-
-: message_id
- Retunns a string that represents the message-id.
-
-== Net::IMAP::Address
-
-((<Net::IMAP::Address>)) represents electronic mail addresses.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: name
- Returns the phrase from ((<[RFC-822]>)) mailbox.
-
-: route
- Returns the route from ((<[RFC-822]>)) route-addr.
-
-: mailbox
- nil indicates end of ((<[RFC-822]>)) group.
- If non-nil and host is nil, returns ((<[RFC-822]>)) group name.
- Otherwise, returns ((<[RFC-822]>)) local-part
-
-: host
- nil indicates ((<[RFC-822]>)) group syntax.
- Otherwise, returns ((<[RFC-822]>)) domain name.
-
-== Net::IMAP::ContentDisposition
-
-Net::IMAP::ContentDisposition represents Content-Disposition fields.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: dsp_type
- Returns the disposition type.
-
-: param
- Returns a hash that represents parameters of the Content-Disposition
- field.
-
-== Net::IMAP::BodyTypeBasic
-
-Net::IMAP::BodyTypeBasic represents basic body structures of messages.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: media_type
- Returns the content media type name as defined in ((<[MIME-IMB]>)).
-
-: subtype
- Returns the content subtype name as defined in ((<[MIME-IMB]>)).
-
-: param
- Returns a hash that represents parameters as defined in
- ((<[MIME-IMB]>)).
-
-: content_id
- Returns a string giving the content id as defined in ((<[MIME-IMB]>)).
-
-: description
- Returns a string giving the content description as defined in
- ((<[MIME-IMB]>)).
-
-: encoding
- Returns a string giving the content transfer encoding as defined in
- ((<[MIME-IMB]>)).
-
-: size
- Returns a number giving the size of the body in octets.
-
-: md5
- Returns a string giving the body MD5 value as defined in ((<[MD5]>)).
-
-: disposition
- Returns a ((<Net::IMAP::ContentDisposition>)) object giving
- the content disposition.
-
-: language
- Returns a string or an array of strings giving the body
- language value as defined in [LANGUAGE-TAGS].
-
-: extension
- Returns extension data.
-
-: multipart?
- Returns false.
-
-== Net::IMAP::BodyTypeText
-
-Net::IMAP::BodyTypeText represents TEXT body structures of messages.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: lines
- Returns the size of the body in text lines.
-
-And Net::IMAP::BodyTypeText has all methods of ((<Net::IMAP::BodyTypeBasic>)).
-
-== Net::IMAP::BodyTypeMessage
-
-Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: envelope
- Returns a ((<Net::IMAP::Envelope>)) giving the envelope structure.
-
-: body
- Returns an object giving the body structure.
-
-And Net::IMAP::BodyTypeMessage has all methods of ((<Net::IMAP::BodyTypeText>)).
-
-== Net::IMAP::BodyTypeText
-
-=== Super Class
-
-Struct
-
-=== Methods
-
-: media_type
- Returns the content media type name as defined in ((<[MIME-IMB]>)).
-
-: subtype
- Returns the content subtype name as defined in ((<[MIME-IMB]>)).
-
-: parts
- Returns multiple parts.
-
-: param
- Returns a hash that represents parameters as defined in
- ((<[MIME-IMB]>)).
-
-: disposition
- Returns a ((<Net::IMAP::ContentDisposition>)) object giving
- the content disposition.
-
-: language
- Returns a string or an array of strings giving the body
- language value as defined in [LANGUAGE-TAGS].
-
-: extension
- Returns extension data.
-
-: multipart?
- Returns true.
-
-== References
-
-: [IMAP]
- M. Crispin, "INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1",
- RFC 2060, December 1996.
-
-: [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.
-
-: [OSSL]
- http://www.openssl.org
-
-: [RSSL]
- http://savannah.gnu.org/projects/rubypki
-
-=end
+# = net/imap.rb
+#
+#--
+# Copyright (C) 2000 Shugo Maeda <shugo@ruby-lang.org>
+#
+# This library is distributed under the terms of the Ruby license.
+# You can freely distribute/modify this library.
+#++
+#
+# Client functionality for the IMAP mail protocol.
+# See the Net::IMAP class for details and examples of use.
+#
+# == 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.
+#
+# [[SORT-THREAD-EXT]]
+# Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - SORT and THREAD
+# Extensions", draft-ietf-imapext-sort, May 2003.
+#
+# [[OSSL]]
+# http://www.openssl.org
+#
+# [[RSSL]]
+# http://savannah.gnu.org/projects/rubypki
require "socket"
require "monitor"
@@ -811,6 +58,132 @@ rescue LoadError
end
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
+ # contains zero or more messages. How this is implemented on
+ # the server is implementation-dependent; on a UNIX server, it
+ # will frequently be implemented as a files in mailbox format
+ # 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.
+ #
+ # Messages have two sorts of identifiers: message sequence
+ # numbers, and UIDs.
+ #
+ # Message sequence numbers number messages within a mail box
+ # from 1 up to the number of items in the mail box. If new
+ # message arrives during a session, it receives a sequence
+ # number equal to the new size of the mail box. If messages
+ # are expunged from the mailbox, remaining messages have their
+ # sequence numbers "shuffled down" to fill the gaps.
+ #
+ # 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
+ # UIDs have to be reassigned. An IMAP client cannot thus
+ # rearrange message orders.
+ #
+ # == EXAMPLES OF USAGE
+ #
+ # === List sender and subject of all recent messages in the default mailbox
+ #
+ # imap = Net::IMAP.new('mail.example.com', 143)
+ # imap.authenticate('LOGIN', 'joe_user', 'joes_password')
+ # imap.examine('INBOX')
+ # imap.search(["RECENT"]).each do |message_id|
+ # envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
+ # puts "#{envelope.from[0].name}: \t#{envelope.subject}"
+ # end
+ #
+ # === Move all messages from April 2003 from "Mail/sent-mail" to "Mail/sent-apr03"
+ #
+ # imap = Net::IMAP.new('mail.example.com', 143)
+ # imap.authenticate('LOGIN', 'joe_user', 'joes_password')
+ # imap.select('Mail/sent-mail')
+ # if not imap.list('Mail/', 'sent-apr03')
+ # imap.create('Mail/sent-apr03')
+ # end
+ # imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
+ # imap.copy(message_id, "Mail/sent-apr03")
+ # imap.store(message_id, "+FLAGS", [:Deleted])
+ # end
+ # imap.expunge
+ #
+ # == THREAD-SAFENESS
+ #
+ # Net::IMAP supports concurrent threads. For example,
+ #
+ # imap = Net::IMAP.new("imap.foo.net", "imap2")
+ # imap.authenticate("cram-md5", "bar", "password")
+ # imap.select("inbox")
+ # fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
+ # search_result = imap.search(["BODY", "hello"])
+ # fetch_result = fetch_thread.value
+ # imap.disconnect
+ #
+ # This script invokes the FETCH command and the SEARCH command concurrently.
+ #
+ # == ERRORS
+ #
+ # An IMAP server can send three different types of responses to indicate
+ # failure:
+ #
+ # NO:: the attempted command could not be successfully completed. For
+ # instance, the username/password used for logging in are incorrect;
+ # the selected mailbox does not exists; etc.
+ #
+ # BAD:: the request from the client does not follow the server's
+ # 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
+ # failure (such as a disk crash) has occurred.
+ #
+ # BYE:: the server is saying goodbye. This can be part of a normal
+ # logout sequence, and can be used as part of a login sequence
+ # to indicate that the server is (for some reason) unwilling
+ # to accept our connection. As a response to any other command,
+ # it indicates either that the server is shutting down, or that
+ # the server is timing out the client connection due to inactivity.
+ #
+ # These three error response are represented by the errors
+ # Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and
+ # Net::IMAP::ByeResponseError, all of which are subclasses of
+ # Net::IMAP::ResponseError. Essentially, all methods that involve
+ # sending a request to the server can generate one of these errors.
+ # Only the most pertinent instances have been documented below.
+ #
+ # Because the IMAP class uses Sockets for communication, its methods
+ # are also susceptible to the various errors that can occur when
+ # working with sockets. These are generally represented as
+ # Errno errors. For instance, any method that involves sending a
+ # request to the server and/or receiving a response from it could
+ # raise an Errno::EPIPE error if the network connection unexpectedly
+ # goes down. See the socket(7), ip(7), tcp(7), socket(2), connect(2),
+ # and associated man pages.
+ #
+ # Finally, a Net::IMAP::DataFormatError is thrown if low-level data
+ # is found to be in an incorrect format (for instance, when converting
+ # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
+ # thrown if a server response is non-parseable.
+ #
class IMAP
include MonitorMixin
if defined?(OpenSSL)
@@ -818,38 +191,82 @@ module Net
include SSL
end
- attr_reader :greeting, :responses, :response_handlers
+ # Returns an initial greeting response from the server.
+ attr_reader :greeting
+
+ # Returns recorded untagged responses. For example:
+ #
+ # imap.select("inbox")
+ # p imap.responses["EXISTS"][-1]
+ # #=> 2
+ # p imap.responses["UIDVALIDITY"][-1]
+ # #=> 968263756
+ attr_reader :responses
+ # Returns all response handlers.
+ attr_reader :response_handlers
+
+ # 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
+ # Returns the debug mode.
def self.debug
return @@debug
end
+ # Sets the debug mode.
def self.debug=(val)
return @@debug = val
end
+ # Adds an authenticator for Net::IMAP#authenticate.
def self.add_authenticator(auth_type, authenticator)
@@authenticators[auth_type] = authenticator
end
+ # Disconnects from the server.
def disconnect
@sock.shutdown unless @usessl
@receiver_thread.join
@sock.close
end
+ # Sends a CAPABILITY command, and returns a listing of
+ # capabilities that the server supports.
def capability
synchronize do
send_command("CAPABILITY")
@@ -857,14 +274,25 @@ module Net
end
end
+ # Sends a NOOP command to the server. It does nothing.
def noop
send_command("NOOP")
end
+ # Sends a LOGOUT command to inform the server that the client is
+ # done with the connection.
def logout
send_command("LOGOUT")
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 "LOGIN" and "CRAM-MD5" for the +auth_type+. For example:
+ #
+ # imap.authenticate('LOGIN', user, password)
+ #
+ # A Net::IMAP::NoResponseError is raised if authentication fails.
def authenticate(auth_type, *args)
auth_type = auth_type.upcase
unless @@authenticators.has_key?(auth_type)
@@ -880,10 +308,26 @@ module Net
end
end
+ # Sends a LOGIN command to identify the client and carries
+ # the plaintext +password+ authenticating this +user+.
+ #
+ # A Net::IMAP::NoResponseError is raised if authentication fails.
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.
+ #
+ # After you have selected a mailbox, you may retrieve the
+ # 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
+ # exist or is for some reason non-selectable.
def select(mailbox)
synchronize do
@responses.clear
@@ -891,6 +335,12 @@ module Net
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.
+ #
+ # A Net::IMAP::NoResponseError is raised if the mailbox does not
+ # exist or is for some reason non-examinable.
def examine(mailbox)
synchronize do
@responses.clear
@@ -898,26 +348,76 @@ module Net
end
end
+ # Sends a CREATE command to create a new +mailbox+.
+ #
+ # A Net::IMAP::NoResponseError is raised if a mailbox with that name
+ # cannot be created.
def create(mailbox)
send_command("CREATE", mailbox)
end
+ # Sends a DELETE command 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.
def delete(mailbox)
send_command("DELETE", mailbox)
end
+ # Sends a RENAME command 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+.
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().
+ #
+ # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
+ # subscribed to, for instance because it does not exist.
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.
+ #
+ # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
+ # unsubscribed from, for instance because the client is not currently
+ # subscribed to it.
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 wilcards) 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:
+ #
+ # imap.create("foo/bar")
+ # imap.create("foo/baz")
+ # p imap.list("", "foo/%")
+ # #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
def list(refname, mailbox)
synchronize do
send_command("LIST", refname, mailbox)
@@ -925,6 +425,10 @@ module Net
end
end
+ # Sends the GETQUOTAROOT command along with specified +mailbox+.
+ # This command is generally available to both admin and user.
+ # If mailbox exists, returns an array containing objects of
+ # Net::IMAP::MailboxQuotaRoot and Net::IMAP::MailboxQuota.
def getquotaroot(mailbox)
synchronize do
send_command("GETQUOTAROOT", mailbox)
@@ -935,6 +439,10 @@ module Net
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 generally is only available to server admin.
def getquota(mailbox)
synchronize do
send_command("GETQUOTA", mailbox)
@@ -942,7 +450,11 @@ module Net
end
end
- # setquota(mailbox, nil) will unset quota.
+ # 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 server admin
+ # for this to work. The IMAP quota commands are described in
+ # [RFC-2087].
def setquota(mailbox, quota)
if quota.nil?
data = '()'
@@ -952,7 +464,10 @@ module Net
send_command("SETQUOTA", mailbox, RawData.new(data))
end
- # setacl(mailbox, user, nil) will remove rights.
+ # 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, "")
@@ -961,6 +476,9 @@ module Net
end
end
+ # Send the GETACL command along with 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)
@@ -968,6 +486,11 @@ module Net
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().
+ # The return value is an array of +Net::IMAP::MailboxList+.
def lsub(refname, mailbox)
synchronize do
send_command("LSUB", refname, mailbox)
@@ -975,6 +498,22 @@ module Net
end
end
+ # Sends a STATUS command, and returns the status of the indicated
+ # +mailbox+. +attr+ is a list of one or more attributes that
+ # we are request the status of. Supported attributes include:
+ #
+ # MESSAGES:: the number of messages in the mailbox.
+ # RECENT:: the number of recent messages in the mailbox.
+ # UNSEEN:: the number of unseen messages in the mailbox.
+ #
+ # The return value is a hash of attributes. For example:
+ #
+ # p imap.status("inbox", ["MESSAGES", "RECENT"])
+ # #=> {"RECENT"=>0, "MESSAGES"=>44}
+ #
+ # A Net::IMAP::NoResponseError is raised if status values
+ # for +mailbox+ cannot be returned, for instance because it
+ # does not exist.
def status(mailbox, attr)
synchronize do
send_command("STATUS", mailbox, attr)
@@ -982,6 +521,24 @@ module Net
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 to initially assing 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", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
+ # Subject: hello
+ # From: shugo@ruby-lang.org
+ # To: shugo@ruby-lang.org
+ #
+ # hello world
+ # EOF
+ #
+ # A Net::IMAP::NoResponseError is raised if the mailbox does
+ # not exist (it is not created automatically), or if the flags,
+ # date_time, or message arguments contain errors.
def append(mailbox, message, flags = nil, date_time = nil)
args = []
if flags
@@ -992,14 +549,23 @@ module Net
send_command("APPEND", mailbox, *args)
end
+ # Sends a CHECK command to request a checkpoint of the currently
+ # selected mailbox. This performs implementation-specific
+ # housekeeping, for instance, reconciling the mailbox's
+ # in-memory and on-disk state.
def check
send_command("CHECK")
end
+ # Sends a CLOSE command to close the currently selected mailbox.
+ # The CLOSE command permanently removes from the mailbox all
+ # messages that have the \Deleted flag set.
def close
send_command("CLOSE")
end
+ # Sends a EXPUNGE command to permanently remove from the currently
+ # selected mailbox all messages that have the \Deleted flag set.
def expunge
synchronize do
send_command("EXPUNGE")
@@ -1007,60 +573,183 @@ module Net
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.
+ #
+ # <message set>:: 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 <date>:: messages with an internal date strictly before
+ # <date>. The date argument has a format similar
+ # to 8-Aug-2002.
+ #
+ # BODY <string>:: messages that contain <string> within their body.
+ #
+ # CC <string>:: messages containing <string> in their CC field.
+ #
+ # FROM <string>:: messages that contain <string> in their FROM field.
+ #
+ # NEW:: messages with the \Recent, but not the \Seen, flag set.
+ #
+ # NOT <search-key>:: negate the following search key.
+ #
+ # OR <search-key> <search-key>:: "or" two search keys together.
+ #
+ # ON <date>:: messages with an internal date exactly equal to <date>,
+ # which has a format similar to 8-Aug-2002.
+ #
+ # SINCE <date>:: messages with an internal date on or after <date>.
+ #
+ # SUBJECT <string>:: messages with <string> in their subject.
+ #
+ # TO <string>:: messages with <string> in their TO field.
+ #
+ # 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
+ # As for #search(), but returns unique identifiers.
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. The +set+ parameter is a number or an array of
+ # numbers or a Range object. The number is a message sequence
+ # number. +attr+ is a list of attributes to fetch; see the
+ # documentation for Net::IMAP::FetchData for a list of valid
+ # attributes.
+ # The return value is an array of Net::IMAP::FetchData. For example:
+ #
+ # p imap.fetch(6..8, "UID")
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
+ # #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\
+ # #<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
+ # p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
+ # data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0]
+ # p data.seqno
+ # #=> 6
+ # p data.attr["RFC822.SIZE"]
+ # #=> 611
+ # p data.attr["INTERNALDATE"]
+ # #=> "12-Oct-2000 22:40:59 +0900"
+ # p data.attr["UID"]
+ # #=> 98
def fetch(set, attr)
return fetch_internal("FETCH", set, attr)
end
+ # As for #fetch(), but +set+ contains unique identifiers.
def uid_fetch(set, attr)
return fetch_internal("UID FETCH", set, attr)
end
+ # Sends a STORE command to alter data associated with messages
+ # in the mailbox, in particular their flags. The +set+ parameter
+ # is a number or 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' means to replace the message's flag list
+ # with the provided one; '+FLAGS' means to add the provided flags;
+ # and '-FLAGS' means to remove them. +flags+ is a list of flags.
+ #
+ # The return value is an array of Net::IMAP::FetchData. For example:
+ #
+ # p imap.store(6..8, "+FLAGS", [:Deleted])
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
+ # #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>, \\
+ # #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
def store(set, attr, flags)
return store_internal("STORE", set, attr, flags)
end
+ # As for #store(), but +set+ contains unique identifiers.
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 or an array of numbers or a Range object. The number is
+ # a message sequence number.
def copy(set, mailbox)
copy_internal("COPY", set, mailbox)
end
+ # As for #copy(), but +set+ contains unique identifiers.
def uid_copy(set, mailbox)
copy_internal("UID COPY", set, mailbox)
end
+ # Sends a SORT command to sort messages in the mailbox.
+ # Returns an array of message sequence numbers. 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]
+ #
+ # See [SORT-THREAD-EXT] for more details.
def sort(sort_keys, search_keys, charset)
return sort_internal("SORT", sort_keys, search_keys, charset)
end
+ # As for #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
+ # Adds a response handler. For example, to detect when
+ # the server sends us a new EXISTS response (which normally
+ # indicates new messages being added to the mail box),
+ # you could 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 = Proc.new)
@response_handlers.push(handler)
end
+ # Removes the response handler.
def remove_response_handler(handler)
@response_handlers.delete(handler)
end
- def thread(argorithm, search_keys, charset)
- return thread_internal("THREAD", argorithm, search_keys, charset)
+ # As for #search(), but returns message sequence numbers in threaded
+ # format, as a Net::IMAP::ThreadMember tree. The supported algorithms
+ # are:
+ #
+ # ORDEREDSUBJECT:: split into single-level threads according to subject,
+ # ordered by date.
+ # 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
- def uid_thread(argorithm, search_keys, charset)
- return thread_internal("UID THREAD", argorithm, search_keys, charset)
+ # As for #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
def self.decode_utf7(s)
@@ -1097,6 +786,25 @@ module Net
@@debug = false
@@authenticators = {}
+ # Creates a new Net::IMAP object and connects it to the specified
+ # +port+ (143 by default) on the named +host+. If +usessl+ is true,
+ # then an attempt will
+ # be made to use SSL (now TLS) to connect to the server. For this
+ # to work OpenSSL [OSSL] and the Ruby OpenSSL [RSSL]
+ # extensions need to be installed. The +certs+ parameter indicates
+ # the path or file containing the CA cert of the server, and the
+ # +verify+ parameter is for the OpenSSL verification callback.
+ #
+ # The most common errors are:
+ #
+ # Errno::ECONNREFUSED:: connection refused by +host+ or an intervening
+ # firewall.
+ # Errno::ETIMEDOUT:: connection timed out (possibly due to packets
+ # being dropped by an intervening firewall).
+ # Errno::NETUNREACH:: there is no route to that network.
+ # SocketError:: hostname not known or other socket error.
+ # Net::IMAP::ByeResponseError:: we connected to the host, but they
+ # immediately said goodbye to us.
def initialize(host, port = PORT, usessl = false, certs = nil, verify = false)
super()
@host = host
@@ -1356,14 +1064,14 @@ module Net
end
end
- def thread_internal(cmd, argorithm, search_keys, charset)
+ def thread_internal(cmd, algorithm, search_keys, charset)
if search_keys.instance_of?(String)
search_keys = [RawData.new(search_keys)]
else
normalize_searching_criteria(search_keys)
end
normalize_searching_criteria(search_keys)
- send_command(cmd, argorithm, charset, *search_keys)
+ send_command(cmd, algorithm, charset, *search_keys)
return @responses.delete("THREAD")[-1]
end
@@ -1587,23 +1295,320 @@ module Net
end
end
+ # 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.
+ #
+ # continue_req ::= "+" SPACE (resp_text / base64)
+ #
+ # ==== Fields:
+ #
+ # 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.
+ #
+ # 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.
+ #
+ # response_data ::= "*" SPACE (resp_cond_state / resp_cond_bye /
+ # mailbox_data / message_data / capability_data)
+ #
+ # ==== Fields:
+ #
+ # name:: Returns the name such as "FLAGS", "LIST", "FETCH"....
+ #
+ # data:: Returns the data such as an array of flag symbols,
+ # a ((<Net::IMAP::MailboxList>)) object....
+ #
+ # raw_data:: Returns the raw data string.
UntaggedResponse = Struct.new(:name, :data, :raw_data)
+
+ # 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.
+ #
+ # response_tagged ::= tag SPACE resp_cond_state CRLF
+ #
+ # tag ::= 1*<any ATOM_CHAR except "+">
+ #
+ # resp_cond_state ::= ("OK" / "NO" / "BAD") SPACE resp_text
+ #
+ # ==== Fields:
+ #
+ # tag:: Returns the tag.
+ #
+ # name:: Returns the name. the name is one of "OK", "NO", "BAD".
+ #
+ # data:: Returns the data. See ((<Net::IMAP::ResponseText>)).
+ #
+ # 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.
+ #
+ # resp_text ::= ["[" resp_text_code "]" SPACE] (text_mime2 / text)
+ # ;; text SHOULD NOT begin with "[" or "="
+ #
+ # ==== Fields:
+ #
+ # code:: Returns the response code. See ((<Net::IMAP::ResponseCode>)).
+ #
+ # text:: Returns the text.
+ #
ResponseText = Struct.new(:code, :text)
+
+ #
+ # Net::IMAP::ResponseCode represents response codes.
+ #
+ # resp_text_code ::= "ALERT" / "PARSE" /
+ # "PERMANENTFLAGS" SPACE "(" #(flag / "\*") ")" /
+ # "READ-ONLY" / "READ-WRITE" / "TRYCREATE" /
+ # "UIDVALIDITY" SPACE nz_number /
+ # "UNSEEN" SPACE nz_number /
+ # atom [SPACE 1*<any TEXT_CHAR except "]">]
+ #
+ # ==== Fields:
+ #
+ # name:: Returns the name such as "ALERT", "PERMANENTFLAGS", "UIDVALIDITY"....
+ #
+ # data:: Returns the data if it exists.
+ #
ResponseCode = Struct.new(:name, :data)
+
+ # Net::IMAP::MailboxList represents contents of the LIST response.
+ #
+ # mailbox_list ::= "(" #("\Marked" / "\Noinferiors" /
+ # "\Noselect" / "\Unmarked" / flag_extension) ")"
+ # SPACE (<"> QUOTED_CHAR <"> / nil) SPACE mailbox
+ #
+ # ==== Fields:
+ #
+ # attr:: Returns the name attributes. Each name attribute is a symbol
+ # capitalized by String#capitalize, such as :Noselect (not :NoSelect).
+ #
+ # delim:: Returns the hierarchy delimiter
+ #
+ # 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
+ # specification below, the delimiter used with the "#" construct is a
+ # single space (SPACE).
+ #
+ # quota_list ::= "(" #quota_resource ")"
+ #
+ # quota_resource ::= atom SPACE number SPACE number
+ #
+ # quota_response ::= "QUOTA" SPACE astring SPACE quota_list
+ #
+ # ==== Fields:
+ #
+ # mailbox:: The mailbox with the associated quota.
+ #
+ # usage:: Current storage usage of mailbox.
+ #
+ # quota:: Quota limit imposed on mailbox.
+ #
MailboxQuota = Struct.new(:mailbox, :usage, :quota)
+
+ # Net::IMAP::MailboxQuotaRoot represents part of the GETQUOTAROOT
+ # response. (GETQUOTAROOT can also return Net::IMAP::MailboxQuota.)
+ #
+ # quotaroot_response ::= "QUOTAROOT" SPACE astring *(SPACE astring)
+ #
+ # ==== Fields:
+ #
+ # mailbox:: The mailbox with the associated quota.
+ #
+ # quotaroots:: Zero or more quotaroots that effect the quota on the
+ # specified mailbox.
+ #
MailboxQuotaRoot = Struct.new(:mailbox, :quotaroots)
+
+ # Net::IMAP::MailboxACLItem represents response from GETACL.
+ #
+ # acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE rights)
+ #
+ # identifier ::= astring
+ #
+ # rights ::= astring
+ #
+ # ==== Fields:
+ #
+ # user:: Login name that has certain rights to the mailbox
+ # that was specified with the getacl command.
+ #
+ # rights:: The access rights the indicated user has to the
+ # mailbox.
+ #
MailboxACLItem = Struct.new(:user, :rights)
+
+ # Net::IMAP::StatusData represents contents of the STATUS response.
+ #
+ # ==== Fields:
+ #
+ # mailbox:: Returns the mailbox name.
+ #
+ # 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 contents of the FETCH response.
+ #
+ # ==== Fields:
+ #
+ # seqno:: Returns the message sequence number.
+ # (Note: not the unique identifier, even for the UID command response.)
+ #
+ # attr:: Returns a hash. Each key is a data item name, and each value is
+ # its value.
+ #
+ # The current data items are:
+ #
+ # [BODY]
+ # A form of BODYSTRUCTURE without extension data.
+ # [BODY[<section>]<<origin_octet>>]
+ # A string expressing the body contents of the specified section.
+ # [BODYSTRUCTURE]
+ # An object that describes the [MIME-IMB] body structure of a message.
+ # See Net::IMAP::BodyTypeBasic, Net::IMAP::BodyTypeText,
+ # Net::IMAP::BodyTypeMessage, Net::IMAP::BodyTypeMultipart.
+ # [ENVELOPE]
+ # A Net::IMAP::Envelope object that describes the envelope
+ # structure of a message.
+ # [FLAGS]
+ # A array of flag symbols that are set for this message. flag symbols
+ # are capitalized by String#capitalize.
+ # [INTERNALDATE]
+ # A string representing the internal date of the message.
+ # [RFC822]
+ # Equivalent to BODY[].
+ # [RFC822.HEADER]
+ # Equivalent to BODY.PEEK[HEADER].
+ # [RFC822.SIZE]
+ # A number expressing the [RFC-822] size of the message.
+ # [RFC822.TEXT]
+ # Equivalent to BODY[TEXT].
+ # [UID]
+ # A number expressing the unique identifier of the message.
+ #
FetchData = Struct.new(:seqno, :attr)
+
+ # Net::IMAP::Envelope represents envelope structures of messages.
+ #
+ # ==== Fields:
+ #
+ # date:: Returns a string that represents the date.
+ #
+ # subject:: Returns a string that represents the subject.
+ #
+ # from:: Returns an array of Net::IMAP::Address that represents the from.
+ #
+ # sender:: Returns an array of Net::IMAP::Address that represents the sender.
+ #
+ # reply_to:: Returns an array of Net::IMAP::Address that represents the reply-to.
+ #
+ # to:: Returns an array of Net::IMAP::Address that represents the to.
+ #
+ # cc:: Returns an array of Net::IMAP::Address that represents the cc.
+ #
+ # bcc:: Returns an array of Net::IMAP::Address that represents the bcc.
+ #
+ # in_reply_to:: Returns a string that represents the in-reply-to.
+ #
+ # 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.
+ #
+ # ==== Fields:
+ #
+ # name:: Returns the phrase from [RFC-822] mailbox.
+ #
+ # route:: Returns the route from [RFC-822] route-addr.
+ #
+ # mailbox:: nil indicates end of [RFC-822] group.
+ # If non-nil and host is nil, returns [RFC-822] group name.
+ # Otherwise, returns [RFC-822] local-part
+ #
+ # 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.
+ #
+ # ==== Fields:
+ #
+ # dsp_type:: Returns the disposition type.
+ #
+ # 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
+ #
+ # ==== Fields:
+ #
+ # seqno:: The sequence number of this message.
+ #
+ # 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.
+ #
+ # ==== Fields:
+ #
+ # media_type:: Returns the content media type name as defined in [MIME-IMB].
+ #
+ # subtype:: Returns the content subtype name as defined in [MIME-IMB].
+ #
+ # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
+ #
+ # content_id:: Returns a string giving the content id as defined in [MIME-IMB].
+ #
+ # description:: Returns a string giving the content description as defined in
+ # [MIME-IMB].
+ #
+ # encoding:: Returns a string giving the content transfer encoding as defined in
+ # [MIME-IMB].
+ #
+ # size:: Returns a number giving the size of the body in octets.
+ #
+ # md5:: Returns a string giving the body MD5 value as defined in [MD5].
+ #
+ # disposition:: Returns a Net::IMAP::ContentDisposition object giving
+ # the content disposition.
+ #
+ # language:: Returns a string or an array of strings giving the body
+ # language value as defined in [LANGUAGE-TAGS].
+ #
+ # extension:: Returns extension data.
+ #
+ # multipart?:: Returns false.
+ #
class BodyTypeBasic < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
@@ -1613,6 +1618,9 @@ module Net
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
$stderr.printf("warning: media_subtype is obsolete.\n")
$stderr.printf(" use subtype instead.\n")
@@ -1620,6 +1628,14 @@ module Net
end
end
+ # Net::IMAP::BodyTypeText represents TEXT body structures of messages.
+ #
+ # ==== Fields:
+ #
+ # lines:: Returns the size of the body in text lines.
+ #
+ # And Net::IMAP::BodyTypeText has all fields of Net::IMAP::BodyTypeBasic.
+ #
class BodyTypeText < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
@@ -1630,6 +1646,9 @@ module Net
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
$stderr.printf("warning: media_subtype is obsolete.\n")
$stderr.printf(" use subtype instead.\n")
@@ -1637,6 +1656,16 @@ module Net
end
end
+ # Net::IMAP::BodyTypeMessage represents MESSAGE/RFC822 body structures of messages.
+ #
+ # ==== Fields:
+ #
+ # envelope:: Returns a Net::IMAP::Envelope giving the envelope structure.
+ #
+ # body:: Returns an object giving the body structure.
+ #
+ # And Net::IMAP::BodyTypeMessage has all methods of Net::IMAP::BodyTypeText.
+ #
class BodyTypeMessage < Struct.new(:media_type, :subtype,
:param, :content_id,
:description, :encoding, :size,
@@ -1647,6 +1676,9 @@ module Net
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
$stderr.printf("warning: media_subtype is obsolete.\n")
$stderr.printf(" use subtype instead.\n")
@@ -1654,6 +1686,29 @@ module Net
end
end
+ # Net::IMAP::BodyTypeMultipart represents multipart body structures
+ # of messages.
+ #
+ # ==== Fields:
+ #
+ # media_type:: Returns the content media type name as defined in [MIME-IMB].
+ #
+ # subtype:: Returns the content subtype name as defined in [MIME-IMB].
+ #
+ # parts:: Returns multiple parts.
+ #
+ # param:: Returns a hash that represents parameters as defined in [MIME-IMB].
+ #
+ # disposition:: Returns a Net::IMAP::ContentDisposition object giving
+ # the content disposition.
+ #
+ # language:: Returns a string or an array of strings giving the body
+ # language value as defined in [LANGUAGE-TAGS].
+ #
+ # extension:: Returns extension data.
+ #
+ # multipart?:: Returns true.
+ #
class BodyTypeMultipart < Struct.new(:media_type, :subtype,
:parts,
:param, :disposition, :language,
@@ -1662,6 +1717,9 @@ module Net
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
$stderr.printf("warning: media_subtype is obsolete.\n")
$stderr.printf(" use subtype instead.\n")
@@ -2970,6 +3028,7 @@ module Net
end
if __FILE__ == $0
+ # :enddoc:
require "getoptlong"
$stdout.sync = true