net-imap 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.document +3 -0
- data/.rdoc_options +7 -0
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/lib/net/imap/command_data.rb +170 -12
- data/lib/net/imap/config.rb +34 -0
- data/lib/net/imap/data_encoding.rb +50 -0
- data/lib/net/imap/errors.rb +47 -10
- data/lib/net/imap/response_data.rb +108 -11
- data/lib/net/imap/response_parser.rb +13 -0
- data/lib/net/imap/response_reader.rb +25 -16
- data/lib/net/imap/sasl/scram_authenticator.rb +74 -0
- data/lib/net/imap/search_result.rb +5 -1
- data/lib/net/imap.rb +167 -61
- data/rakelib/rdoc.rake +1 -18
- metadata +4 -2
data/lib/net/imap.rb
CHANGED
|
@@ -450,8 +450,8 @@ module Net
|
|
|
450
450
|
#
|
|
451
451
|
# Although IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] is not supported
|
|
452
452
|
# yet, Net::IMAP supports several extensions that have been folded into it:
|
|
453
|
-
# +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+,
|
|
454
|
-
# <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
|
|
453
|
+
# +ENABLE+, +IDLE+, +LITERAL-+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+,
|
|
454
|
+
# +UNSELECT+, <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
|
|
455
455
|
# Commands for these extensions are listed with the {Core IMAP
|
|
456
456
|
# commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above.
|
|
457
457
|
#
|
|
@@ -459,9 +459,12 @@ module Net
|
|
|
459
459
|
# <em>The following are folded into +IMAP4rev2+ but are currently
|
|
460
460
|
# unsupported or incompletely supported by</em> Net::IMAP<em>: RFC4466
|
|
461
461
|
# extensions, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
|
|
462
|
-
#
|
|
462
|
+
# and +SPECIAL-USE+.</em>
|
|
463
463
|
#
|
|
464
464
|
# ==== RFC2087: +QUOTA+
|
|
465
|
+
# +NOTE:+ Only the +STORAGE+ quota resource type is currently supported.
|
|
466
|
+
# - Obsoleted by <tt>QUOTA=RES-*</tt> [RFC9208[https://www.rfc-editor.org/rfc/rfc9208]],
|
|
467
|
+
# although the commands are backward compatible.
|
|
465
468
|
# - #getquota: returns the resource usage and limits for a quota root
|
|
466
469
|
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
|
|
467
470
|
# their resource usage and limits.
|
|
@@ -486,9 +489,7 @@ module Net
|
|
|
486
489
|
# IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
|
|
487
490
|
# - Updates #fetch and #uid_fetch with the +BINARY+, +BINARY.PEEK+, and
|
|
488
491
|
# +BINARY.SIZE+ items. See FetchData#binary and FetchData#binary_size.
|
|
489
|
-
#
|
|
490
|
-
# >>>
|
|
491
|
-
# *NOTE:* The binary extension the #append command is _not_ supported yet.
|
|
492
|
+
# - Updates #append to allow binary messages containing +NULL+ bytes.
|
|
492
493
|
#
|
|
493
494
|
# ==== RFC3691: +UNSELECT+
|
|
494
495
|
# Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
|
|
@@ -568,6 +569,15 @@ module Net
|
|
|
568
569
|
# - Updates #store and #uid_store with the +unchangedsince+ modifier and adds
|
|
569
570
|
# the +MODIFIED+ ResponseCode to the tagged response.
|
|
570
571
|
#
|
|
572
|
+
# ==== RFC7888: <tt>LITERAL+</tt>
|
|
573
|
+
# - Literal strings smaller than Config#max_non_synchronizing_literal bytes
|
|
574
|
+
# are sent without waiting for the server's continuation request.
|
|
575
|
+
#
|
|
576
|
+
# ==== RFC7888: +LITERAL-+
|
|
577
|
+
# - Literal strings smaller than 4096 bytes or
|
|
578
|
+
# Config#max_non_synchronizing_literal (whichever is smaller)
|
|
579
|
+
# are sent without waiting for the server's continuation request.
|
|
580
|
+
#
|
|
571
581
|
# ==== RFC8438: <tt>STATUS=SIZE</tt>
|
|
572
582
|
# - Updates #status with the +SIZE+ status attribute.
|
|
573
583
|
#
|
|
@@ -578,6 +588,16 @@ module Net
|
|
|
578
588
|
# See FetchData#emailid and FetchData#emailid.
|
|
579
589
|
# - Updates #status with support for the +MAILBOXID+ status attribute.
|
|
580
590
|
#
|
|
591
|
+
# ==== RFC9208: <tt>QUOTA=RES-*</tt>
|
|
592
|
+
# +NOTE:+ Only the +STORAGE+ quota resource type is currently supported.
|
|
593
|
+
# - Obsoletes the +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
|
|
594
|
+
# extension and provides strict semantics for different resource types.
|
|
595
|
+
# - #getquota: returns the resource usage and limits for a quota root
|
|
596
|
+
# - #getquotaroot: returns the list of quota roots for a mailbox, as well as
|
|
597
|
+
# their resource usage and limits.
|
|
598
|
+
# - #setquota: sets the resource limits for a given quota root.
|
|
599
|
+
# - Updates #status with <tt>"DELETED"</tt> and +DELETED-STORAGE+ attributes.
|
|
600
|
+
#
|
|
581
601
|
# ==== RFC9394: +PARTIAL+
|
|
582
602
|
# - Updates #search, #uid_search with the +PARTIAL+ return option which adds
|
|
583
603
|
# ESearchResult#partial return data.
|
|
@@ -631,9 +651,9 @@ module Net
|
|
|
631
651
|
# RFC 5322, DOI 10.17487/RFC5322, October 2008,
|
|
632
652
|
# <https://www.rfc-editor.org/info/rfc5322>.
|
|
633
653
|
#
|
|
634
|
-
#
|
|
635
|
-
# RFC-2822[https://www.rfc-editor.org/rfc/rfc2822]
|
|
636
|
-
# RFC-822[https://www.rfc-editor.org/rfc/rfc822]
|
|
654
|
+
# *NOTE*: obsoletes
|
|
655
|
+
# RFC-2822[https://www.rfc-editor.org/rfc/rfc2822] (April 2001) and
|
|
656
|
+
# RFC-822[https://www.rfc-editor.org/rfc/rfc822] (August 1982).
|
|
637
657
|
#
|
|
638
658
|
# [CHARSET[https://www.rfc-editor.org/rfc/rfc2978]]::
|
|
639
659
|
# Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
|
|
@@ -698,13 +718,12 @@ module Net
|
|
|
698
718
|
#
|
|
699
719
|
# === \IMAP Extensions
|
|
700
720
|
#
|
|
701
|
-
# [QUOTA[https://www.rfc-editor.org/rfc/
|
|
702
|
-
#
|
|
703
|
-
#
|
|
721
|
+
# [QUOTA[https://www.rfc-editor.org/rfc/rfc2087]]::
|
|
722
|
+
# Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087,
|
|
723
|
+
# January 1997, <https://www.rfc-editor.org/info/rfc2087>.
|
|
704
724
|
#
|
|
705
|
-
#
|
|
706
|
-
#
|
|
707
|
-
# <em>Net::IMAP does not fully support the RFC9208 updates yet.</em>
|
|
725
|
+
# *NOTE*: _obsoleted_ by RFC9208[https://www.rfc-editor.org/rfc/rfc9208]
|
|
726
|
+
# (March 2022).
|
|
708
727
|
# [IDLE[https://www.rfc-editor.org/rfc/rfc2177]]::
|
|
709
728
|
# Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
|
|
710
729
|
# June 1997, <https://www.rfc-editor.org/info/rfc2177>.
|
|
@@ -741,8 +760,8 @@ module Net
|
|
|
741
760
|
# Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
|
|
742
761
|
# (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
|
|
743
762
|
# <https://www.rfc-editor.org/info/rfc6851>.
|
|
744
|
-
# [UTF8=ACCEPT[https://www.rfc-editor.org/rfc/rfc6855]]::
|
|
745
|
-
# [UTF8=ONLY[https://www.rfc-editor.org/rfc/rfc6855]]::
|
|
763
|
+
# [{UTF8=ACCEPT}[https://www.rfc-editor.org/rfc/rfc6855]]::
|
|
764
|
+
# [{UTF8=ONLY}[https://www.rfc-editor.org/rfc/rfc6855]]::
|
|
746
765
|
# Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
|
|
747
766
|
# "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
|
|
748
767
|
# <https://www.rfc-editor.org/info/rfc6855>.
|
|
@@ -756,6 +775,11 @@ module Net
|
|
|
756
775
|
# Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
|
|
757
776
|
# RFC 8474, DOI 10.17487/RFC8474, September 2018,
|
|
758
777
|
# <https://www.rfc-editor.org/info/rfc8474>.
|
|
778
|
+
# [{QUOTA=RES-*}[https://www.rfc-editor.org/rfc/rfc9208]]::
|
|
779
|
+
# Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
|
|
780
|
+
# March 2022, <https://www.rfc-editor.org/info/rfc9208>.
|
|
781
|
+
#
|
|
782
|
+
# Obsoletes RFC2087[https://www.rfc-editor.org/rfc/rfc2087].
|
|
759
783
|
# [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
|
|
760
784
|
# Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
|
|
761
785
|
# "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
|
|
@@ -769,6 +793,7 @@ module Net
|
|
|
769
793
|
#
|
|
770
794
|
# === IANA registries
|
|
771
795
|
# * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
|
|
796
|
+
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
|
|
772
797
|
# * {IMAP Response Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
|
|
773
798
|
# * {IMAP Mailbox Name Attributes}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
|
|
774
799
|
# * {IMAP and JMAP Keywords}[https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml]
|
|
@@ -779,8 +804,8 @@ module Net
|
|
|
779
804
|
# * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
|
|
780
805
|
# +imap+
|
|
781
806
|
# * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
|
|
807
|
+
#
|
|
782
808
|
# ==== For currently unsupported features:
|
|
783
|
-
# * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
|
|
784
809
|
# * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
|
|
785
810
|
# * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
|
|
786
811
|
# * {IMAP ANNOTATE Extension Entries and Attributes}[https://www.iana.org/assignments/imap-annotate-extension/imap-annotate-extension.xhtml]
|
|
@@ -788,7 +813,7 @@ module Net
|
|
|
788
813
|
# * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
|
|
789
814
|
#
|
|
790
815
|
class IMAP < Protocol
|
|
791
|
-
VERSION = "0.6.
|
|
816
|
+
VERSION = "0.6.4"
|
|
792
817
|
|
|
793
818
|
# Aliases for supported capabilities, to be used with the #enable command.
|
|
794
819
|
ENABLE_ALIASES = {
|
|
@@ -1120,6 +1145,31 @@ module Net
|
|
|
1120
1145
|
start_imap_connection
|
|
1121
1146
|
end
|
|
1122
1147
|
|
|
1148
|
+
# Returns a string representation of +self+, showing basic client state
|
|
1149
|
+
# information.
|
|
1150
|
+
#
|
|
1151
|
+
# imap = Net::IMAP.new(hostname, ssl: true)
|
|
1152
|
+
# imap.inspect #=> "#<Net::IMAP imap.example.net:993 TLS not_authenticated>"
|
|
1153
|
+
#
|
|
1154
|
+
# imap.authenticate(:oauthbearer, "user", token)
|
|
1155
|
+
# imap.inspect #=> "#<Net::IMAP imap.example.net:993 TLS authenticated>"
|
|
1156
|
+
#
|
|
1157
|
+
# imap.select("INBOX")
|
|
1158
|
+
# imap.inspect #=> "#<Net::IMAP imap.example.net:993 TLS selected>"
|
|
1159
|
+
#
|
|
1160
|
+
# imap.logout
|
|
1161
|
+
# imap.inspect #=> "#<Net::IMAP imap.example.net:993 TLS logout>"
|
|
1162
|
+
#
|
|
1163
|
+
def inspect
|
|
1164
|
+
tls_state = tls_verified? ? "TLS" :
|
|
1165
|
+
ssl_ctx ? "TLS (NOT VERIFIED)" :
|
|
1166
|
+
"PLAINTEXT"
|
|
1167
|
+
conn_state = disconnected? ? "disconnected" : connection_state.to_sym
|
|
1168
|
+
"#<%s:0x%08x %s:%s %s %s>" % [
|
|
1169
|
+
self.class.name, __id__, host, port, tls_state, conn_state
|
|
1170
|
+
]
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1123
1173
|
# Returns true after the TLS negotiation has completed and the remote
|
|
1124
1174
|
# hostname has been verified. Returns false when TLS has been established
|
|
1125
1175
|
# but peer verification was disabled.
|
|
@@ -1390,9 +1440,11 @@ module Net
|
|
|
1390
1440
|
#
|
|
1391
1441
|
def starttls(**options)
|
|
1392
1442
|
@ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
|
|
1443
|
+
handled = false
|
|
1393
1444
|
error = nil
|
|
1394
1445
|
ok = send_command("STARTTLS") do |resp|
|
|
1395
1446
|
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
|
1447
|
+
handled = true
|
|
1396
1448
|
clear_cached_capabilities
|
|
1397
1449
|
clear_responses
|
|
1398
1450
|
start_tls_session
|
|
@@ -1404,6 +1456,13 @@ module Net
|
|
|
1404
1456
|
disconnect
|
|
1405
1457
|
raise error
|
|
1406
1458
|
end
|
|
1459
|
+
unless handled
|
|
1460
|
+
disconnect
|
|
1461
|
+
raise InvalidResponseError,
|
|
1462
|
+
"STARTTLS handler was bypassed, although server responded %p" % [
|
|
1463
|
+
ok.raw_data.chomp
|
|
1464
|
+
]
|
|
1465
|
+
end
|
|
1407
1466
|
ok
|
|
1408
1467
|
end
|
|
1409
1468
|
|
|
@@ -1825,12 +1884,18 @@ module Net
|
|
|
1825
1884
|
# to both admin and user. If this mailbox exists, it returns an array
|
|
1826
1885
|
# containing objects of type MailboxQuotaRoot and MailboxQuota.
|
|
1827
1886
|
#
|
|
1887
|
+
# *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
|
|
1888
|
+
# resource type. This is usually +STORAGE+, but you may need to verify this
|
|
1889
|
+
# with UntaggedResponse#raw_data.
|
|
1890
|
+
#
|
|
1828
1891
|
# Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
|
|
1829
1892
|
#
|
|
1830
1893
|
# ==== Capabilities
|
|
1831
1894
|
#
|
|
1832
|
-
#
|
|
1833
|
-
#
|
|
1895
|
+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
|
|
1896
|
+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
|
|
1897
|
+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
|
|
1898
|
+
# resource type.
|
|
1834
1899
|
def getquotaroot(mailbox)
|
|
1835
1900
|
synchronize do
|
|
1836
1901
|
send_command("GETQUOTAROOT", mailbox)
|
|
@@ -1842,41 +1907,59 @@ module Net
|
|
|
1842
1907
|
end
|
|
1843
1908
|
|
|
1844
1909
|
# Sends a {GETQUOTA command [RFC2087 §4.2]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.2]
|
|
1845
|
-
#
|
|
1846
|
-
# containing a MailboxQuota object is returned.
|
|
1847
|
-
#
|
|
1910
|
+
# for the +quota_root+. If this quota root exists, then an array
|
|
1911
|
+
# containing a MailboxQuota object is returned.
|
|
1912
|
+
#
|
|
1913
|
+
# The names of quota roots that are applicable to a particular mailbox can
|
|
1914
|
+
# be discovered with #getquotaroot.
|
|
1915
|
+
#
|
|
1916
|
+
# *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
|
|
1917
|
+
# resource type. This is usually +STORAGE+, but you may need to verify this
|
|
1918
|
+
# with UntaggedResponse#raw_data.
|
|
1848
1919
|
#
|
|
1849
1920
|
# Related: #getquotaroot, #setquota, MailboxQuota
|
|
1850
1921
|
#
|
|
1851
1922
|
# ==== Capabilities
|
|
1852
1923
|
#
|
|
1853
|
-
#
|
|
1854
|
-
#
|
|
1855
|
-
|
|
1924
|
+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
|
|
1925
|
+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
|
|
1926
|
+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
|
|
1927
|
+
# resource type.
|
|
1928
|
+
def getquota(quota_root)
|
|
1856
1929
|
synchronize do
|
|
1857
|
-
send_command("GETQUOTA",
|
|
1930
|
+
send_command("GETQUOTA", quota_root)
|
|
1858
1931
|
clear_responses("QUOTA")
|
|
1859
1932
|
end
|
|
1860
1933
|
end
|
|
1861
1934
|
|
|
1862
1935
|
# Sends a {SETQUOTA command [RFC2087 §4.1]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.1]
|
|
1863
|
-
# along with the specified +
|
|
1864
|
-
# +
|
|
1865
|
-
#
|
|
1936
|
+
# along with the specified +quota_root+ and +storage_limit+. If
|
|
1937
|
+
# +storage_limit+ is +nil+, resource limits are unset for that quota root.
|
|
1938
|
+
# If +storage_limit+ is a number, it sets the +STORAGE+ resource limit.
|
|
1939
|
+
#
|
|
1940
|
+
# imap.setquota "#user/alice", 100
|
|
1941
|
+
# imap.getquota "#user/alice"
|
|
1942
|
+
# # => [#<struct Net::IMAP::MailboxQuota mailbox="#user/alice" usage=54 quota=100>]
|
|
1943
|
+
#
|
|
1944
|
+
# Typically one needs to be logged in as a server admin for this to work.
|
|
1945
|
+
#
|
|
1946
|
+
# *NOTE:* Currently, Net::IMAP only supports setting +STORAGE+ quota limits.
|
|
1866
1947
|
#
|
|
1867
1948
|
# Related: #getquota, #getquotaroot
|
|
1868
1949
|
#
|
|
1869
1950
|
# ==== Capabilities
|
|
1870
1951
|
#
|
|
1871
|
-
#
|
|
1872
|
-
#
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1952
|
+
# Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
|
|
1953
|
+
# capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
|
|
1954
|
+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
|
|
1955
|
+
# resource type.
|
|
1956
|
+
def setquota(quota_root, storage_limit)
|
|
1957
|
+
if storage_limit.nil?
|
|
1958
|
+
list = []
|
|
1876
1959
|
else
|
|
1877
|
-
|
|
1960
|
+
list = ["STORAGE", NumValidator.coerce_number64(storage_limit)]
|
|
1878
1961
|
end
|
|
1879
|
-
send_command("SETQUOTA",
|
|
1962
|
+
send_command("SETQUOTA", quota_root, list)
|
|
1880
1963
|
end
|
|
1881
1964
|
|
|
1882
1965
|
# Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
|
|
@@ -1983,7 +2066,10 @@ module Net
|
|
|
1983
2066
|
# <tt>STATUS=SIZE</tt>
|
|
1984
2067
|
# {[RFC8483]}[https://www.rfc-editor.org/rfc/rfc8483.html].
|
|
1985
2068
|
#
|
|
1986
|
-
# +DELETED+
|
|
2069
|
+
# +DELETED+ must be supported when the server's capabilities includes
|
|
2070
|
+
# +IMAP4rev2+.
|
|
2071
|
+
# or <tt>QUOTA=RES-MESSAGES</tt>
|
|
2072
|
+
# {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208.html].
|
|
1987
2073
|
#
|
|
1988
2074
|
# +HIGHESTMODSEQ+ requires the server's capabilities to include +CONDSTORE+
|
|
1989
2075
|
# {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
|
|
@@ -2019,6 +2105,11 @@ module Net
|
|
|
2019
2105
|
#
|
|
2020
2106
|
# ==== Capabilities
|
|
2021
2107
|
#
|
|
2108
|
+
# If +BINARY+ [RFC3516[https://www.rfc-editor.org/rfc/rfc3516.html]] is
|
|
2109
|
+
# supported by the server, +message+ may contain +NULL+ characters and
|
|
2110
|
+
# be sent as a binary literal. Otherwise, binary message parts must be
|
|
2111
|
+
# encoded appropriately (for example, +base64+).
|
|
2112
|
+
#
|
|
2022
2113
|
# If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
|
|
2023
2114
|
# supported and the destination supports persistent UIDs, the server's
|
|
2024
2115
|
# response should include an +APPENDUID+ response code with AppendUIDData.
|
|
@@ -2029,12 +2120,11 @@ module Net
|
|
|
2029
2120
|
# TODO: add MULTIAPPEND support
|
|
2030
2121
|
#++
|
|
2031
2122
|
def append(mailbox, message, flags = nil, date_time = nil)
|
|
2123
|
+
message = StringFormatter.literal_or_literal8(message, name: "message")
|
|
2032
2124
|
args = []
|
|
2033
|
-
if flags
|
|
2034
|
-
args.push(flags)
|
|
2035
|
-
end
|
|
2125
|
+
args.push(flags) if flags
|
|
2036
2126
|
args.push(date_time) if date_time
|
|
2037
|
-
args.push(
|
|
2127
|
+
args.push(message)
|
|
2038
2128
|
send_command("APPEND", mailbox, *args)
|
|
2039
2129
|
end
|
|
2040
2130
|
|
|
@@ -2264,11 +2354,11 @@ module Net
|
|
|
2264
2354
|
# Encoded as an \IMAP date (see ::encode_date).
|
|
2265
2355
|
#
|
|
2266
2356
|
# [When +criteria+ is a String]
|
|
2267
|
-
# +criteria+ will be sent
|
|
2268
|
-
#
|
|
2357
|
+
# +criteria+ will be sent to the server <em>with minimal validation and no
|
|
2358
|
+
# encoding or formatting</em>.
|
|
2269
2359
|
#
|
|
2270
|
-
# <em>*WARNING:*
|
|
2271
|
-
#
|
|
2360
|
+
# <em>*WARNING:* Although CRLF is prohibited, this is vulnerable to other
|
|
2361
|
+
# types of attribute injection attack if unvetted user input is used.</em>
|
|
2272
2362
|
#
|
|
2273
2363
|
# ==== Supported return options
|
|
2274
2364
|
#
|
|
@@ -2589,6 +2679,13 @@ module Net
|
|
|
2589
2679
|
#
|
|
2590
2680
|
# +attr+ is a list of attributes to fetch; see FetchStruct documentation for
|
|
2591
2681
|
# a list of supported attributes.
|
|
2682
|
+
# >>>
|
|
2683
|
+
# When +attr+ is a String, it will be sent <em>with minimal validation and
|
|
2684
|
+
# no encoding or formatting</em>. When +attr+ is an Array, each String in
|
|
2685
|
+
# +attr+ will be sent this way.
|
|
2686
|
+
#
|
|
2687
|
+
# <em>*WARNING:* Although CRLF is prohibited, this is vulnerable to other
|
|
2688
|
+
# types of attribute injection attack if unvetted user input is used.</em>
|
|
2592
2689
|
#
|
|
2593
2690
|
# +changedsince+ is an optional integer mod-sequence. It limits results to
|
|
2594
2691
|
# messages with a mod-sequence greater than +changedsince+.
|
|
@@ -3077,6 +3174,7 @@ module Net
|
|
|
3077
3174
|
|
|
3078
3175
|
synchronize do
|
|
3079
3176
|
tag = Thread.current[:net_imap_tag] = generate_tag
|
|
3177
|
+
guard_against_tagged_response_skipping_handler!(tag, "IDLE")
|
|
3080
3178
|
put_string("#{tag} IDLE#{CRLF}")
|
|
3081
3179
|
|
|
3082
3180
|
begin
|
|
@@ -3481,7 +3579,7 @@ module Net
|
|
|
3481
3579
|
raise BadResponseError, resp
|
|
3482
3580
|
else
|
|
3483
3581
|
disconnect
|
|
3484
|
-
raise InvalidResponseError, "invalid tagged resp: %p" % [resp.
|
|
3582
|
+
raise InvalidResponseError, "invalid tagged resp: %p" % [resp.raw_data.chomp]
|
|
3485
3583
|
end
|
|
3486
3584
|
end
|
|
3487
3585
|
|
|
@@ -3541,21 +3639,29 @@ module Net
|
|
|
3541
3639
|
put_string(" ")
|
|
3542
3640
|
send_data(i, tag)
|
|
3543
3641
|
end
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
end
|
|
3548
|
-
if block
|
|
3549
|
-
add_response_handler(&block)
|
|
3550
|
-
end
|
|
3642
|
+
@logout_command_tag = tag if cmd == "LOGOUT"
|
|
3643
|
+
guard_against_tagged_response_skipping_handler!(tag, cmd)
|
|
3644
|
+
add_response_handler(&block) if block
|
|
3551
3645
|
begin
|
|
3552
|
-
|
|
3646
|
+
put_string(CRLF)
|
|
3647
|
+
get_tagged_response(tag, cmd)
|
|
3553
3648
|
ensure
|
|
3554
|
-
if block
|
|
3555
|
-
remove_response_handler(block)
|
|
3556
|
-
end
|
|
3649
|
+
remove_response_handler(block) if block
|
|
3557
3650
|
end
|
|
3558
3651
|
end
|
|
3652
|
+
rescue InvalidResponseError
|
|
3653
|
+
disconnect
|
|
3654
|
+
raise
|
|
3655
|
+
end
|
|
3656
|
+
|
|
3657
|
+
def guard_against_tagged_response_skipping_handler!(tag, cmd)
|
|
3658
|
+
return unless (resp = @tagged_responses[tag])&.name&.upcase == "OK"
|
|
3659
|
+
raise InvalidResponseError, format(
|
|
3660
|
+
"Received tagged 'OK' to incomplete %s command (tag=%s). " \
|
|
3661
|
+
"This could indicate a malicious server, a man-in-the-middle, or " \
|
|
3662
|
+
"client-side command injection. Disconnecting.",
|
|
3663
|
+
cmd, tag
|
|
3664
|
+
)
|
|
3559
3665
|
end
|
|
3560
3666
|
|
|
3561
3667
|
def generate_tag
|
|
@@ -3709,7 +3815,7 @@ module Net
|
|
|
3709
3815
|
end
|
|
3710
3816
|
|
|
3711
3817
|
def store_internal(cmd, set, attr, flags, unchangedsince: nil)
|
|
3712
|
-
attr =
|
|
3818
|
+
attr = Atom.new(attr) if attr.instance_of?(String)
|
|
3713
3819
|
args = [SequenceSet.new(set)]
|
|
3714
3820
|
args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
|
|
3715
3821
|
args << attr << flags
|
|
@@ -3781,7 +3887,7 @@ module Net
|
|
|
3781
3887
|
params = (Hash.try_convert(ssl) || {}).freeze
|
|
3782
3888
|
context = OpenSSL::SSL::SSLContext.new
|
|
3783
3889
|
context.set_params(params)
|
|
3784
|
-
context.
|
|
3890
|
+
context.setup
|
|
3785
3891
|
[params, context]
|
|
3786
3892
|
else
|
|
3787
3893
|
false
|
data/rakelib/rdoc.rake
CHANGED
|
@@ -12,17 +12,6 @@ module RDoc::Generator
|
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
# See https://github.com/ruby/rdoc/pull/936
|
|
16
|
-
module FixSectionComments
|
|
17
|
-
def markup(text)
|
|
18
|
-
@store ||= @parent&.store
|
|
19
|
-
super
|
|
20
|
-
end
|
|
21
|
-
def description; markup comment end
|
|
22
|
-
def comment; super || @comments&.first end
|
|
23
|
-
def parse(_comment_location = nil) super() end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
15
|
# render "[label] data" lists as tables. adapted from "hanna-nouveau" gem.
|
|
27
16
|
module LabelListTable
|
|
28
17
|
def list_item_start(list_item, list_type)
|
|
@@ -51,20 +40,14 @@ class RDoc::AnyMethod
|
|
|
51
40
|
prepend RDoc::Generator::NetIMAP::RemoveRedundantParens
|
|
52
41
|
end
|
|
53
42
|
|
|
54
|
-
class RDoc::Context::Section
|
|
55
|
-
prepend RDoc::Generator::NetIMAP::FixSectionComments
|
|
56
|
-
end
|
|
57
|
-
|
|
58
43
|
class RDoc::Markup::ToHtml
|
|
59
44
|
LIST_TYPE_TO_HTML[:NOTE] = ['<table class="rdoc-list note-list"><tbody>', '</tbody></table>']
|
|
60
45
|
prepend RDoc::Generator::NetIMAP::LabelListTable
|
|
61
46
|
end
|
|
62
47
|
|
|
63
48
|
RDoc::Task.new do |doc|
|
|
64
|
-
doc.main = "README.md"
|
|
65
49
|
doc.title = "net-imap #{Net::IMAP::VERSION}"
|
|
66
50
|
doc.rdoc_dir = "doc"
|
|
67
|
-
doc.rdoc_files = FileList.new %w[lib/**/*.rb *.rdoc *.md]
|
|
68
51
|
doc.options << "--template-stylesheets" << "docs/styles.css"
|
|
69
|
-
|
|
52
|
+
doc.generator = "darkfish" # TODO: fix issues with aliki
|
|
70
53
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: net-imap
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shugo Maeda
|
|
@@ -46,6 +46,8 @@ executables: []
|
|
|
46
46
|
extensions: []
|
|
47
47
|
extra_rdoc_files: []
|
|
48
48
|
files:
|
|
49
|
+
- ".document"
|
|
50
|
+
- ".rdoc_options"
|
|
49
51
|
- BSDL
|
|
50
52
|
- COPYING
|
|
51
53
|
- Gemfile
|
|
@@ -129,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
129
131
|
- !ruby/object:Gem::Version
|
|
130
132
|
version: '0'
|
|
131
133
|
requirements: []
|
|
132
|
-
rubygems_version: 4.0.
|
|
134
|
+
rubygems_version: 4.0.10
|
|
133
135
|
specification_version: 4
|
|
134
136
|
summary: Ruby client api for Internet Message Access Protocol
|
|
135
137
|
test_files: []
|