Skip to content

Commit 2e0b2e9

Browse files
committed
📚 Update QUOTA rdoc, params, attrs to match RFCs
This updates quota docs with references to RFC9208 (`QUOTA=RES-*`). For the most part, RFC9208 is backward compatible with RFC2087. This updates the documentation to include RFC9208 wherever relevant. This also documents how `net-imap`'s support for `QUOTA` is incomplete: that it only supports setting `STORAGE` and can only parse a single resource type (which is _usually_ `STORAGE`). The RFCs are very clear that `quota root` is _not_ the same as `mailbox`, so this updates method parameters and rdoc to reflect that. `MailboxQuota#mailbox` is incorrectly named, but renaming it would be backward incompatible. This just updates the documentation and adds `quota_root` as an alias. This also fixes the rdoc for `MailboxQuota#quota` to specify that it is the _storage_ limit, rather than any other quota resource type. This adds a note in the rdoc that _only_ `STORAGE` is currently supported. `GETQUOTA` generally _is_ available to normal users. That commant on `#getquota` may have been copied from `SETQUOTA`.
1 parent 6546305 commit 2e0b2e9

File tree

2 files changed

+86
-30
lines changed

2 files changed

+86
-30
lines changed

lib/net/imap.rb

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,8 @@ module Net
462462
# +LITERAL-+, and +SPECIAL-USE+.</em>
463463
#
464464
# ==== RFC2087: +QUOTA+
465+
# - Obsoleted by <tt>QUOTA=RES-*</tt> [RFC9208[https://www.rfc-editor.org/rfc/rfc9208]],
466+
# although the commands are backward compatible.
465467
# - #getquota: returns the resource usage and limits for a quota root
466468
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
467469
# their resource usage and limits.
@@ -576,6 +578,15 @@ module Net
576578
# See FetchData#emailid and FetchData#emailid.
577579
# - Updates #status with support for the +MAILBOXID+ status attribute.
578580
#
581+
# ==== RFC9208: <tt>QUOTA=RES-*</tt>
582+
# - Obsoletes the +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
583+
# extension and provides strict semantics for different resource types.
584+
# - #getquota: returns the resource usage and limits for a quota root
585+
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
586+
# their resource usage and limits.
587+
# - #setquota: sets the resource limits for a given quota root.
588+
# - Updates #status with <tt>"DELETED"</tt> and +DELETED-STORAGE+ attributes.
589+
#
579590
# ==== RFC9394: +PARTIAL+
580591
# - Updates #search, #uid_search with the +PARTIAL+ return option which adds
581592
# ESearchResult#partial return data.
@@ -696,13 +707,12 @@ module Net
696707
#
697708
# === \IMAP Extensions
698709
#
699-
# [QUOTA[https://www.rfc-editor.org/rfc/rfc9208]]::
700-
# Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
701-
# March 2022, <https://www.rfc-editor.org/info/rfc9208>.
710+
# [QUOTA[https://www.rfc-editor.org/rfc/rfc2087]]::
711+
# Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087,
712+
# January 1997, <https://www.rfc-editor.org/info/rfc2087>.
702713
#
703-
# <em>Note: obsoletes</em>
704-
# RFC-2087[https://www.rfc-editor.org/rfc/rfc2087]<em> (January 1997)</em>.
705-
# <em>Net::IMAP does not fully support the RFC9208 updates yet.</em>
714+
# *NOTE*: _obsoleted_ by RFC9208[https://www.rfc-editor.org/rfc/rfc9208]
715+
# (March 2022).
706716
# [IDLE[https://www.rfc-editor.org/rfc/rfc2177]]::
707717
# Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
708718
# June 1997, <https://www.rfc-editor.org/info/rfc2177>.
@@ -754,6 +764,11 @@ module Net
754764
# Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
755765
# RFC 8474, DOI 10.17487/RFC8474, September 2018,
756766
# <https://www.rfc-editor.org/info/rfc8474>.
767+
# [{QUOTA=RES-*}[https://www.rfc-editor.org/rfc/rfc9208]]::
768+
# Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
769+
# March 2022, <https://www.rfc-editor.org/info/rfc9208>.
770+
#
771+
# Obsoletes RFC2087[https://www.rfc-editor.org/rfc/rfc2087].
757772
# [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
758773
# Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
759774
# "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
@@ -767,6 +782,7 @@ module Net
767782
#
768783
# === IANA registries
769784
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
785+
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
770786
# * {IMAP Response Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
771787
# * {IMAP Mailbox Name Attributes}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
772788
# * {IMAP and JMAP Keywords}[https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml]
@@ -777,8 +793,8 @@ module Net
777793
# * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
778794
# +imap+
779795
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
796+
#
780797
# ==== For currently unsupported features:
781-
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
782798
# * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
783799
# * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
784800
# * {IMAP ANNOTATE Extension Entries and Attributes}[https://www.iana.org/assignments/imap-annotate-extension/imap-annotate-extension.xhtml]
@@ -1848,12 +1864,18 @@ def xlist(refname, mailbox)
18481864
# to both admin and user. If this mailbox exists, it returns an array
18491865
# containing objects of type MailboxQuotaRoot and MailboxQuota.
18501866
#
1867+
# *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
1868+
# resource type. This is usually +STORAGE+, but you may need to verify this
1869+
# with UntaggedResponse#raw_data.
1870+
#
18511871
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
18521872
#
18531873
# ==== Capabilities
18541874
#
1855-
# The server's capabilities must include +QUOTA+
1856-
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1875+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1876+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1877+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1878+
# resource type.
18571879
def getquotaroot(mailbox)
18581880
synchronize do
18591881
send_command("GETQUOTAROOT", mailbox)
@@ -1865,41 +1887,55 @@ def getquotaroot(mailbox)
18651887
end
18661888

18671889
# Sends a {GETQUOTA command [RFC2087 §4.2]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.2]
1868-
# along with specified +mailbox+. If this mailbox exists, then an array
1869-
# containing a MailboxQuota object is returned. This command is generally
1870-
# only available to server admin.
1890+
# for the +quota_root+. If this quota root exists, then an array
1891+
# containing a MailboxQuota object is returned.
1892+
#
1893+
# The names of quota roots that are applicable to a particular mailbox can
1894+
# be discovered with #getquotaroot.
1895+
#
1896+
# *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
1897+
# resource type. This is usually +STORAGE+, but you may need to verify this
1898+
# with UntaggedResponse#raw_data.
18711899
#
18721900
# Related: #getquotaroot, #setquota, MailboxQuota
18731901
#
18741902
# ==== Capabilities
18751903
#
1876-
# The server's capabilities must include +QUOTA+
1877-
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1878-
def getquota(mailbox)
1904+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1905+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1906+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1907+
# resource type.
1908+
def getquota(quota_root)
18791909
synchronize do
1880-
send_command("GETQUOTA", mailbox)
1910+
send_command("GETQUOTA", quota_root)
18811911
clear_responses("QUOTA")
18821912
end
18831913
end
18841914

18851915
# Sends a {SETQUOTA command [RFC2087 §4.1]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.1]
1886-
# along with the specified +mailbox+ and +quota+. If +quota+ is nil, then
1887-
# +quota+ will be unset for that mailbox. Typically one needs to be logged
1888-
# in as a server admin for this to work.
1916+
# along with the specified +quota_root+ and +storage_limit+. If
1917+
# +storage_limit+ is +nil+, resource limits are unset for that quota root.
1918+
# Otherwise, it sets the +STORAGE+ resource limit.
1919+
#
1920+
# Typically one needs to be logged in as a server admin for this to work.
1921+
#
1922+
# *NOTE:* Currently, Net::IMAP only supports setting +STORAGE+ quota limits.
18891923
#
18901924
# Related: #getquota, #getquotaroot
18911925
#
18921926
# ==== Capabilities
18931927
#
1894-
# The server's capabilities must include +QUOTA+
1895-
# [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]].
1896-
def setquota(mailbox, quota)
1897-
if quota.nil?
1898-
data = '()'
1928+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1929+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1930+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1931+
# resource type.
1932+
def setquota(quota_root, storage_limit)
1933+
if storage_limit.nil?
1934+
list = '()'
18991935
else
1900-
data = '(STORAGE ' + quota.to_s + ')'
1936+
list = '(STORAGE ' + storage_limit.to_s + ')'
19011937
end
1902-
send_command("SETQUOTA", mailbox, RawData.new(data))
1938+
send_command("SETQUOTA", quota_root, RawData.new(list))
19031939
end
19041940

19051941
# Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
@@ -2006,7 +2042,10 @@ def lsub(refname, mailbox)
20062042
# <tt>STATUS=SIZE</tt>
20072043
# {[RFC8483]}[https://www.rfc-editor.org/rfc/rfc8483.html].
20082044
#
2009-
# +DELETED+ requires the server's capabilities to include +IMAP4rev2+.
2045+
# +DELETED+ must be supported when the server's capabilities includes
2046+
# +IMAP4rev2+.
2047+
# or <tt>QUOTA=RES-MESSAGES</tt>
2048+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208.html].
20102049
#
20112050
# +HIGHESTMODSEQ+ requires the server's capabilities to include +CONDSTORE+
20122051
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].

lib/net/imap/response_data.rb

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,14 @@ class ResponseText < Struct.new(:code, :text)
380380
# because the server doesn't allow deletion of mailboxes with children.
381381
# #data is +nil+.
382382
#
383+
# === <tt>QUOTA=RES-*</tt> response codes
384+
# See {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208.html#section-4.3].
385+
# * +OVERQUOTA+ (also in RFC5530[https://www.rfc-editor.org/rfc/rfc5530]),
386+
# with a tagged +NO+ response to an +APPEND+/+COPY+/+MOVE+ command when
387+
# the command would put the target mailbox over any quota, and with an
388+
# untagged +NO+ when a mailbox exceeds a soft quota (which may be caused
389+
# be external events). #data is +nil+.
390+
#
383391
# === +CONDSTORE+ extension
384392
# See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
385393
# * +NOMODSEQ+, when selecting a mailbox that does not support
@@ -463,14 +471,23 @@ class MailboxList < Struct.new(:attr, :delim, :name)
463471
# and MailboxQuota objects.
464472
#
465473
# == Required capability
474+
#
466475
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
467-
# capability.
476+
# or <tt>QUOTA=RES-STORAGE</tt>
477+
# [RFC9208[https://www.rfc-editor.org/rfc/rfc9208]] capability.
468478
class MailboxQuota < Struct.new(:mailbox, :usage, :quota)
469479
##
470480
# method: mailbox
471481
# :call-seq: mailbox -> string
472482
#
473-
# The mailbox with the associated quota.
483+
# The quota root with the associated quota.
484+
#
485+
# NOTE: this was mistakenly named "mailbox". But the quota root's name may
486+
# differ from the mailbox. A single quota root may cover multiple
487+
# mailboxes, and a single mailbox may be governed by multiple quota roots.
488+
489+
# The quota root with the associated quota.
490+
alias quota_root mailbox
474491

475492
##
476493
# method: usage
@@ -482,7 +499,7 @@ class MailboxQuota < Struct.new(:mailbox, :usage, :quota)
482499
# method: quota
483500
# :call-seq: quota -> Integer
484501
#
485-
# Quota limit imposed on the mailbox.
502+
# Storage limit imposed on the mailbox.
486503
#
487504
end
488505

0 commit comments

Comments
 (0)