tdiary 5.4.0 → 5.5.0.beta1

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.
Files changed (641) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +25 -2
  3. data/Gemfile.lock +211 -61
  4. data/README.md +4 -4
  5. data/doc/HOWTO-make-plugin.md +1 -1
  6. data/doc/HOWTO-testing-tDiary.md +2 -2
  7. data/doc/INSTALL-cgi.md +7 -0
  8. data/doc/INSTALL-paas.md +11 -11
  9. data/doc/INSTALL.md +2 -2
  10. data/doc/README.en.md +1 -1
  11. data/doc/README.md +1 -1
  12. data/lib/aws/pa_api.rb +6 -2
  13. data/lib/tdiary/admin.rb +6 -4
  14. data/lib/tdiary/application.rb +17 -17
  15. data/lib/tdiary/author_only_base.rb +6 -13
  16. data/lib/tdiary/base.rb +52 -16
  17. data/lib/tdiary/cgi_adapter.rb +86 -0
  18. data/lib/tdiary/cgi_compat.rb +189 -0
  19. data/lib/tdiary/configuration.rb +1 -1
  20. data/lib/tdiary/core_ext.rb +4 -53
  21. data/lib/tdiary/diary_container.rb +23 -11
  22. data/lib/tdiary/dispatcher/index_main.rb +16 -16
  23. data/lib/tdiary/dispatcher/update_main.rb +16 -16
  24. data/lib/tdiary/dispatcher.rb +4 -28
  25. data/lib/tdiary/environment.rb +12 -0
  26. data/lib/tdiary/filter.rb +5 -2
  27. data/lib/tdiary/io/pstore.rb +6 -3
  28. data/lib/tdiary/plugin/00default.rb +10 -14
  29. data/lib/tdiary/plugin/05referer.rb +6 -6
  30. data/lib/tdiary/plugin/60sf.rb +1 -1
  31. data/lib/tdiary/plugin.rb +76 -16
  32. data/lib/tdiary/request.rb +11 -353
  33. data/lib/tdiary/tasks/db.rake +17 -4
  34. data/lib/tdiary/tasks/heroku.rake +9 -0
  35. data/lib/tdiary/tasks/release.rake +126 -146
  36. data/lib/tdiary/version.rb +1 -1
  37. data/lib/tdiary/view.rb +3 -3
  38. data/lib/tdiary.rb +3 -1
  39. data/misc/convert2.rb +3 -0
  40. data/misc/migrate.rb +3 -0
  41. data/misc/plugin/a.rb +1 -6
  42. data/misc/plugin/amazon.rb +5 -4
  43. data/misc/plugin/calendar2.rb +1 -1
  44. data/misc/plugin/en/disp_referrer.rb +1 -1
  45. data/misc/plugin/ja/disp_referrer.rb +1 -1
  46. data/misc/plugin/kw.rb +2 -21
  47. data/misc/plugin/makelirs.rb +1 -4
  48. data/tdiary.conf.sample +8 -0
  49. data/theme/base.css +15 -0
  50. data/vendor/bundle/ruby/3.4.0/bin/emot +29 -0
  51. data/vendor/bundle/ruby/3.4.0/bin/hikidoc +29 -0
  52. data/vendor/bundle/ruby/3.4.0/bin/rackup +29 -0
  53. data/vendor/bundle/ruby/3.4.0/bin/rake +29 -0
  54. data/vendor/bundle/ruby/3.4.0/bin/thor +29 -0
  55. data/vendor/bundle/ruby/3.4.0/cache/base64-0.3.0.gem +0 -0
  56. data/vendor/bundle/ruby/3.4.0/cache/cgi-0.5.2.gem +0 -0
  57. data/vendor/bundle/ruby/3.4.0/cache/date-3.5.1.gem +0 -0
  58. data/vendor/bundle/ruby/3.4.0/cache/emot-0.0.4.gem +0 -0
  59. data/vendor/bundle/ruby/3.4.0/cache/fastimage-2.4.1.gem +0 -0
  60. data/vendor/bundle/ruby/3.4.0/cache/hikidoc-0.1.1.gem +0 -0
  61. data/vendor/bundle/ruby/3.4.0/cache/logger-1.7.0.gem +0 -0
  62. data/vendor/bundle/ruby/3.4.0/cache/mail-2.9.1.gem +0 -0
  63. data/vendor/bundle/ruby/3.4.0/cache/mini_mime-1.1.5.gem +0 -0
  64. data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.5.15.gem +0 -0
  65. data/vendor/bundle/ruby/3.4.0/cache/net-pop-0.1.2.gem +0 -0
  66. data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.2.2.gem +0 -0
  67. data/vendor/bundle/ruby/3.4.0/cache/net-smtp-0.5.1.gem +0 -0
  68. data/vendor/bundle/ruby/3.4.0/cache/pstore-0.2.1.gem +0 -0
  69. data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.6.gem +0 -0
  70. data/vendor/bundle/ruby/3.4.0/cache/rack-session-2.1.2.gem +0 -0
  71. data/vendor/bundle/ruby/3.4.0/cache/rackup-2.3.1.gem +0 -0
  72. data/vendor/bundle/ruby/3.4.0/cache/rake-13.4.2.gem +0 -0
  73. data/vendor/bundle/ruby/3.4.0/cache/thor-1.5.0.gem +0 -0
  74. data/vendor/bundle/ruby/3.4.0/cache/timeout-0.6.1.gem +0 -0
  75. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/cgi/escape.so +0 -0
  76. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem.build_complete +0 -0
  77. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem_make.out +18 -0
  78. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/date_core.so +0 -0
  79. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem.build_complete +0 -0
  80. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem_make.out +24 -0
  81. data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/mkmf.log +93 -0
  82. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/BSDL +22 -0
  83. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/COPYING +56 -0
  84. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/LEGAL +60 -0
  85. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/README.md +48 -0
  86. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/lib/base64.rb +381 -0
  87. data/vendor/bundle/ruby/3.4.0/gems/base64-0.3.0/sig/base64.rbs +355 -0
  88. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/BSDL +22 -0
  89. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/COPYING +56 -0
  90. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/README.md +98 -0
  91. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/Makefile +275 -0
  92. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/depend +2 -0
  93. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/escape.c +487 -0
  94. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/ext/cgi/escape/extconf.rb +7 -0
  95. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/cookie.rb +212 -0
  96. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/core.rb +1273 -0
  97. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/escape.rb +227 -0
  98. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/escape.so +0 -0
  99. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/html.rb +1040 -0
  100. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/session/pstore.rb +91 -0
  101. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/session.rb +574 -0
  102. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi/util.rb +48 -0
  103. data/vendor/bundle/ruby/3.4.0/gems/cgi-0.5.2/lib/cgi.rb +310 -0
  104. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/BSDL +22 -0
  105. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/COPYING +56 -0
  106. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/README.md +102 -0
  107. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/Makefile +273 -0
  108. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_core.c +10065 -0
  109. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_parse.c +3086 -0
  110. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_strftime.c +638 -0
  111. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_strptime.c +704 -0
  112. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/date_tmx.h +56 -0
  113. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/extconf.rb +13 -0
  114. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/prereq.mk +19 -0
  115. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/zonetab.h +1564 -0
  116. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/ext/date/zonetab.list +330 -0
  117. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/lib/date.rb +70 -0
  118. data/vendor/bundle/ruby/3.4.0/gems/date-3.5.1/lib/date_core.so +0 -0
  119. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/Gemfile +4 -0
  120. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/LICENSE.txt +22 -0
  121. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/README.md +87 -0
  122. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/Rakefile +7 -0
  123. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/bin/emot +5 -0
  124. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/emot.gemspec +26 -0
  125. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/cli.rb +62 -0
  126. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/map.rb +894 -0
  127. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/symbol_ext.rb +11 -0
  128. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot/version.rb +3 -0
  129. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/lib/emot.rb +34 -0
  130. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/cli_spec.rb +56 -0
  131. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/emot_spec.rb +50 -0
  132. data/vendor/bundle/ruby/3.4.0/gems/emot-0.0.4/spec/spec_helper.rb +2 -0
  133. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/MIT-LICENSE +20 -0
  134. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/README.md +209 -0
  135. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage.rb +471 -0
  136. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/avif.rb +12 -0
  137. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/bmp.rb +17 -0
  138. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/exif.rb +76 -0
  139. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/fiber_stream.rb +58 -0
  140. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/gif.rb +63 -0
  141. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/heic.rb +8 -0
  142. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/ico.rb +9 -0
  143. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/image_base.rb +17 -0
  144. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/iso_bmff.rb +176 -0
  145. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jpeg.rb +52 -0
  146. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jxl.rb +13 -0
  147. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/jxlc.rb +75 -0
  148. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/png.rb +26 -0
  149. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/psd.rb +7 -0
  150. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/stream_util.rb +19 -0
  151. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/svg.rb +69 -0
  152. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/tiff.rb +16 -0
  153. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/type_parser.rb +74 -0
  154. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/fastimage_parsing/webp.rb +60 -0
  155. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage/version.rb +5 -0
  156. data/vendor/bundle/ruby/3.4.0/gems/fastimage-2.4.1/lib/fastimage.rb +73 -0
  157. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/COPYING +28 -0
  158. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/Gemfile +4 -0
  159. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/NEWS +36 -0
  160. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/NEWS.ja +36 -0
  161. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README +95 -0
  162. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.ja +92 -0
  163. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.ja.md +112 -0
  164. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/README.md +114 -0
  165. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/Rakefile +18 -0
  166. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules +320 -0
  167. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.ja +318 -0
  168. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.ja.md +385 -0
  169. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/TextFormattingRules.md +388 -0
  170. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/bin/hikidoc +70 -0
  171. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/hikidoc.gemspec +24 -0
  172. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/lib/hikidoc.rb +912 -0
  173. data/vendor/bundle/ruby/3.4.0/gems/hikidoc-0.1.1/test/hikidoc_test.rb +514 -0
  174. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/BSDL +22 -0
  175. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/COPYING +56 -0
  176. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/README.md +104 -0
  177. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/errors.rb +9 -0
  178. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/formatter.rb +36 -0
  179. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/log_device.rb +265 -0
  180. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/period.rb +47 -0
  181. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/severity.rb +38 -0
  182. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger/version.rb +5 -0
  183. data/vendor/bundle/ruby/3.4.0/gems/logger-1.7.0/lib/logger.rb +789 -0
  184. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/MIT-LICENSE +20 -0
  185. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/README.md +771 -0
  186. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/attachments_list.rb +109 -0
  187. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/body.rb +305 -0
  188. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/configuration.rb +78 -0
  189. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/constants.rb +79 -0
  190. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/address.rb +258 -0
  191. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/address_list.rb +34 -0
  192. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_disposition_element.rb +20 -0
  193. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_location_element.rb +17 -0
  194. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_transfer_encoding_element.rb +13 -0
  195. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/content_type_element.rb +25 -0
  196. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/date_time_element.rb +15 -0
  197. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/envelope_from_element.rb +39 -0
  198. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/message_ids_element.rb +31 -0
  199. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/mime_version_element.rb +15 -0
  200. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/phrase_list.rb +19 -0
  201. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements/received_element.rb +35 -0
  202. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/elements.rb +15 -0
  203. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/7bit.rb +27 -0
  204. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/8bit.rb +18 -0
  205. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/base64.rb +38 -0
  206. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/binary.rb +13 -0
  207. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/identity.rb +24 -0
  208. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/quoted_printable.rb +45 -0
  209. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/transfer_encoding.rb +77 -0
  210. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings/unix_to_unix.rb +20 -0
  211. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/encodings.rb +314 -0
  212. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/envelope.rb +28 -0
  213. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/field.rb +313 -0
  214. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/field_list.rb +87 -0
  215. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/bcc_field.rb +49 -0
  216. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/cc_field.rb +33 -0
  217. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/comments_field.rb +31 -0
  218. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_address_field.rb +162 -0
  219. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_date_field.rb +56 -0
  220. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_field.rb +77 -0
  221. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/common_message_id_field.rb +41 -0
  222. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_description_field.rb +12 -0
  223. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_disposition_field.rb +44 -0
  224. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_id_field.rb +35 -0
  225. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_location_field.rb +28 -0
  226. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_transfer_encoding_field.rb +44 -0
  227. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/content_type_field.rb +171 -0
  228. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/date_field.rb +28 -0
  229. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/from_field.rb +33 -0
  230. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/in_reply_to_field.rb +45 -0
  231. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/keywords_field.rb +30 -0
  232. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/message_id_field.rb +36 -0
  233. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/mime_version_field.rb +42 -0
  234. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/named_structured_field.rb +10 -0
  235. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/named_unstructured_field.rb +10 -0
  236. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/optional_field.rb +15 -0
  237. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/parameter_hash.rb +61 -0
  238. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/received_field.rb +61 -0
  239. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/references_field.rb +42 -0
  240. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/reply_to_field.rb +33 -0
  241. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_bcc_field.rb +33 -0
  242. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_cc_field.rb +33 -0
  243. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_date_field.rb +10 -0
  244. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_from_field.rb +33 -0
  245. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_message_id_field.rb +10 -0
  246. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_sender_field.rb +32 -0
  247. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/resent_to_field.rb +33 -0
  248. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/return_path_field.rb +60 -0
  249. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/sender_field.rb +45 -0
  250. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/structured_field.rb +24 -0
  251. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/subject_field.rb +14 -0
  252. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/to_field.rb +33 -0
  253. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields/unstructured_field.rb +189 -0
  254. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/fields.rb +45 -0
  255. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/header.rb +237 -0
  256. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/indifferent_hash.rb +147 -0
  257. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/mail.rb +267 -0
  258. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/matchers/attachment_matchers.rb +44 -0
  259. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/matchers/has_sent_mail.rb +201 -0
  260. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/message.rb +2159 -0
  261. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/chars.rb +318 -0
  262. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/unicode.rb +405 -0
  263. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte/utils.rb +44 -0
  264. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/multibyte.rb +82 -0
  265. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/exim.rb +50 -0
  266. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/file_delivery.rb +43 -0
  267. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
  268. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/sendmail.rb +87 -0
  269. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/smtp.rb +200 -0
  270. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/smtp_connection.rb +57 -0
  271. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/delivery_methods/test_mailer.rb +44 -0
  272. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/base.rb +64 -0
  273. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/imap.rb +190 -0
  274. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/pop3.rb +143 -0
  275. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network/retriever_methods/test_retriever.rb +45 -0
  276. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/network.rb +16 -0
  277. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parser_tools.rb +15 -0
  278. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/address_lists_parser.rb +33245 -0
  279. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/address_lists_parser.rl +183 -0
  280. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rb +904 -0
  281. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_disposition_parser.rl +93 -0
  282. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_location_parser.rb +825 -0
  283. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_location_parser.rl +82 -0
  284. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rb +525 -0
  285. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
  286. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_type_parser.rb +1051 -0
  287. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/content_type_parser.rl +94 -0
  288. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/date_time_parser.rb +894 -0
  289. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/date_time_parser.rl +73 -0
  290. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rb +3678 -0
  291. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/envelope_from_parser.rl +93 -0
  292. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/message_ids_parser.rb +5164 -0
  293. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/message_ids_parser.rl +97 -0
  294. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/mime_version_parser.rb +516 -0
  295. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/mime_version_parser.rl +72 -0
  296. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rb +887 -0
  297. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/phrase_lists_parser.rl +94 -0
  298. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/received_parser.rb +8785 -0
  299. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/received_parser.rl +95 -0
  300. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
  301. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_content_type.rl +25 -0
  302. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2045_mime.rl +16 -0
  303. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
  304. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc3629_utf8.rl +19 -0
  305. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
  306. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322.rl +74 -0
  307. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_address.rl +72 -0
  308. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_date_time.rl +37 -0
  309. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
  310. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parsers.rb +13 -0
  311. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/part.rb +119 -0
  312. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/parts_list.rb +131 -0
  313. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/smtp_envelope.rb +57 -0
  314. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/utilities.rb +576 -0
  315. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/values/unicode_tables.dat +0 -0
  316. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/version.rb +17 -0
  317. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail/yaml.rb +30 -0
  318. data/vendor/bundle/ruby/3.4.0/gems/mail-2.9.1/lib/mail.rb +65 -0
  319. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/CHANGELOG +65 -0
  320. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/CODE_OF_CONDUCT.md +74 -0
  321. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/Gemfile +9 -0
  322. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/LICENSE.txt +21 -0
  323. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/README.md +114 -0
  324. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/Rakefile +97 -0
  325. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bench/bench.rb +51 -0
  326. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/console +15 -0
  327. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/db_pull_request +20 -0
  328. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/bin/setup +8 -0
  329. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/db/content_type_mime.db +880 -0
  330. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/db/ext_mime.db +1201 -0
  331. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/mini_mime/version.rb +4 -0
  332. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/lib/mini_mime.rb +186 -0
  333. data/vendor/bundle/ruby/3.4.0/gems/mini_mime-1.1.5/mini_mime.gemspec +31 -0
  334. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/BSDL +22 -0
  335. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/COPYING +56 -0
  336. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Gemfile +25 -0
  337. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/LICENSE.txt +65 -0
  338. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/README.md +77 -0
  339. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Rakefile +13 -0
  340. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/docs/styles.css +85 -0
  341. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/authenticators.rb +37 -0
  342. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/command_data.rb +507 -0
  343. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_accessors.rb +75 -0
  344. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_inheritance.rb +90 -0
  345. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_type_coercion.rb +74 -0
  346. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config/attr_version_defaults.rb +93 -0
  347. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/config.rb +500 -0
  348. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/connection_state.rb +48 -0
  349. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_encoding.rb +214 -0
  350. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_lite.rb +226 -0
  351. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/deprecated_client_options.rb +142 -0
  352. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/errors.rb +118 -0
  353. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/esearch_result.rb +219 -0
  354. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/fetch_data.rb +597 -0
  355. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/flags.rb +262 -0
  356. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_data.rb +1113 -0
  357. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_parser/parser_utils.rb +245 -0
  358. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_parser.rb +2282 -0
  359. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/response_reader.rb +92 -0
  360. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/anonymous_authenticator.rb +69 -0
  361. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/authentication_exchange.rb +139 -0
  362. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/authenticators.rb +122 -0
  363. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/client_adapter.rb +123 -0
  364. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/cram_md5_authenticator.rb +61 -0
  365. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/digest_md5_authenticator.rb +342 -0
  366. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/external_authenticator.rb +83 -0
  367. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/gs2_header.rb +80 -0
  368. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/login_authenticator.rb +56 -0
  369. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/oauthbearer_authenticator.rb +199 -0
  370. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/plain_authenticator.rb +101 -0
  371. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/protocol_adapters.rb +101 -0
  372. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/scram_algorithm.rb +58 -0
  373. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/scram_authenticator.rb +361 -0
  374. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/stringprep.rb +12 -0
  375. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl/xoauth2_authenticator.rb +106 -0
  376. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl.rb +182 -0
  377. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sasl_adapter.rb +20 -0
  378. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/search_result.rb +145 -0
  379. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/sequence_set.rb +1952 -0
  380. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/nameprep.rb +70 -0
  381. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/saslprep.rb +69 -0
  382. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/saslprep_tables.rb +96 -0
  383. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/tables.rb +146 -0
  384. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep/trace.rb +85 -0
  385. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/stringprep.rb +159 -0
  386. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/uidplus_data.rb +244 -0
  387. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/vanished_data.rb +65 -0
  388. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap.rb +3968 -0
  389. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/net-imap.gemspec +38 -0
  390. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/benchmarks.rake +91 -0
  391. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/rdoc.rake +70 -0
  392. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/rfcs.rake +170 -0
  393. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/saslprep.rake +30 -0
  394. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/rakelib/string_prep_tables_generator.rb +449 -0
  395. data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/sample/net-imap.rb +167 -0
  396. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/Gemfile +7 -0
  397. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/LICENSE.txt +22 -0
  398. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/README.md +66 -0
  399. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/Rakefile +17 -0
  400. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/lib/net/pop.rb +1025 -0
  401. data/vendor/bundle/ruby/3.4.0/gems/net-pop-0.1.2/net-pop.gemspec +32 -0
  402. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Gemfile +7 -0
  403. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/LICENSE.txt +22 -0
  404. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/README.md +29 -0
  405. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Rakefile +10 -0
  406. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/console +14 -0
  407. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/setup +8 -0
  408. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/lib/net/protocol.rb +544 -0
  409. data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/net-protocol.gemspec +33 -0
  410. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/LICENSE.txt +2 -0
  411. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/NEWS.md +133 -0
  412. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/README.md +97 -0
  413. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_cram_md5.rb +48 -0
  414. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_login.rb +11 -0
  415. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_plain.rb +9 -0
  416. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/auth_xoauth2.rb +17 -0
  417. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp/authenticator.rb +57 -0
  418. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/lib/net/smtp.rb +1164 -0
  419. data/vendor/bundle/ruby/3.4.0/gems/net-smtp-0.5.1/net-smtp.gemspec +31 -0
  420. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/BSDL +22 -0
  421. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/COPYING +56 -0
  422. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/Gemfile +10 -0
  423. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/README.md +95 -0
  424. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/Rakefile +10 -0
  425. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/bin/console +14 -0
  426. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/bin/setup +8 -0
  427. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/lib/pstore.rb +736 -0
  428. data/vendor/bundle/ruby/3.4.0/gems/pstore-0.2.1/pstore.gemspec +32 -0
  429. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/CHANGELOG.md +1346 -0
  430. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/CONTRIBUTING.md +144 -0
  431. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/MIT-LICENSE +20 -0
  432. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/README.md +384 -0
  433. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/SPEC.rdoc +258 -0
  434. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/abstract/handler.rb +41 -0
  435. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/abstract/request.rb +51 -0
  436. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/auth/basic.rb +58 -0
  437. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/bad_request.rb +8 -0
  438. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/body_proxy.rb +63 -0
  439. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/builder.rb +296 -0
  440. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/cascade.rb +67 -0
  441. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/common_logger.rb +89 -0
  442. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/conditional_get.rb +87 -0
  443. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/config.rb +22 -0
  444. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/constants.rb +68 -0
  445. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/content_length.rb +34 -0
  446. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/content_type.rb +33 -0
  447. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/deflater.rb +158 -0
  448. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/directory.rb +208 -0
  449. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/etag.rb +71 -0
  450. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/events.rb +172 -0
  451. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/files.rb +216 -0
  452. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/head.rb +25 -0
  453. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/headers.rb +238 -0
  454. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/lint.rb +964 -0
  455. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/lock.rb +29 -0
  456. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/media_type.rb +52 -0
  457. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/method_override.rb +56 -0
  458. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mime.rb +694 -0
  459. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock.rb +3 -0
  460. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock_request.rb +161 -0
  461. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/mock_response.rb +156 -0
  462. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/generator.rb +99 -0
  463. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/parser.rb +621 -0
  464. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart/uploaded_file.rb +82 -0
  465. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/multipart.rb +77 -0
  466. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/null_logger.rb +48 -0
  467. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/query_parser.rb +261 -0
  468. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/recursive.rb +66 -0
  469. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/reloader.rb +112 -0
  470. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/request.rb +790 -0
  471. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/response.rb +403 -0
  472. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/rewindable_input.rb +116 -0
  473. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/runtime.rb +35 -0
  474. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/sendfile.rb +197 -0
  475. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/show_exceptions.rb +409 -0
  476. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/show_status.rb +121 -0
  477. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/static.rb +192 -0
  478. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/tempfile_reaper.rb +33 -0
  479. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/urlmap.rb +99 -0
  480. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/utils.rb +714 -0
  481. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack/version.rb +17 -0
  482. data/vendor/bundle/ruby/3.4.0/gems/rack-3.2.6/lib/rack.rb +64 -0
  483. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/abstract/id.rb +535 -0
  484. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/constants.rb +13 -0
  485. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/cookie.rb +315 -0
  486. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/encryptor.rb +415 -0
  487. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/pool.rb +82 -0
  488. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session/version.rb +10 -0
  489. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/lib/rack/session.rb +12 -0
  490. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/license.md +72 -0
  491. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/readme.md +47 -0
  492. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/releases.md +31 -0
  493. data/vendor/bundle/ruby/3.4.0/gems/rack-session-2.1.2/security.md +3 -0
  494. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/bin/rackup +5 -0
  495. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler/cgi.rb +61 -0
  496. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler/webrick.rb +196 -0
  497. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/handler.rb +113 -0
  498. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/lobster.rb +81 -0
  499. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/server.rb +462 -0
  500. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/stream.rb +199 -0
  501. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup/version.rb +8 -0
  502. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/lib/rackup.rb +21 -0
  503. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/license.md +80 -0
  504. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/readme.md +82 -0
  505. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/releases.md +28 -0
  506. data/vendor/bundle/ruby/3.4.0/gems/rackup-2.3.1/security.md +3 -0
  507. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/History.rdoc +2454 -0
  508. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/MIT-LICENSE +21 -0
  509. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/README.rdoc +155 -0
  510. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/command_line_usage.rdoc +171 -0
  511. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile1 +38 -0
  512. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/Rakefile2 +35 -0
  513. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/a.c +6 -0
  514. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/b.c +6 -0
  515. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/example/main.c +11 -0
  516. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/glossary.rdoc +42 -0
  517. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/jamis.rb +592 -0
  518. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/proto_rake.rdoc +127 -0
  519. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rake.1 +156 -0
  520. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rakefile.rdoc +635 -0
  521. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/doc/rational.rdoc +151 -0
  522. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/exe/rake +27 -0
  523. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/application.rb +847 -0
  524. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/backtrace.rb +25 -0
  525. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/clean.rb +78 -0
  526. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cloneable.rb +17 -0
  527. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/cpu_counter.rb +122 -0
  528. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/default_loader.rb +15 -0
  529. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/dsl_definition.rb +196 -0
  530. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/early_time.rb +22 -0
  531. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/core.rb +26 -0
  532. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/ext/string.rb +176 -0
  533. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_creation_task.rb +25 -0
  534. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_list.rb +435 -0
  535. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_task.rb +58 -0
  536. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils.rb +137 -0
  537. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/file_utils_ext.rb +135 -0
  538. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_chain.rb +57 -0
  539. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/invocation_exception_mixin.rb +17 -0
  540. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/late_time.rb +18 -0
  541. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/linked_list.rb +112 -0
  542. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/loaders/makefile.rb +54 -0
  543. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/multi_task.rb +14 -0
  544. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/name_space.rb +38 -0
  545. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/options.rb +31 -0
  546. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/packagetask.rb +222 -0
  547. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/phony.rb +16 -0
  548. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/private_reader.rb +21 -0
  549. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/promise.rb +100 -0
  550. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/pseudo_status.rb +30 -0
  551. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_module.rb +67 -0
  552. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rake_test_loader.rb +27 -0
  553. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/rule_recursion_overflow_error.rb +20 -0
  554. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/scope.rb +43 -0
  555. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task.rb +434 -0
  556. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_argument_error.rb +8 -0
  557. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_arguments.rb +113 -0
  558. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/task_manager.rb +333 -0
  559. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/tasklib.rb +12 -0
  560. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/testtask.rb +192 -0
  561. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_history_display.rb +49 -0
  562. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/thread_pool.rb +157 -0
  563. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/trace_output.rb +23 -0
  564. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/version.rb +10 -0
  565. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake/win32.rb +17 -0
  566. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/lib/rake.rb +69 -0
  567. data/vendor/bundle/ruby/3.4.0/gems/rake-13.4.2/rake.gemspec +102 -0
  568. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/CONTRIBUTING.md +32 -0
  569. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/LICENSE.md +20 -0
  570. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/README.md +44 -0
  571. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/bin/thor +6 -0
  572. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/create_file.rb +105 -0
  573. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/create_link.rb +61 -0
  574. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/directory.rb +108 -0
  575. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/empty_directory.rb +143 -0
  576. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/file_manipulation.rb +407 -0
  577. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions/inject_into_file.rb +163 -0
  578. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/actions.rb +340 -0
  579. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/base.rb +826 -0
  580. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/command.rb +151 -0
  581. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/core_ext/hash_with_indifferent_access.rb +107 -0
  582. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/error.rb +106 -0
  583. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/group.rb +292 -0
  584. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/invocation.rb +178 -0
  585. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor/basic.rb +37 -0
  586. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor/readline.rb +88 -0
  587. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/line_editor.rb +17 -0
  588. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/nested_context.rb +29 -0
  589. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/argument.rb +86 -0
  590. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/arguments.rb +195 -0
  591. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/option.rb +178 -0
  592. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser/options.rb +294 -0
  593. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/parser.rb +4 -0
  594. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/rake_compat.rb +72 -0
  595. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/runner.rb +335 -0
  596. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/basic.rb +392 -0
  597. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/color.rb +117 -0
  598. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/column_printer.rb +29 -0
  599. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/html.rb +84 -0
  600. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/lcs_diff.rb +49 -0
  601. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/table_printer.rb +118 -0
  602. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/terminal.rb +42 -0
  603. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell/wrapped_printer.rb +38 -0
  604. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/shell.rb +81 -0
  605. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/util.rb +285 -0
  606. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor/version.rb +3 -0
  607. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/lib/thor.rb +707 -0
  608. data/vendor/bundle/ruby/3.4.0/gems/thor-1.5.0/thor.gemspec +33 -0
  609. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/BSDL +22 -0
  610. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/COPYING +56 -0
  611. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/Gemfile +10 -0
  612. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/README.md +39 -0
  613. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/lib/timeout.rb +314 -0
  614. data/vendor/bundle/ruby/3.4.0/gems/timeout-0.6.1/timeout.gemspec +33 -0
  615. data/vendor/bundle/ruby/3.4.0/specifications/base64-0.3.0.gemspec +23 -0
  616. data/vendor/bundle/ruby/3.4.0/specifications/cgi-0.5.2.gemspec +25 -0
  617. data/vendor/bundle/ruby/3.4.0/specifications/date-3.5.1.gemspec +25 -0
  618. data/vendor/bundle/ruby/3.4.0/specifications/emot-0.0.4.gemspec +30 -0
  619. data/vendor/bundle/ruby/3.4.0/specifications/fastimage-2.4.1.gemspec +32 -0
  620. data/vendor/bundle/ruby/3.4.0/specifications/hikidoc-0.1.1.gemspec +28 -0
  621. data/vendor/bundle/ruby/3.4.0/specifications/logger-1.7.0.gemspec +22 -0
  622. data/vendor/bundle/ruby/3.4.0/specifications/mail-2.9.1.gemspec +38 -0
  623. data/vendor/bundle/ruby/3.4.0/specifications/mini_mime-1.1.5.gemspec +30 -0
  624. data/vendor/bundle/ruby/3.4.0/specifications/net-imap-0.5.15.gemspec +28 -0
  625. data/vendor/bundle/ruby/3.4.0/specifications/net-pop-0.1.2.gemspec +26 -0
  626. data/vendor/bundle/ruby/3.4.0/specifications/net-protocol-0.2.2.gemspec +26 -0
  627. data/vendor/bundle/ruby/3.4.0/specifications/net-smtp-0.5.1.gemspec +26 -0
  628. data/vendor/bundle/ruby/3.4.0/specifications/pstore-0.2.1.gemspec +22 -0
  629. data/vendor/bundle/ruby/3.4.0/specifications/rack-3.2.6.gemspec +31 -0
  630. data/vendor/bundle/ruby/3.4.0/specifications/rack-session-2.1.2.gemspec +30 -0
  631. data/vendor/bundle/ruby/3.4.0/specifications/rackup-2.3.1.gemspec +26 -0
  632. data/vendor/bundle/ruby/3.4.0/specifications/rake-13.4.2.gemspec +26 -0
  633. data/vendor/bundle/ruby/3.4.0/specifications/thor-1.5.0.gemspec +28 -0
  634. data/vendor/bundle/ruby/3.4.0/specifications/timeout-0.6.1.gemspec +22 -0
  635. metadata +595 -20
  636. data/js/02edit.js +0 -15
  637. data/lib/tdiary/compatible.rb +0 -56
  638. data/misc/lib/fcgi_patch.rb +0 -89
  639. data/misc/paas/heroku/Gemfile.local +0 -12
  640. data/misc/paas/heroku/Gemfile.lock +0 -287
  641. data/public/index.rdf +0 -22
@@ -0,0 +1,3968 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # = net/imap.rb
4
+ #
5
+ # Copyright (C) 2000 Shugo Maeda <shugo@ruby-lang.org>
6
+ #
7
+ # This library is distributed under the terms of the Ruby license.
8
+ # You can freely distribute/modify this library.
9
+ #
10
+ # Documentation: Shugo Maeda, with RDoc conversion and overview by William
11
+ # Webber.
12
+ #
13
+ # See Net::IMAP for documentation.
14
+ #
15
+
16
+ require "socket"
17
+ require "monitor"
18
+ require 'net/protocol'
19
+ begin
20
+ require "openssl"
21
+ rescue LoadError
22
+ end
23
+
24
+ module Net
25
+
26
+ # Net::IMAP implements Internet Message Access Protocol (\IMAP) client
27
+ # functionality. The protocol is described
28
+ # in {IMAP4rev1 [RFC3501]}[https://www.rfc-editor.org/rfc/rfc3501]
29
+ # and {IMAP4rev2 [RFC9051]}[https://www.rfc-editor.org/rfc/rfc9051].
30
+ #
31
+ # == \IMAP Overview
32
+ #
33
+ # An \IMAP client connects to a server, and then authenticates
34
+ # itself using either #authenticate or #login. Having
35
+ # authenticated itself, there is a range of commands
36
+ # available to it. Most work with mailboxes, which may be
37
+ # arranged in an hierarchical namespace, and each of which
38
+ # contains zero or more messages. How this is implemented on
39
+ # the server is implementation-dependent; on a UNIX server, it
40
+ # will frequently be implemented as files in mailbox format
41
+ # within a hierarchy of directories.
42
+ #
43
+ # To work on the messages within a mailbox, the client must
44
+ # first select that mailbox, using either #select or #examine
45
+ # (for read-only access). Once the client has successfully
46
+ # selected a mailbox, they enter the +selected+ state, and that
47
+ # mailbox becomes the _current_ mailbox, on which mail-item
48
+ # related commands implicitly operate.
49
+ #
50
+ # === Connection state
51
+ #
52
+ # Once an IMAP connection is established, the connection is in one of four
53
+ # states: <tt>not authenticated</tt>, +authenticated+, +selected+, and
54
+ # +logout+. Most commands are valid only in certain states.
55
+ #
56
+ # See #connection_state.
57
+ #
58
+ # === Sequence numbers and UIDs
59
+ #
60
+ # Messages have two sorts of identifiers: message sequence
61
+ # numbers and UIDs.
62
+ #
63
+ # Message sequence numbers number messages within a mailbox
64
+ # from 1 up to the number of items in the mailbox. If a new
65
+ # message arrives during a session, it receives a sequence
66
+ # number equal to the new size of the mailbox. If messages
67
+ # are expunged from the mailbox, remaining messages have their
68
+ # sequence numbers "shuffled down" to fill the gaps.
69
+ #
70
+ # To avoid sequence number race conditions, servers must not expunge messages
71
+ # when no command is in progress, nor when responding to #fetch, #store, or
72
+ # #search. Expunges _may_ be sent during any other command, including
73
+ # #uid_fetch, #uid_store, and #uid_search. The #noop and #idle commands are
74
+ # both useful for this side-effect: they allow the server to send all mailbox
75
+ # updates, including expunges.
76
+ #
77
+ # UIDs, on the other hand, are permanently guaranteed not to
78
+ # identify another message within the same mailbox, even if
79
+ # the existing message is deleted. UIDs are required to
80
+ # be assigned in ascending (but not necessarily sequential)
81
+ # order within a mailbox; this means that if a non-IMAP client
82
+ # rearranges the order of mail items within a mailbox, the
83
+ # UIDs have to be reassigned. An \IMAP client thus cannot
84
+ # rearrange message orders.
85
+ #
86
+ # === Examples of Usage
87
+ #
88
+ # ==== List sender and subject of all recent messages in the default mailbox
89
+ #
90
+ # imap = Net::IMAP.new('mail.example.com')
91
+ # imap.authenticate('PLAIN', 'joe_user', 'joes_password')
92
+ # imap.examine('INBOX')
93
+ # imap.search(["RECENT"]).each do |message_id|
94
+ # envelope = imap.fetch(message_id, "ENVELOPE")[0].attr["ENVELOPE"]
95
+ # puts "#{envelope.from[0].name}: \t#{envelope.subject}"
96
+ # end
97
+ #
98
+ # ==== Move all messages from April 2003 from "Mail/sent-mail" to "Mail/sent-apr03"
99
+ #
100
+ # imap = Net::IMAP.new('mail.example.com')
101
+ # imap.authenticate('PLAIN', 'joe_user', 'joes_password')
102
+ # imap.select('Mail/sent-mail')
103
+ # if not imap.list('Mail/', 'sent-apr03')
104
+ # imap.create('Mail/sent-apr03')
105
+ # end
106
+ # imap.search(["BEFORE", "30-Apr-2003", "SINCE", "1-Apr-2003"]).each do |message_id|
107
+ # imap.copy(message_id, "Mail/sent-apr03")
108
+ # imap.store(message_id, "+FLAGS", [:Deleted])
109
+ # end
110
+ # imap.expunge
111
+ #
112
+ # == Capabilities
113
+ #
114
+ # Most Net::IMAP methods do not _currently_ modify their behaviour according
115
+ # to the server's advertised #capabilities. Users of this class must check
116
+ # that the server is capable of extension commands or command arguments before
117
+ # sending them. Special care should be taken to follow the #capabilities
118
+ # requirements for #starttls, #login, and #authenticate.
119
+ #
120
+ # See #capable?, #auth_capable?, #capabilities, #auth_mechanisms to discover
121
+ # server capabilities. For relevant capability requirements, see the
122
+ # documentation on each \IMAP command.
123
+ #
124
+ # imap = Net::IMAP.new("mail.example.com")
125
+ # imap.capable?(:IMAP4rev1) or raise "Not an IMAP4rev1 server"
126
+ # imap.capable?(:starttls) or raise "Cannot start TLS"
127
+ # imap.starttls
128
+ #
129
+ # if imap.auth_capable?("PLAIN")
130
+ # imap.authenticate "PLAIN", username, password
131
+ # elsif !imap.capability?("LOGINDISABLED")
132
+ # imap.login username, password
133
+ # else
134
+ # raise "No acceptable authentication mechanisms"
135
+ # end
136
+ #
137
+ # # Support for "UTF8=ACCEPT" implies support for "ENABLE"
138
+ # imap.enable :utf8 if imap.capable?("UTF8=ACCEPT")
139
+ #
140
+ # namespaces = imap.namespace if imap.capable?(:namespace)
141
+ # mbox_prefix = namespaces&.personal&.first&.prefix || ""
142
+ # mbox_delim = namespaces&.personal&.first&.delim || "/"
143
+ # mbox_path = prefix + %w[path to my mailbox].join(delim)
144
+ # imap.create mbox_path
145
+ #
146
+ # === Basic IMAP4rev1 capabilities
147
+ #
148
+ # IMAP4rev1 servers must advertise +IMAP4rev1+ in their capabilities list.
149
+ # IMAP4rev1 servers must _implement_ the +STARTTLS+, <tt>AUTH=PLAIN</tt>,
150
+ # and +LOGINDISABLED+ capabilities. See #starttls, #login, and #authenticate
151
+ # for the implications of these capabilities.
152
+ #
153
+ # === Caching +CAPABILITY+ responses
154
+ #
155
+ # Net::IMAP automatically stores and discards capability data according to the
156
+ # the requirements and recommendations in
157
+ # {IMAP4rev2 §6.1.1}[https://www.rfc-editor.org/rfc/rfc9051#section-6.1.1],
158
+ # {§6.2}[https://www.rfc-editor.org/rfc/rfc9051#section-6.2], and
159
+ # {§7.1}[https://www.rfc-editor.org/rfc/rfc9051#section-7.1].
160
+ # Use #capable?, #auth_capable?, or #capabilities to use this cache and avoid
161
+ # sending the #capability command unnecessarily.
162
+ #
163
+ # The server may advertise its initial capabilities using the +CAPABILITY+
164
+ # ResponseCode in a +PREAUTH+ or +OK+ #greeting. When TLS has started
165
+ # (#starttls) and after authentication (#login or #authenticate), the server's
166
+ # capabilities may change and cached capabilities are discarded. The server
167
+ # may send updated capabilities with an +OK+ TaggedResponse to #login or
168
+ # #authenticate, and these will be cached by Net::IMAP. But the
169
+ # TaggedResponse to #starttls MUST be ignored--it is sent before TLS starts
170
+ # and is unprotected.
171
+ #
172
+ # When storing capability values to variables, be careful that they are
173
+ # discarded or reset appropriately, especially following #starttls.
174
+ #
175
+ # === Using IMAP4rev1 extensions
176
+ #
177
+ # See the {IANA IMAP4 capabilities
178
+ # registry}[http://www.iana.org/assignments/imap4-capabilities] for a list of
179
+ # all standard capabilities, and their reference RFCs.
180
+ #
181
+ # IMAP4rev1 servers must not activate behavior that is incompatible with the
182
+ # base specification until an explicit client action invokes a capability,
183
+ # e.g. sending a command or command argument specific to that capability.
184
+ # Servers may send data with backward compatible behavior, such as response
185
+ # codes or mailbox attributes, at any time without client action.
186
+ #
187
+ # Invoking capabilities which are unknown to Net::IMAP may cause unexpected
188
+ # behavior and errors. For example, ResponseParseError is raised when
189
+ # unknown response syntax is received. Invoking commands or command
190
+ # parameters that are unsupported by the server may raise NoResponseError,
191
+ # BadResponseError, or cause other unexpected behavior.
192
+ #
193
+ # Some capabilities must be explicitly activated using the #enable command.
194
+ # See #enable for details.
195
+ #
196
+ # == Thread Safety
197
+ #
198
+ # Net::IMAP supports concurrent threads. For example,
199
+ #
200
+ # imap = Net::IMAP.new("imap.foo.net", "imap2")
201
+ # imap.authenticate("scram-md5", "bar", "password")
202
+ # imap.select("inbox")
203
+ # fetch_thread = Thread.start { imap.fetch(1..-1, "UID") }
204
+ # search_result = imap.search(["BODY", "hello"])
205
+ # fetch_result = fetch_thread.value
206
+ # imap.disconnect
207
+ #
208
+ # This script invokes the FETCH command and the SEARCH command concurrently.
209
+ #
210
+ # When running multiple commands, care must be taken to avoid ambiguity. For
211
+ # example, SEARCH responses are ambiguous about which command they are
212
+ # responding to, so search commands should not run simultaneously, unless the
213
+ # server supports +ESEARCH+ {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731] or
214
+ # IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051]. See {RFC9051
215
+ # §5.5}[https://www.rfc-editor.org/rfc/rfc9051.html#section-5.5] for
216
+ # other examples of command sequences which should not be pipelined.
217
+ #
218
+ # == Unbounded memory use
219
+ #
220
+ # Net::IMAP reads server responses in a separate receiver thread per client.
221
+ # Unhandled response data is saved to #responses, and response_handlers run
222
+ # inside the receiver thread. See the list of methods for {handling server
223
+ # responses}[rdoc-ref:Net::IMAP@Handling+server+responses], below.
224
+ #
225
+ # Because the receiver thread continuously reads and saves new responses, some
226
+ # scenarios must be careful to avoid unbounded memory use:
227
+ #
228
+ # * Commands such as #list or #fetch can have an enormous number of responses.
229
+ # * Commands such as #fetch can result in an enormous size per response.
230
+ # * Long-lived connections will gradually accumulate unsolicited server
231
+ # responses, especially +EXISTS+, +FETCH+, and +EXPUNGE+ responses.
232
+ # * A buggy or untrusted server could send inappropriate responses, which
233
+ # could be very numerous, very large, and very rapid.
234
+ #
235
+ # Use paginated or limited versions of commands whenever possible.
236
+ #
237
+ # Use Config#max_response_size to impose a limit on incoming server responses
238
+ # as they are being read. <em>This is especially important for untrusted
239
+ # servers.</em>
240
+ #
241
+ # Use #add_response_handler to handle responses after each one is received.
242
+ # Use the +response_handlers+ argument to ::new to assign response handlers
243
+ # before the receiver thread is started. Use #extract_responses,
244
+ # #clear_responses, or #responses (with a block) to prune responses.
245
+ #
246
+ # == Errors
247
+ #
248
+ # An \IMAP server can send three different types of responses to indicate
249
+ # failure:
250
+ #
251
+ # NO:: the attempted command could not be successfully completed. For
252
+ # instance, the username/password used for logging in are incorrect;
253
+ # the selected mailbox does not exist; etc.
254
+ #
255
+ # BAD:: the request from the client does not follow the server's
256
+ # understanding of the \IMAP protocol. This includes attempting
257
+ # commands from the wrong client state; for instance, attempting
258
+ # to perform a SEARCH command without having SELECTed a current
259
+ # mailbox. It can also signal an internal server
260
+ # failure (such as a disk crash) has occurred.
261
+ #
262
+ # BYE:: the server is saying goodbye. This can be part of a normal
263
+ # logout sequence, and can be used as part of a login sequence
264
+ # to indicate that the server is (for some reason) unwilling
265
+ # to accept your connection. As a response to any other command,
266
+ # it indicates either that the server is shutting down, or that
267
+ # the server is timing out the client connection due to inactivity.
268
+ #
269
+ # These three error response are represented by the errors
270
+ # Net::IMAP::NoResponseError, Net::IMAP::BadResponseError, and
271
+ # Net::IMAP::ByeResponseError, all of which are subclasses of
272
+ # Net::IMAP::ResponseError. Essentially, all methods that involve
273
+ # sending a request to the server can generate one of these errors.
274
+ # Only the most pertinent instances have been documented below.
275
+ #
276
+ # Because the IMAP class uses Sockets for communication, its methods
277
+ # are also susceptible to the various errors that can occur when
278
+ # working with sockets. These are generally represented as
279
+ # Errno errors. For instance, any method that involves sending a
280
+ # request to the server and/or receiving a response from it could
281
+ # raise an Errno::EPIPE error if the network connection unexpectedly
282
+ # goes down. See the socket(7), ip(7), tcp(7), socket(2), connect(2),
283
+ # and associated man pages.
284
+ #
285
+ # Finally, a Net::IMAP::DataFormatError is thrown if low-level data
286
+ # is found to be in an incorrect format (for instance, when converting
287
+ # between UTF-8 and UTF-16), and Net::IMAP::ResponseParseError is
288
+ # thrown if a server response is non-parseable.
289
+ #
290
+ # == What's here?
291
+ #
292
+ # * {Connection control}[rdoc-ref:Net::IMAP@Connection+control+methods]
293
+ # * {Server capabilities}[rdoc-ref:Net::IMAP@Server+capabilities]
294
+ # * {Handling server responses}[rdoc-ref:Net::IMAP@Handling+server+responses]
295
+ # * {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands]
296
+ # * {for any state}[rdoc-ref:Net::IMAP@Any+state]
297
+ # * {for the "not authenticated" state}[rdoc-ref:Net::IMAP@Not+Authenticated+state]
298
+ # * {for the "authenticated" state}[rdoc-ref:Net::IMAP@Authenticated+state]
299
+ # * {for the "selected" state}[rdoc-ref:Net::IMAP@Selected+state]
300
+ # * {for the "logout" state}[rdoc-ref:Net::IMAP@Logout+state]
301
+ # * {IMAP extension support}[rdoc-ref:Net::IMAP@IMAP+extension+support]
302
+ #
303
+ # === Connection control methods
304
+ #
305
+ # - Net::IMAP.new: Creates a new \IMAP client which connects immediately and
306
+ # waits for a successful server greeting before the method returns.
307
+ # - #connection_state: Returns the connection state.
308
+ # - #starttls: Asks the server to upgrade a clear-text connection to use TLS.
309
+ # - #logout: Tells the server to end the session. Enters the +logout+ state.
310
+ # - #disconnect: Disconnects the connection (without sending #logout first).
311
+ # - #disconnected?: True if the connection has been closed.
312
+ #
313
+ # === Server capabilities
314
+ #
315
+ # - #capable?: Returns whether the server supports a given capability.
316
+ # - #capabilities: Returns the server's capabilities as an array of strings.
317
+ # - #auth_capable?: Returns whether the server advertises support for a given
318
+ # SASL mechanism, for use with #authenticate.
319
+ # - #auth_mechanisms: Returns the #authenticate SASL mechanisms which
320
+ # the server claims to support as an array of strings.
321
+ # - #clear_cached_capabilities: Clears cached capabilities.
322
+ #
323
+ # <em>The capabilities cache is automatically cleared after completing
324
+ # #starttls, #login, or #authenticate.</em>
325
+ # - #capability: Sends the +CAPABILITY+ command and returns the #capabilities.
326
+ #
327
+ # <em>In general, #capable? should be used rather than explicitly sending a
328
+ # +CAPABILITY+ command to the server.</em>
329
+ #
330
+ # === Handling server responses
331
+ #
332
+ # - #greeting: The server's initial untagged response, which can indicate a
333
+ # pre-authenticated connection.
334
+ # - #responses: Yields unhandled UntaggedResponse#data and <em>non-+nil+</em>
335
+ # ResponseCode#data.
336
+ # - #extract_responses: Removes and returns the responses for which the block
337
+ # returns a true value.
338
+ # - #clear_responses: Deletes unhandled data from #responses and returns it.
339
+ # - #add_response_handler: Add a block to be called inside the receiver thread
340
+ # with every server response.
341
+ # - #response_handlers: Returns the list of response handlers.
342
+ # - #remove_response_handler: Remove a previously added response handler.
343
+ #
344
+ # === Core \IMAP commands
345
+ #
346
+ # The following commands are defined either by
347
+ # the [IMAP4rev1[https://www.rfc-editor.org/rfc/rfc3501]] base specification, or
348
+ # by one of the following extensions:
349
+ # [IDLE[https://www.rfc-editor.org/rfc/rfc2177]],
350
+ # [NAMESPACE[https://www.rfc-editor.org/rfc/rfc2342]],
351
+ # [UNSELECT[https://www.rfc-editor.org/rfc/rfc3691]],
352
+ # [ENABLE[https://www.rfc-editor.org/rfc/rfc5161]],
353
+ # [MOVE[https://www.rfc-editor.org/rfc/rfc6851]].
354
+ # These extensions are widely supported by modern IMAP4rev1 servers and have
355
+ # all been integrated into [IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051]].
356
+ # <em>*NOTE:* Net::IMAP doesn't support IMAP4rev2 yet.</em>
357
+ #
358
+ # ==== Any state
359
+ #
360
+ # - #capability: Returns the server's capabilities as an array of strings.
361
+ #
362
+ # <em>In general, #capable? should be used rather than explicitly sending a
363
+ # +CAPABILITY+ command to the server.</em>
364
+ # - #noop: Allows the server to send unsolicited untagged #responses.
365
+ # - #logout: Tells the server to end the session. Enters the +logout+ state.
366
+ #
367
+ # ==== Not Authenticated state
368
+ #
369
+ # In addition to the commands for any state, the following commands are valid
370
+ # in the +not_authenticated+ state:
371
+ #
372
+ # - #starttls: Upgrades a clear-text connection to use TLS.
373
+ #
374
+ # <em>Requires the +STARTTLS+ capability.</em>
375
+ # - #authenticate: Identifies the client to the server using the given
376
+ # {SASL mechanism}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
377
+ # and credentials. Enters the +authenticated+ state.
378
+ #
379
+ # <em>The server should list <tt>"AUTH=#{mechanism}"</tt> capabilities for
380
+ # supported mechanisms.</em>
381
+ # - #login: Identifies the client to the server using a plain text password.
382
+ # Using #authenticate is preferred. Enters the +authenticated+ state.
383
+ #
384
+ # <em>The +LOGINDISABLED+ capability</em> <b>must NOT</b> <em>be listed.</em>
385
+ #
386
+ # ==== Authenticated state
387
+ #
388
+ # In addition to the commands for any state, the following commands are valid
389
+ # in the +authenticated+ state:
390
+ #
391
+ # - #enable: Enables backwards incompatible server extensions.
392
+ # <em>Requires the +ENABLE+ or +IMAP4rev2+ capability.</em>
393
+ # - #select: Open a mailbox and enter the +selected+ state.
394
+ # - #examine: Open a mailbox read-only, and enter the +selected+ state.
395
+ # - #create: Creates a new mailbox.
396
+ # - #delete: Permanently remove a mailbox.
397
+ # - #rename: Change the name of a mailbox.
398
+ # - #subscribe: Adds a mailbox to the "subscribed" set.
399
+ # - #unsubscribe: Removes a mailbox from the "subscribed" set.
400
+ # - #list: Returns names and attributes of mailboxes matching a given pattern.
401
+ # - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
402
+ # <em>Requires the +NAMESPACE+ or +IMAP4rev2+ capability.</em>
403
+ # - #status: Returns mailbox information, e.g. message count, unseen message
404
+ # count, +UIDVALIDITY+ and +UIDNEXT+.
405
+ # - #append: Appends a message to the end of a mailbox.
406
+ # - #idle: Allows the server to send updates to the client, without the client
407
+ # needing to poll using #noop.
408
+ # <em>Requires the +IDLE+ or +IMAP4rev2+ capability.</em>
409
+ # - *Obsolete* #lsub: <em>Replaced by <tt>LIST-EXTENDED</tt> and removed from
410
+ # +IMAP4rev2+.</em> Lists mailboxes in the "subscribed" set.
411
+ #
412
+ # <em>*Note:* Net::IMAP hasn't implemented <tt>LIST-EXTENDED</tt> yet.</em>
413
+ #
414
+ # ==== Selected state
415
+ #
416
+ # In addition to the commands for any state and the +authenticated+
417
+ # commands, the following commands are valid in the +selected+ state:
418
+ #
419
+ # - #close: Closes the mailbox and returns to the +authenticated+ state,
420
+ # expunging deleted messages, unless the mailbox was opened as read-only.
421
+ # - #unselect: Closes the mailbox and returns to the +authenticated+ state,
422
+ # without expunging any messages.
423
+ # <em>Requires the +UNSELECT+ or +IMAP4rev2+ capability.</em>
424
+ # - #expunge: Permanently removes messages which have the Deleted flag set.
425
+ # - #uid_expunge: Restricts expunge to only remove the specified UIDs.
426
+ # <em>Requires the +UIDPLUS+ or +IMAP4rev2+ capability.</em>
427
+ # - #search, #uid_search: Returns sequence numbers or UIDs of messages that
428
+ # match the given searching criteria.
429
+ # - #fetch, #uid_fetch: Returns data associated with a set of messages,
430
+ # specified by sequence number or UID.
431
+ # - #store, #uid_store: Alters a message's flags.
432
+ # - #copy, #uid_copy: Copies the specified messages to the end of the
433
+ # specified destination mailbox.
434
+ # - #move, #uid_move: Moves the specified messages to the end of the
435
+ # specified destination mailbox, expunging them from the current mailbox.
436
+ # <em>Requires the +MOVE+ or +IMAP4rev2+ capability.</em>
437
+ # - #check: <em>*Obsolete:* removed from +IMAP4rev2+.</em>
438
+ # Can be replaced with #noop or #idle.
439
+ #
440
+ # ==== Logout state
441
+ #
442
+ # No \IMAP commands are valid in the +logout+ state. If the socket is still
443
+ # open, Net::IMAP will close it after receiving server confirmation.
444
+ # Exceptions will be raised by \IMAP commands that have already started and
445
+ # are waiting for a response, as well as any that are called after logout.
446
+ #
447
+ # === \IMAP extension support
448
+ #
449
+ # ==== RFC9051: +IMAP4rev2+
450
+ #
451
+ # Although IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] is not supported
452
+ # yet, Net::IMAP supports several extensions that have been folded into it:
453
+ # +ENABLE+, +IDLE+, +MOVE+, +NAMESPACE+, +SASL-IR+, +UIDPLUS+, +UNSELECT+,
454
+ # <tt>STATUS=SIZE</tt>, and the fetch side of +BINARY+.
455
+ # Commands for these extensions are listed with the {Core IMAP
456
+ # commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands], above.
457
+ #
458
+ # >>>
459
+ # <em>The following are folded into +IMAP4rev2+ but are currently
460
+ # unsupported or incompletely supported by</em> Net::IMAP<em>: RFC4466
461
+ # extensions, +SEARCHRES+, +LIST-EXTENDED+, +LIST-STATUS+,
462
+ # +LITERAL-+, and +SPECIAL-USE+.</em>
463
+ #
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.
468
+ # - #getquota: returns the resource usage and limits for a quota root
469
+ # - #getquotaroot: returns the list of quota roots for a mailbox, as well as
470
+ # their resource usage and limits.
471
+ # - #setquota: sets the resource limits for a given quota root.
472
+ #
473
+ # ==== RFC2177: +IDLE+
474
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
475
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
476
+ # - #idle: Allows the server to send updates to the client, without the client
477
+ # needing to poll using #noop.
478
+ #
479
+ # ==== RFC2342: +NAMESPACE+
480
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
481
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
482
+ # - #namespace: Returns mailbox namespaces, with path prefixes and delimiters.
483
+ #
484
+ # ==== RFC2971: +ID+
485
+ # - #id: exchanges client and server implementation information.
486
+ #
487
+ # ==== RFC3516: +BINARY+
488
+ # The fetch side of +BINARY+ has been folded into
489
+ # IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
490
+ # - Updates #fetch and #uid_fetch with the +BINARY+, +BINARY.PEEK+, and
491
+ # +BINARY.SIZE+ items. See FetchData#binary and FetchData#binary_size.
492
+ #
493
+ # >>>
494
+ # *NOTE:* The binary extension the #append command is _not_ supported yet.
495
+ #
496
+ # ==== RFC3691: +UNSELECT+
497
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
498
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
499
+ # - #unselect: Closes the mailbox and returns to the +authenticated+ state,
500
+ # without expunging any messages.
501
+ #
502
+ # ==== RFC4314: +ACL+
503
+ # - #getacl: lists the authenticated user's access rights to a mailbox.
504
+ # - #setacl: sets the access rights for a user on a mailbox
505
+ # >>>
506
+ # *NOTE:* +DELETEACL+, +LISTRIGHTS+, and +MYRIGHTS+ are not supported yet.
507
+ #
508
+ # ==== RFC4315: +UIDPLUS+
509
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
510
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
511
+ # - #uid_expunge: Restricts #expunge to only remove the specified UIDs.
512
+ # - Updates #select, #examine with the +UIDNOTSTICKY+ ResponseCode
513
+ # - Updates #append with the +APPENDUID+ ResponseCode
514
+ # - Updates #copy, #move with the +COPYUID+ ResponseCode
515
+ #
516
+ # ==== RFC4731: +ESEARCH+
517
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
518
+ # - Updates #search, #uid_search with +return+ options and ESearchResult.
519
+ #
520
+ # ==== RFC4959: +SASL-IR+
521
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051].
522
+ # - Updates #authenticate with the option to send an initial response.
523
+ #
524
+ # ==== RFC5161: +ENABLE+
525
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
526
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
527
+ # - #enable: Enables backwards incompatible server extensions.
528
+ #
529
+ # ==== RFC5256: +SORT+
530
+ # - #sort, #uid_sort: An alternate version of #search or #uid_search which
531
+ # sorts the results by specified keys.
532
+ # ==== RFC5256: +THREAD+
533
+ # - #thread, #uid_thread: An alternate version of #search or #uid_search,
534
+ # which arranges the results into ordered groups or threads according to a
535
+ # chosen algorithm.
536
+ #
537
+ # ==== +X-GM-EXT-1+
538
+ # +X-GM-EXT-1+ is a non-standard Gmail extension. See {Google's
539
+ # documentation}[https://developers.google.com/gmail/imap/imap-extensions].
540
+ # - Updates #fetch and #uid_fetch with support for +X-GM-MSGID+ (unique
541
+ # message ID), +X-GM-THRID+ (thread ID), and +X-GM-LABELS+ (Gmail labels).
542
+ # - Updates #search with the +X-GM-RAW+ search attribute.
543
+ # - #xlist: replaced by +SPECIAL-USE+ attributes in #list responses.
544
+ #
545
+ # *NOTE:* The +OBJECTID+ extension should replace +X-GM-MSGID+ and
546
+ # +X-GM-THRID+, but Gmail does not support it (as of 2023-11-10).
547
+ #
548
+ # ==== RFC6851: +MOVE+
549
+ # Folded into IMAP4rev2[https://www.rfc-editor.org/rfc/rfc9051] and also included
550
+ # above with {Core IMAP commands}[rdoc-ref:Net::IMAP@Core+IMAP+commands].
551
+ # - #move, #uid_move: Moves the specified messages to the end of the
552
+ # specified destination mailbox, expunging them from the current mailbox.
553
+ #
554
+ # ==== RFC6855: <tt>UTF8=ACCEPT</tt>, <tt>UTF8=ONLY</tt>
555
+ #
556
+ # - See #enable for information about support for UTF-8 string encoding.
557
+ #
558
+ # ==== RFC7162: +CONDSTORE+
559
+ #
560
+ # - Updates #enable with +CONDSTORE+ parameter. +CONDSTORE+ will also be
561
+ # enabled by using any of the extension's command parameters, listed below.
562
+ # - Updates #status with the +HIGHESTMODSEQ+ status attribute.
563
+ # - Updates #select and #examine with the +condstore+ modifier, and adds
564
+ # either a +HIGHESTMODSEQ+ or +NOMODSEQ+ ResponseCode to the responses.
565
+ # - Updates #search, #uid_search, #sort, and #uid_sort with the +MODSEQ+
566
+ # search criterion, and adds SearchResult#modseq to the search response.
567
+ # - Updates #thread and #uid_thread with the +MODSEQ+ search criterion
568
+ # <em>(but thread responses are unchanged)</em>.
569
+ # - Updates #fetch and #uid_fetch with the +changedsince+ modifier and
570
+ # +MODSEQ+ FetchData attribute.
571
+ # - Updates #store and #uid_store with the +unchangedsince+ modifier and adds
572
+ # the +MODIFIED+ ResponseCode to the tagged response.
573
+ #
574
+ # ==== RFC8438: <tt>STATUS=SIZE</tt>
575
+ # - Updates #status with the +SIZE+ status attribute.
576
+ #
577
+ # ==== RFC8474: +OBJECTID+
578
+ # - Adds +MAILBOXID+ ResponseCode to #create tagged response.
579
+ # - Adds +MAILBOXID+ ResponseCode to #select and #examine untagged response.
580
+ # - Updates #fetch and #uid_fetch with the +EMAILID+ and +THREADID+ items.
581
+ # See FetchData#emailid and FetchData#emailid.
582
+ # - Updates #status with support for the +MAILBOXID+ status attribute.
583
+ #
584
+ # ==== RFC9208: <tt>QUOTA=RES-*</tt>
585
+ # +NOTE:+ Only the +STORAGE+ quota resource type is currently supported.
586
+ # - Obsoletes the +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
587
+ # extension and provides strict semantics for different resource types.
588
+ # - #getquota: returns the resource usage and limits for a quota root
589
+ # - #getquotaroot: returns the list of quota roots for a mailbox, as well as
590
+ # their resource usage and limits.
591
+ # - #setquota: sets the resource limits for a given quota root.
592
+ # - Updates #status with <tt>"DELETED"</tt> and +DELETED-STORAGE+ attributes.
593
+ #
594
+ # ==== RFC9394: +PARTIAL+
595
+ # - Updates #search, #uid_search with the +PARTIAL+ return option which adds
596
+ # ESearchResult#partial return data.
597
+ # - Updates #uid_fetch with the +partial+ modifier.
598
+ #
599
+ # ==== RFC9586: +UIDONLY+
600
+ # - Updates #enable with +UIDONLY+ parameter.
601
+ # - Updates #uid_fetch and #uid_store to return +UIDFETCH+ response.
602
+ # - Updates #expunge and #uid_expunge to return +VANISHED+ response.
603
+ # - Prohibits use of message sequence numbers in responses or requests.
604
+ #
605
+ # == References
606
+ #
607
+ # [{IMAP4rev1}[https://www.rfc-editor.org/rfc/rfc3501.html]]::
608
+ # Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - \VERSION 4rev1",
609
+ # RFC 3501, DOI 10.17487/RFC3501, March 2003,
610
+ # <https://www.rfc-editor.org/info/rfc3501>.
611
+ #
612
+ # [IMAP-ABNF-EXT[https://www.rfc-editor.org/rfc/rfc4466.html]]::
613
+ # Melnikov, A. and C. Daboo, "Collected Extensions to IMAP4 ABNF",
614
+ # RFC 4466, DOI 10.17487/RFC4466, April 2006,
615
+ # <https://www.rfc-editor.org/info/rfc4466>.
616
+ #
617
+ # <em>Note: Net::IMAP cannot parse the entire RFC4466 grammar yet.</em>
618
+ #
619
+ # [{IMAP4rev2}[https://www.rfc-editor.org/rfc/rfc9051.html]]::
620
+ # Melnikov, A., Ed., and B. Leiba, Ed., "Internet Message Access Protocol
621
+ # (\IMAP) - Version 4rev2", RFC 9051, DOI 10.17487/RFC9051, August 2021,
622
+ # <https://www.rfc-editor.org/info/rfc9051>.
623
+ #
624
+ # <em>Note: Net::IMAP is not fully compatible with IMAP4rev2 yet.</em>
625
+ #
626
+ # [IMAP-IMPLEMENTATION[https://www.rfc-editor.org/info/rfc2683]]::
627
+ # Leiba, B., "IMAP4 Implementation Recommendations",
628
+ # RFC 2683, DOI 10.17487/RFC2683, September 1999,
629
+ # <https://www.rfc-editor.org/info/rfc2683>.
630
+ #
631
+ # [IMAP-MULTIACCESS[https://www.rfc-editor.org/info/rfc2180]]::
632
+ # Gahrns, M., "IMAP4 Multi-Accessed Mailbox Practice", RFC 2180, DOI
633
+ # 10.17487/RFC2180, July 1997, <https://www.rfc-editor.org/info/rfc2180>.
634
+ #
635
+ # [UTF7[https://www.rfc-editor.org/rfc/rfc2152]]::
636
+ # Goldsmith, D. and M. Davis, "UTF-7 A Mail-Safe Transformation Format of
637
+ # Unicode", RFC 2152, DOI 10.17487/RFC2152, May 1997,
638
+ # <https://www.rfc-editor.org/info/rfc2152>.
639
+ #
640
+ # === Message envelope and body structure
641
+ #
642
+ # [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]::
643
+ # Resnick, P., Ed., "Internet Message Format",
644
+ # RFC 5322, DOI 10.17487/RFC5322, October 2008,
645
+ # <https://www.rfc-editor.org/info/rfc5322>.
646
+ #
647
+ # <em>Note: obsoletes</em>
648
+ # RFC-2822[https://www.rfc-editor.org/rfc/rfc2822]<em> (April 2001) and</em>
649
+ # RFC-822[https://www.rfc-editor.org/rfc/rfc822]<em> (August 1982).</em>
650
+ #
651
+ # [CHARSET[https://www.rfc-editor.org/rfc/rfc2978]]::
652
+ # Freed, N. and J. Postel, "IANA Charset Registration Procedures", BCP 19,
653
+ # RFC 2978, DOI 10.17487/RFC2978, October 2000,
654
+ # <https://www.rfc-editor.org/info/rfc2978>.
655
+ #
656
+ # [DISPOSITION[https://www.rfc-editor.org/rfc/rfc2183]]::
657
+ # Troost, R., Dorner, S., and K. Moore, Ed., "Communicating Presentation
658
+ # Information in Internet Messages: The Content-Disposition Header
659
+ # Field", RFC 2183, DOI 10.17487/RFC2183, August 1997,
660
+ # <https://www.rfc-editor.org/info/rfc2183>.
661
+ #
662
+ # [MIME-IMB[https://www.rfc-editor.org/rfc/rfc2045]]::
663
+ # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
664
+ # (MIME) Part One: Format of Internet Message Bodies",
665
+ # RFC 2045, DOI 10.17487/RFC2045, November 1996,
666
+ # <https://www.rfc-editor.org/info/rfc2045>.
667
+ #
668
+ # [MIME-IMT[https://www.rfc-editor.org/rfc/rfc2046]]::
669
+ # Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions
670
+ # (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046,
671
+ # November 1996, <https://www.rfc-editor.org/info/rfc2046>.
672
+ #
673
+ # [MIME-HDRS[https://www.rfc-editor.org/rfc/rfc2047]]::
674
+ # Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part Three:
675
+ # Message Header Extensions for Non-ASCII Text",
676
+ # RFC 2047, DOI 10.17487/RFC2047, November 1996,
677
+ # <https://www.rfc-editor.org/info/rfc2047>.
678
+ #
679
+ # [RFC2231[https://www.rfc-editor.org/rfc/rfc2231]]::
680
+ # Freed, N. and K. Moore, "MIME Parameter Value and Encoded Word
681
+ # Extensions: Character Sets, Languages, and Continuations",
682
+ # RFC 2231, DOI 10.17487/RFC2231, November 1997,
683
+ # <https://www.rfc-editor.org/info/rfc2231>.
684
+ #
685
+ # [I18n-HDRS[https://www.rfc-editor.org/rfc/rfc6532]]::
686
+ # Yang, A., Steele, S., and N. Freed, "Internationalized Email Headers",
687
+ # RFC 6532, DOI 10.17487/RFC6532, February 2012,
688
+ # <https://www.rfc-editor.org/info/rfc6532>.
689
+ #
690
+ # [LANGUAGE-TAGS[https://www.rfc-editor.org/info/rfc3282]]::
691
+ # Alvestrand, H., "Content Language Headers",
692
+ # RFC 3282, DOI 10.17487/RFC3282, May 2002,
693
+ # <https://www.rfc-editor.org/info/rfc3282>.
694
+ #
695
+ # [LOCATION[https://www.rfc-editor.org/info/rfc2557]]::
696
+ # Palme, J., Hopmann, A., and N. Shelness, "MIME Encapsulation of
697
+ # Aggregate Documents, such as HTML (MHTML)",
698
+ # RFC 2557, DOI 10.17487/RFC2557, March 1999,
699
+ # <https://www.rfc-editor.org/info/rfc2557>.
700
+ #
701
+ # [MD5[https://www.rfc-editor.org/rfc/rfc1864]]::
702
+ # Myers, J. and M. Rose, "The Content-MD5 Header Field",
703
+ # RFC 1864, DOI 10.17487/RFC1864, October 1995,
704
+ # <https://www.rfc-editor.org/info/rfc1864>.
705
+ #
706
+ # [RFC3503[https://www.rfc-editor.org/rfc/rfc3503]]::
707
+ # Melnikov, A., "Message Disposition Notification (MDN)
708
+ # profile for Internet Message Access Protocol (IMAP)",
709
+ # RFC 3503, DOI 10.17487/RFC3503, March 2003,
710
+ # <https://www.rfc-editor.org/info/rfc3503>.
711
+ #
712
+ # === \IMAP Extensions
713
+ #
714
+ # [QUOTA[https://www.rfc-editor.org/rfc/rfc2087]]::
715
+ # Myers, J., "IMAP4 QUOTA extension", RFC 2087, DOI 10.17487/RFC2087,
716
+ # January 1997, <https://www.rfc-editor.org/info/rfc2087>.
717
+ #
718
+ # *NOTE*: _obsoleted_ by RFC9208[https://www.rfc-editor.org/rfc/rfc9208]
719
+ # (March 2022).
720
+ # [IDLE[https://www.rfc-editor.org/rfc/rfc2177]]::
721
+ # Leiba, B., "IMAP4 IDLE command", RFC 2177, DOI 10.17487/RFC2177,
722
+ # June 1997, <https://www.rfc-editor.org/info/rfc2177>.
723
+ # [NAMESPACE[https://www.rfc-editor.org/rfc/rfc2342]]::
724
+ # Gahrns, M. and C. Newman, "IMAP4 Namespace", RFC 2342,
725
+ # DOI 10.17487/RFC2342, May 1998, <https://www.rfc-editor.org/info/rfc2342>.
726
+ # [ID[https://www.rfc-editor.org/rfc/rfc2971]]::
727
+ # Showalter, T., "IMAP4 ID extension", RFC 2971, DOI 10.17487/RFC2971,
728
+ # October 2000, <https://www.rfc-editor.org/info/rfc2971>.
729
+ # [BINARY[https://www.rfc-editor.org/rfc/rfc3516]]::
730
+ # Nerenberg, L., "IMAP4 Binary Content Extension", RFC 3516,
731
+ # DOI 10.17487/RFC3516, April 2003,
732
+ # <https://www.rfc-editor.org/info/rfc3516>.
733
+ # [ACL[https://www.rfc-editor.org/rfc/rfc4314]]::
734
+ # Melnikov, A., "IMAP4 Access Control List (ACL) Extension", RFC 4314,
735
+ # DOI 10.17487/RFC4314, December 2005,
736
+ # <https://www.rfc-editor.org/info/rfc4314>.
737
+ # [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]]::
738
+ # Crispin, M., "Internet Message Access Protocol (\IMAP) - UIDPLUS
739
+ # extension", RFC 4315, DOI 10.17487/RFC4315, December 2005,
740
+ # <https://www.rfc-editor.org/info/rfc4315>.
741
+ # [SORT[https://www.rfc-editor.org/rfc/rfc5256]]::
742
+ # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
743
+ # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
744
+ # <https://www.rfc-editor.org/info/rfc5256>.
745
+ # [THREAD[https://www.rfc-editor.org/rfc/rfc5256]]::
746
+ # Crispin, M. and K. Murchison, "Internet Message Access Protocol - SORT and
747
+ # THREAD Extensions", RFC 5256, DOI 10.17487/RFC5256, June 2008,
748
+ # <https://www.rfc-editor.org/info/rfc5256>.
749
+ # [RFC5530[https://www.rfc-editor.org/rfc/rfc5530.html]]::
750
+ # Gulbrandsen, A., "IMAP Response Codes", RFC 5530, DOI 10.17487/RFC5530,
751
+ # May 2009, <https://www.rfc-editor.org/info/rfc5530>.
752
+ # [MOVE[https://www.rfc-editor.org/rfc/rfc6851]]::
753
+ # Gulbrandsen, A. and N. Freed, Ed., "Internet Message Access Protocol
754
+ # (\IMAP) - MOVE Extension", RFC 6851, DOI 10.17487/RFC6851, January 2013,
755
+ # <https://www.rfc-editor.org/info/rfc6851>.
756
+ # [UTF8=ACCEPT[https://www.rfc-editor.org/rfc/rfc6855]]::
757
+ # [UTF8=ONLY[https://www.rfc-editor.org/rfc/rfc6855]]::
758
+ # Resnick, P., Ed., Newman, C., Ed., and S. Shen, Ed.,
759
+ # "IMAP Support for UTF-8", RFC 6855, DOI 10.17487/RFC6855, March 2013,
760
+ # <https://www.rfc-editor.org/info/rfc6855>.
761
+ # [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162]]::
762
+ # [QRESYNC[https://www.rfc-editor.org/rfc/rfc7162]]::
763
+ # Melnikov, A. and D. Cridland, "IMAP Extensions: Quick Flag Changes
764
+ # Resynchronization (CONDSTORE) and Quick Mailbox Resynchronization
765
+ # (QRESYNC)", RFC 7162, DOI 10.17487/RFC7162, May 2014,
766
+ # <https://www.rfc-editor.org/info/rfc7162>.
767
+ # [OBJECTID[https://www.rfc-editor.org/rfc/rfc8474]]::
768
+ # Gondwana, B., Ed., "IMAP Extension for Object Identifiers",
769
+ # RFC 8474, DOI 10.17487/RFC8474, September 2018,
770
+ # <https://www.rfc-editor.org/info/rfc8474>.
771
+ # [{QUOTA=RES-*}[https://www.rfc-editor.org/rfc/rfc9208]]::
772
+ # Melnikov, A., "IMAP QUOTA Extension", RFC 9208, DOI 10.17487/RFC9208,
773
+ # March 2022, <https://www.rfc-editor.org/info/rfc9208>.
774
+ #
775
+ # Obsoletes RFC2087[https://www.rfc-editor.org/rfc/rfc2087].
776
+ # [PARTIAL[https://www.rfc-editor.org/info/rfc9394]]::
777
+ # Melnikov, A., Achuthan, A., Nagulakonda, V., and L. Alves,
778
+ # "IMAP PARTIAL Extension for Paged SEARCH and FETCH", RFC 9394,
779
+ # DOI 10.17487/RFC9394, June 2023,
780
+ # <https://www.rfc-editor.org/info/rfc9394>.
781
+ # [UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.pdf]]::
782
+ # Melnikov, A., Achuthan, A., Nagulakonda, V., Singh, A., and L. Alves,
783
+ # "\IMAP Extension for Using and Returning Unique Identifiers (UIDs) Only",
784
+ # RFC 9586, DOI 10.17487/RFC9586, May 2024,
785
+ # <https://www.rfc-editor.org/info/rfc9586>.
786
+ #
787
+ # === IANA registries
788
+ # * {IMAP Capabilities}[http://www.iana.org/assignments/imap4-capabilities]
789
+ # * {IMAP Quota Resource Types}[http://www.iana.org/assignments/imap4-capabilities#imap-capabilities-2]
790
+ # * {IMAP Response Codes}[https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml]
791
+ # * {IMAP Mailbox Name Attributes}[https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml]
792
+ # * {IMAP and JMAP Keywords}[https://www.iana.org/assignments/imap-jmap-keywords/imap-jmap-keywords.xhtml]
793
+ # * {IMAP Threading Algorithms}[https://www.iana.org/assignments/imap-threading-algorithms/imap-threading-algorithms.xhtml]
794
+ # * {SASL Mechanisms and SASL SCRAM Family Mechanisms}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
795
+ # * {Service Name and Transport Protocol Port Number Registry}[https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml]:
796
+ # +imap+: tcp/143, +imaps+: tcp/993
797
+ # * {GSSAPI/Kerberos/SASL Service Names}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml]:
798
+ # +imap+
799
+ # * {Character sets}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
800
+ #
801
+ # ==== For currently unsupported features:
802
+ # * {LIST-EXTENDED options and responses}[https://www.iana.org/assignments/imap-list-extended/imap-list-extended.xhtml]
803
+ # * {IMAP METADATA Server Entry and Mailbox Entry Registries}[https://www.iana.org/assignments/imap-metadata/imap-metadata.xhtml]
804
+ # * {IMAP ANNOTATE Extension Entries and Attributes}[https://www.iana.org/assignments/imap-annotate-extension/imap-annotate-extension.xhtml]
805
+ # * {IMAP URLAUTH Access Identifiers and Prefixes}[https://www.iana.org/assignments/urlauth-access-ids/urlauth-access-ids.xhtml]
806
+ # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
807
+ #
808
+ class IMAP < Protocol
809
+ VERSION = "0.5.15"
810
+
811
+ # Aliases for supported capabilities, to be used with the #enable command.
812
+ ENABLE_ALIASES = {
813
+ utf8: "UTF8=ACCEPT",
814
+ "UTF8=ONLY" => "UTF8=ACCEPT",
815
+ }.freeze
816
+
817
+ dir = File.expand_path("imap", __dir__)
818
+ autoload :ConnectionState, "#{dir}/connection_state"
819
+ autoload :ResponseReader, "#{dir}/response_reader"
820
+ autoload :SASL, "#{dir}/sasl"
821
+ autoload :SASLAdapter, "#{dir}/sasl_adapter"
822
+ autoload :SequenceSet, "#{dir}/sequence_set"
823
+ autoload :StringPrep, "#{dir}/stringprep"
824
+
825
+ include MonitorMixin
826
+ if defined?(OpenSSL::SSL)
827
+ include OpenSSL
828
+ include SSL
829
+ end
830
+
831
+ # :call-seq:
832
+ # Net::IMAP::SequenceSet(set = nil) -> SequenceSet
833
+ #
834
+ # Coerces +set+ into a SequenceSet, using either SequenceSet.try_convert or
835
+ # SequenceSet.new.
836
+ #
837
+ # * When +set+ is a SequenceSet, that same set is returned.
838
+ # * When +set+ responds to +to_sequence_set+, +set.to_sequence_set+ is
839
+ # returned.
840
+ # * Otherwise, returns the result from calling SequenceSet.new with +set+.
841
+ #
842
+ # Related: SequenceSet.try_convert, SequenceSet.new, SequenceSet::[]
843
+ def self.SequenceSet(set = nil)
844
+ SequenceSet.try_convert(set) || SequenceSet.new(set)
845
+ end
846
+
847
+ # Returns the global Config object
848
+ def self.config; Config.global end
849
+
850
+ # Returns the global debug mode.
851
+ # Delegates to {Net::IMAP.config.debug}[rdoc-ref:Config#debug].
852
+ def self.debug; config.debug end
853
+
854
+ # Sets the global debug mode.
855
+ # Delegates to {Net::IMAP.config.debug=}[rdoc-ref:Config#debug=].
856
+ def self.debug=(val)
857
+ config.debug = val
858
+ end
859
+
860
+ # The default port for IMAP connections, port 143
861
+ def self.default_port
862
+ return PORT
863
+ end
864
+
865
+ # The default port for IMAPS connections, port 993
866
+ def self.default_tls_port
867
+ return SSL_PORT
868
+ end
869
+
870
+ class << self
871
+ alias default_imap_port default_port
872
+ alias default_imaps_port default_tls_port
873
+ alias default_ssl_port default_tls_port
874
+ end
875
+
876
+ # Returns the initial greeting sent by the server, an UntaggedResponse.
877
+ attr_reader :greeting
878
+
879
+ # The client configuration. See Net::IMAP::Config.
880
+ #
881
+ # By default, the client's local configuration inherits from the global
882
+ # Net::IMAP.config.
883
+ attr_reader :config
884
+
885
+ ##
886
+ # :attr_reader: open_timeout
887
+ # Seconds to wait until a connection is opened. Also used by #starttls.
888
+ # Delegates to {config.open_timeout}[rdoc-ref:Config#open_timeout].
889
+
890
+ ##
891
+ # :attr_reader: idle_response_timeout
892
+ # Seconds to wait until an IDLE response is received.
893
+ # Delegates to {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout].
894
+
895
+ ##
896
+ # :attr_accessor: max_response_size
897
+ #
898
+ # The maximum allowed server response size, in bytes.
899
+ # Delegates to {config.max_response_size}[rdoc-ref:Config#max_response_size].
900
+
901
+ # :stopdoc:
902
+ def open_timeout; config.open_timeout end
903
+ def idle_response_timeout; config.idle_response_timeout end
904
+ def max_response_size; config.max_response_size end
905
+ def max_response_size=(val) config.max_response_size = val end
906
+ # :startdoc:
907
+
908
+ # The hostname this client connected to
909
+ attr_reader :host
910
+
911
+ # The port this client connected to
912
+ attr_reader :port
913
+
914
+ # Returns the
915
+ # {SSLContext}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html]
916
+ # used by the SSLSocket when TLS is attempted, even when the TLS handshake
917
+ # is unsuccessful. The context object will be frozen.
918
+ #
919
+ # Returns +nil+ for a plaintext connection.
920
+ attr_reader :ssl_ctx
921
+
922
+ # Returns the parameters that were sent to #ssl_ctx
923
+ # {set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params]
924
+ # when the connection tries to use TLS (even when unsuccessful).
925
+ #
926
+ # Returns +false+ for a plaintext connection.
927
+ attr_reader :ssl_ctx_params
928
+
929
+ # Returns the current connection state.
930
+ #
931
+ # Once an IMAP connection is established, the connection is in one of four
932
+ # states: +not_authenticated+, +authenticated+, +selected+, and +logout+.
933
+ # Most commands are valid only in certain states.
934
+ #
935
+ # The connection state object responds to +to_sym+ and +name+ with the name
936
+ # of the current connection state, as a Symbol or String. Future versions
937
+ # of +net-imap+ may store additional information on the state object.
938
+ #
939
+ # From {RFC9051}[https://www.rfc-editor.org/rfc/rfc9051#section-3]:
940
+ # +----------------------+
941
+ # |connection established|
942
+ # +----------------------+
943
+ # ||
944
+ # \/
945
+ # +--------------------------------------+
946
+ # | server greeting |
947
+ # +--------------------------------------+
948
+ # || (1) || (2) || (3)
949
+ # \/ || ||
950
+ # +-----------------+ || ||
951
+ # |Not Authenticated| || ||
952
+ # +-----------------+ || ||
953
+ # || (7) || (4) || ||
954
+ # || \/ \/ ||
955
+ # || +----------------+ ||
956
+ # || | Authenticated |<=++ ||
957
+ # || +----------------+ || ||
958
+ # || || (7) || (5) || (6) ||
959
+ # || || \/ || ||
960
+ # || || +--------+ || ||
961
+ # || || |Selected|==++ ||
962
+ # || || +--------+ ||
963
+ # || || || (7) ||
964
+ # \/ \/ \/ \/
965
+ # +--------------------------------------+
966
+ # | Logout |
967
+ # +--------------------------------------+
968
+ # ||
969
+ # \/
970
+ # +-------------------------------+
971
+ # |both sides close the connection|
972
+ # +-------------------------------+
973
+ #
974
+ # >>>
975
+ # Legend for the above diagram:
976
+ #
977
+ # 1. connection without pre-authentication (+OK+ #greeting)
978
+ # 2. pre-authenticated connection (+PREAUTH+ #greeting)
979
+ # 3. rejected connection (+BYE+ #greeting)
980
+ # 4. successful #login or #authenticate command
981
+ # 5. successful #select or #examine command
982
+ # 6. #close or #unselect command, unsolicited +CLOSED+ response code, or
983
+ # failed #select or #examine command
984
+ # 7. #logout command, server shutdown, or connection closed
985
+ #
986
+ # Before the server greeting, the state is +not_authenticated+.
987
+ # After the connection closes, the state remains +logout+.
988
+ attr_reader :connection_state
989
+
990
+ # Creates a new Net::IMAP object and connects it to the specified
991
+ # +host+.
992
+ #
993
+ # ==== Options
994
+ #
995
+ # Accepts the following options:
996
+ #
997
+ # [port]
998
+ # Port number. Defaults to 993 when +ssl+ is truthy, and 143 otherwise.
999
+ #
1000
+ # [ssl]
1001
+ # If +true+, the connection will use TLS with the default params set by
1002
+ # {OpenSSL::SSL::SSLContext#set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params].
1003
+ # If +ssl+ is a hash, it's passed to
1004
+ # {OpenSSL::SSL::SSLContext#set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params];
1005
+ # the keys are names of attribute assignment methods on
1006
+ # SSLContext[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html]. For example:
1007
+ #
1008
+ # [{ca_file}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-ca_file]]
1009
+ # The path to a file containing a PEM-format CA certificate.
1010
+ # [{ca_path}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-ca_path]]
1011
+ # The path to a directory containing CA certificates in PEM format.
1012
+ # [{min_version}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D]]
1013
+ # Sets the lower bound on the supported SSL/TLS protocol version. Set to
1014
+ # an +OpenSSL+ constant such as +OpenSSL::SSL::TLS1_2_VERSION+,
1015
+ # [{verify_mode}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_mode]]
1016
+ # SSL session verification mode. Valid modes include
1017
+ # +OpenSSL::SSL::VERIFY_PEER+ and +OpenSSL::SSL::VERIFY_NONE+.
1018
+ #
1019
+ # See {OpenSSL::SSL::SSLContext}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html] for other valid SSL context params.
1020
+ #
1021
+ # See DeprecatedClientOptions.new for deprecated SSL arguments.
1022
+ #
1023
+ # [response_handlers]
1024
+ # A list of response handlers to be added before the receiver thread is
1025
+ # started. This ensures every server response is handled, including the
1026
+ # #greeting. Note that the greeting is handled in the current thread, but
1027
+ # all other responses are handled in the receiver thread.
1028
+ #
1029
+ # [config]
1030
+ # A Net::IMAP::Config object to use as the basis for #config. By default,
1031
+ # the global Net::IMAP.config is used.
1032
+ #
1033
+ # >>>
1034
+ # *NOTE:* +config+ does not set #config directly---it sets the _parent_
1035
+ # config for inheritance. Every client creates its own unique #config.
1036
+ #
1037
+ # All other keyword arguments are forwarded to Net::IMAP::Config.new, to
1038
+ # initialize the client's #config. For example:
1039
+ #
1040
+ # [{open_timeout}[rdoc-ref:Config#open_timeout]]
1041
+ # Seconds to wait until a connection is opened
1042
+ # [{idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]]
1043
+ # Seconds to wait until an IDLE response is received
1044
+ #
1045
+ # See Net::IMAP::Config for other valid options.
1046
+ #
1047
+ # ==== Examples
1048
+ #
1049
+ # Connect to cleartext port 143 at mail.example.com and receive the server greeting:
1050
+ # imap = Net::IMAP.new('mail.example.com', ssl: false) # => #<Net::IMAP:0x00007f79b0872bd0>
1051
+ # imap.port => 143
1052
+ # imap.tls_verified? => false
1053
+ # imap.greeting => name: ("OK" | "PREAUTH") => status
1054
+ # status # => "OK"
1055
+ # # The client is connected in the "Not Authenticated" state.
1056
+ #
1057
+ # Connect with TLS to port 993
1058
+ # imap = Net::IMAP.new('mail.example.com', ssl: true) # => #<Net::IMAP:0x00007f79b0872bd0>
1059
+ # imap.port => 993
1060
+ # imap.tls_verified? => true
1061
+ # imap.greeting => name: (/OK/i | /PREAUTH/i) => status
1062
+ # case status
1063
+ # in /OK/i
1064
+ # # The client is connected in the "Not Authenticated" state.
1065
+ # imap.authenticate("PLAIN", "joe_user", "joes_password")
1066
+ # in /PREAUTH/i
1067
+ # # The client is connected in the "Authenticated" state.
1068
+ # end
1069
+ #
1070
+ # Connect with prior authentication, for example using an SSL certificate:
1071
+ # ssl_ctx_params = {
1072
+ # cert: OpenSSL::X509::Certificate.new(File.read("client.crt")),
1073
+ # key: OpenSSL::PKey::EC.new(File.read('client.key')),
1074
+ # extra_chain_cert: [
1075
+ # OpenSSL::X509::Certificate.new(File.read("intermediate.crt")),
1076
+ # ],
1077
+ # }
1078
+ # imap = Net::IMAP.new('mail.example.com', ssl: ssl_ctx_params)
1079
+ # imap.port => 993
1080
+ # imap.tls_verified? => true
1081
+ # imap.greeting => name: "PREAUTH"
1082
+ # # The client is connected in the "Authenticated" state.
1083
+ #
1084
+ # ==== Exceptions
1085
+ #
1086
+ # The most common errors are:
1087
+ #
1088
+ # [Errno::ECONNREFUSED]
1089
+ # Connection refused by +host+ or an intervening firewall.
1090
+ # [Errno::ETIMEDOUT]
1091
+ # Connection timed out (possibly due to packets being dropped by an
1092
+ # intervening firewall).
1093
+ # [Errno::ENETUNREACH]
1094
+ # There is no route to that network.
1095
+ # [SocketError]
1096
+ # Hostname not known or other socket error.
1097
+ # [Net::IMAP::ByeResponseError]
1098
+ # Connected to the host successfully, but it immediately said goodbye.
1099
+ #
1100
+ def initialize(host, port: nil, ssl: nil, response_handlers: nil,
1101
+ config: Config.global, **config_options)
1102
+ super()
1103
+ # Config options
1104
+ @host = host
1105
+ @config = Config.new(config, **config_options)
1106
+ @port = port || (ssl ? SSL_PORT : PORT)
1107
+ @ssl_ctx_params, @ssl_ctx = build_ssl_ctx(ssl)
1108
+
1109
+ # Basic Client State
1110
+ @utf8_strings = false
1111
+ @debug_output_bol = true
1112
+ @exception = nil
1113
+ @greeting = nil
1114
+ @capabilities = nil
1115
+ @tls_verified = false
1116
+ @connection_state = ConnectionState::NotAuthenticated.new
1117
+
1118
+ # Client Protocol Receiver
1119
+ @parser = ResponseParser.new(config: @config)
1120
+ @responses = Hash.new {|h, k| h[k] = [] }
1121
+ @response_handlers = []
1122
+ @receiver_thread = nil
1123
+ @receiver_thread_exception = nil
1124
+ @receiver_thread_terminating = false
1125
+ response_handlers&.each do add_response_handler(_1) end
1126
+
1127
+ # Client Protocol Sender (including state for currently running commands)
1128
+ @tag_prefix = "RUBY"
1129
+ @tagno = 0
1130
+ @tagged_responses = {}
1131
+ @tagged_response_arrival = new_cond
1132
+ @continued_command_tag = nil
1133
+ @continuation_request_arrival = new_cond
1134
+ @continuation_request_exception = nil
1135
+ @idle_done_cond = nil
1136
+ @logout_command_tag = nil
1137
+
1138
+ # Connection
1139
+ @sock = tcp_socket(@host, @port)
1140
+ @reader = ResponseReader.new(self, @sock)
1141
+ start_tls_session if ssl_ctx
1142
+ start_imap_connection
1143
+ end
1144
+
1145
+ # Returns true after the TLS negotiation has completed and the remote
1146
+ # hostname has been verified. Returns false when TLS has been established
1147
+ # but peer verification was disabled.
1148
+ def tls_verified?; @tls_verified end
1149
+
1150
+ # Disconnects from the server.
1151
+ #
1152
+ # Waits for receiver thread to close before returning, except when called
1153
+ # from inside the connection mutex such as from a response handler. Slow or
1154
+ # stuck response handlers can cause #disconnect to hang until they complete.
1155
+ #
1156
+ # Related: #logout, #logout!
1157
+ def disconnect
1158
+ in_logout_state = try_state_logout?
1159
+ return if disconnected?
1160
+ in_receiver_thread = Thread.current == @receiver_thread
1161
+ begin
1162
+ @sock.to_io.shutdown
1163
+ rescue Errno::ENOTCONN
1164
+ # ignore `Errno::ENOTCONN: Socket is not connected' on some platforms.
1165
+ rescue Exception => e
1166
+ @receiver_thread.raise(e) unless in_receiver_thread
1167
+ end
1168
+ @sock.close
1169
+ @receiver_thread.join unless mon_owned? || in_receiver_thread
1170
+ raise e if e
1171
+ ensure
1172
+ # Try again after shutting down the receiver thread. With no reciever
1173
+ # left to wait for, any remaining locks should be _very_ brief.
1174
+ state_logout! unless in_logout_state
1175
+ end
1176
+
1177
+ # Returns true if disconnected from the server.
1178
+ #
1179
+ # Related: #logout, #disconnect
1180
+ def disconnected?
1181
+ return @sock.closed?
1182
+ end
1183
+
1184
+ # Returns whether the server supports a given +capability+. When available,
1185
+ # cached #capabilities are used without sending a new #capability command to
1186
+ # the server.
1187
+ #
1188
+ # <em>*NOTE:* Most Net::IMAP methods do not _currently_ modify their
1189
+ # behaviour according to the server's advertised #capabilities.</em>
1190
+ #
1191
+ # See Net::IMAP@Capabilities for more about \IMAP capabilities.
1192
+ #
1193
+ # Related: #auth_capable?, #capabilities, #capability, #enable
1194
+ def capable?(capability) capabilities.include? capability.to_s.upcase end
1195
+ alias capability? capable?
1196
+
1197
+ # Returns the server capabilities. When available, cached capabilities are
1198
+ # used without sending a new #capability command to the server.
1199
+ #
1200
+ # To ensure a case-insensitive comparison, #capable? can be used instead.
1201
+ #
1202
+ # <em>*NOTE:* Most Net::IMAP methods do not _currently_ modify their
1203
+ # behaviour according to the server's advertised #capabilities.</em>
1204
+ #
1205
+ # See Net::IMAP@Capabilities for more about \IMAP capabilities.
1206
+ #
1207
+ # Related: #capable?, #auth_capable?, #auth_mechanisms, #capability, #enable
1208
+ def capabilities
1209
+ @capabilities || capability
1210
+ end
1211
+
1212
+ # Returns the #authenticate mechanisms that the server claims to support.
1213
+ # These are derived from the #capabilities with an <tt>AUTH=</tt> prefix.
1214
+ #
1215
+ # This may be different when the connection is cleartext or using TLS. Most
1216
+ # servers will drop all <tt>AUTH=</tt> mechanisms from #capabilities after
1217
+ # the connection has authenticated.
1218
+ #
1219
+ # imap = Net::IMAP.new(hostname, ssl: false)
1220
+ # imap.capabilities # => ["IMAP4REV1", "LOGINDISABLED"]
1221
+ # imap.auth_mechanisms # => []
1222
+ #
1223
+ # imap.starttls
1224
+ # imap.capabilities # => ["IMAP4REV1", "AUTH=PLAIN", "AUTH=XOAUTH2",
1225
+ # # "AUTH=OAUTHBEARER"]
1226
+ # imap.auth_mechanisms # => ["PLAIN", "XOAUTH2", "OAUTHBEARER"]
1227
+ #
1228
+ # imap.authenticate("XOAUTH2", username, oauth2_access_token)
1229
+ # imap.auth_mechanisms # => []
1230
+ #
1231
+ # Related: #authenticate, #auth_capable?, #capabilities
1232
+ def auth_mechanisms
1233
+ capabilities
1234
+ .grep(/\AAUTH=/i)
1235
+ .map { _1.delete_prefix("AUTH=") }
1236
+ end
1237
+
1238
+ # Returns whether the server supports a given SASL +mechanism+ for use with
1239
+ # the #authenticate command. The +mechanism+ is supported when
1240
+ # #capabilities includes <tt>"AUTH=#{mechanism.to_s.upcase}"</tt>. When
1241
+ # available, cached capabilities are used without sending a new #capability
1242
+ # command to the server.
1243
+ #
1244
+ # imap.capable? "AUTH=PLAIN" # => true
1245
+ # imap.auth_capable? "PLAIN" # => true
1246
+ # imap.auth_capable? "blurdybloop" # => false
1247
+ #
1248
+ # Related: #authenticate, #auth_mechanisms, #capable?, #capabilities
1249
+ def auth_capable?(mechanism)
1250
+ capable? "AUTH=#{mechanism}"
1251
+ end
1252
+
1253
+ # Returns whether capabilities have been cached. When true, #capable? and
1254
+ # #capabilities don't require sending a #capability command to the server.
1255
+ #
1256
+ # See Net::IMAP@Capabilities for more about \IMAP capabilities.
1257
+ #
1258
+ # Related: #capable?, #capability, #clear_cached_capabilities
1259
+ def capabilities_cached?
1260
+ !!@capabilities
1261
+ end
1262
+
1263
+ # Clears capabilities that have been remembered by the Net::IMAP client.
1264
+ # This forces a #capability command to be sent the next time a #capabilities
1265
+ # query method is called.
1266
+ #
1267
+ # Net::IMAP automatically discards its cached capabilities when they can
1268
+ # change. Explicitly calling this _should_ be unnecessary for well-behaved
1269
+ # servers.
1270
+ #
1271
+ # Related: #capable?, #capability, #capabilities_cached?
1272
+ def clear_cached_capabilities
1273
+ synchronize do
1274
+ clear_responses("CAPABILITY")
1275
+ @capabilities = nil
1276
+ end
1277
+ end
1278
+
1279
+ # Sends a {CAPABILITY command [IMAP4rev1 §6.1.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.1]
1280
+ # and returns an array of capabilities that are supported by the server.
1281
+ # The result is stored for use by #capable? and #capabilities.
1282
+ #
1283
+ # <em>*NOTE:* Most Net::IMAP methods do not _currently_ modify their
1284
+ # behaviour according to the server's advertised #capabilities.</em>
1285
+ #
1286
+ # Net::IMAP automatically stores and discards capability data according to
1287
+ # the requirements and recommendations in
1288
+ # {IMAP4rev2 §6.1.1}[https://www.rfc-editor.org/rfc/rfc9051#section-6.1.1],
1289
+ # {§6.2}[https://www.rfc-editor.org/rfc/rfc9051#section-6.2], and
1290
+ # {§7.1}[https://www.rfc-editor.org/rfc/rfc9051#section-7.1].
1291
+ # Use #capable?, #auth_capable?, or #capabilities to this cache and avoid
1292
+ # sending the #capability command unnecessarily.
1293
+ #
1294
+ # See Net::IMAP@Capabilities for more about \IMAP capabilities.
1295
+ #
1296
+ # Related: #capable?, #auth_capable?, #capability, #enable
1297
+ def capability
1298
+ synchronize do
1299
+ send_command("CAPABILITY")
1300
+ @capabilities = clear_responses("CAPABILITY").last.freeze
1301
+ end
1302
+ end
1303
+
1304
+ # Sends an {ID command [RFC2971 §3.1]}[https://www.rfc-editor.org/rfc/rfc2971#section-3.1]
1305
+ # and returns a hash of the server's response, or nil if the server does not
1306
+ # identify itself.
1307
+ #
1308
+ # Note that the user should first check if the server supports the ID
1309
+ # capability. For example:
1310
+ #
1311
+ # if capable?(:ID)
1312
+ # id = imap.id(
1313
+ # name: "my IMAP client (ruby)",
1314
+ # version: MyIMAP::VERSION,
1315
+ # "support-url": "mailto:bugs@example.com",
1316
+ # os: RbConfig::CONFIG["host_os"],
1317
+ # )
1318
+ # end
1319
+ #
1320
+ # See [ID[https://www.rfc-editor.org/rfc/rfc2971]] for field definitions.
1321
+ #
1322
+ # ==== Capabilities
1323
+ #
1324
+ # The server's capabilities must include +ID+
1325
+ # [RFC2971[https://www.rfc-editor.org/rfc/rfc2971]].
1326
+ def id(client_id=nil)
1327
+ synchronize do
1328
+ send_command("ID", ClientID.new(client_id))
1329
+ clear_responses("ID").last
1330
+ end
1331
+ end
1332
+
1333
+ # Sends a {NOOP command [IMAP4rev1 §6.1.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.2]
1334
+ # to the server.
1335
+ #
1336
+ # This allows the server to send unsolicited untagged EXPUNGE #responses,
1337
+ # but does not execute any client request. \IMAP servers are permitted to
1338
+ # send unsolicited untagged responses at any time, except for +EXPUNGE+:
1339
+ #
1340
+ # * +EXPUNGE+ can only be sent while a command is in progress.
1341
+ # * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
1342
+ # * +EXPUNGE+ may be sent during #uid_fetch, #uid_store, or #uid_search.
1343
+ #
1344
+ # Related: #idle, #check
1345
+ def noop
1346
+ send_command("NOOP")
1347
+ end
1348
+
1349
+ # Sends a {LOGOUT command [IMAP4rev1 §6.1.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.1.3]
1350
+ # to inform the command to inform the server that the client is done with
1351
+ # the connection.
1352
+ #
1353
+ # Related: #disconnect, #logout!
1354
+ def logout
1355
+ send_command("LOGOUT")
1356
+ end
1357
+
1358
+ # Calls #logout then, after receiving the TaggedResponse for the +LOGOUT+,
1359
+ # calls #disconnect. Returns the TaggedResponse from +LOGOUT+. Returns
1360
+ # +nil+ when the client is already disconnected, in contrast to #logout
1361
+ # which raises an exception.
1362
+ #
1363
+ # If #logout raises a StandardError, a warning will be printed but the
1364
+ # exception will not be re-raised.
1365
+ #
1366
+ # This is useful in situations where the connection must be dropped, for
1367
+ # example for security or after tests. If logout errors need to be handled,
1368
+ # use #logout and #disconnect instead.
1369
+ #
1370
+ # Related: #logout, #disconnect
1371
+ def logout!
1372
+ logout unless disconnected?
1373
+ rescue => ex
1374
+ warn "%s during <Net::IMAP %s:%s> logout!: %s" % [
1375
+ ex.class, host, port, ex
1376
+ ]
1377
+ ensure
1378
+ disconnect
1379
+ end
1380
+
1381
+ # Sends a {STARTTLS command [IMAP4rev1 §6.2.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.1]
1382
+ # to start a TLS session.
1383
+ #
1384
+ # Any +options+ are forwarded directly to
1385
+ # {OpenSSL::SSL::SSLContext#set_params}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-set_params];
1386
+ # the keys are names of attribute assignment methods on
1387
+ # SSLContext[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html].
1388
+ #
1389
+ # See DeprecatedClientOptions#starttls for deprecated arguments.
1390
+ #
1391
+ # This method returns after TLS negotiation and hostname verification are
1392
+ # both successful. Any error indicates that the connection has not been
1393
+ # secured.
1394
+ #
1395
+ # After the server agrees to start a TLS connection, this method waits up to
1396
+ # {config.open_timeout}[rdoc-ref:Config#open_timeout] before raising
1397
+ # +Net::OpenTimeout+.
1398
+ #
1399
+ # *Note:*
1400
+ # >>>
1401
+ # Any #response_handlers added before STARTTLS should be aware that the
1402
+ # TaggedResponse to STARTTLS is sent clear-text, _before_ TLS negotiation.
1403
+ # TLS starts immediately _after_ that response. Any response code sent
1404
+ # with the response (e.g. CAPABILITY) is insecure and cannot be trusted.
1405
+ #
1406
+ # Related: Net::IMAP.new, #login, #authenticate
1407
+ #
1408
+ # ==== Capability
1409
+ # Clients should not call #starttls unless the server advertises the
1410
+ # +STARTTLS+ capability.
1411
+ #
1412
+ # Server capabilities may change after #starttls, #login, and #authenticate.
1413
+ # Cached #capabilities will be cleared when this method completes.
1414
+ #
1415
+ def starttls(**options)
1416
+ @ssl_ctx_params, @ssl_ctx = build_ssl_ctx(options)
1417
+ handled = false
1418
+ error = nil
1419
+ ok = send_command("STARTTLS") do |resp|
1420
+ if resp.kind_of?(TaggedResponse) && resp.name == "OK"
1421
+ handled = true
1422
+ clear_cached_capabilities
1423
+ clear_responses
1424
+ start_tls_session
1425
+ end
1426
+ rescue Exception => error
1427
+ raise # note that the error backtrace is in the receiver_thread
1428
+ end
1429
+ if error
1430
+ disconnect
1431
+ raise error
1432
+ end
1433
+ unless handled
1434
+ disconnect
1435
+ raise InvalidResponseError,
1436
+ "STARTTLS handler was bypassed, although server responded %p" % [
1437
+ ok.raw_data.chomp
1438
+ ]
1439
+ end
1440
+ ok
1441
+ end
1442
+
1443
+ # :call-seq:
1444
+ # authenticate(mechanism, *, sasl_ir: config.sasl_ir, registry: Net::IMAP::SASL.authenticators, **, &) -> ok_resp
1445
+ #
1446
+ # Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
1447
+ # to authenticate the client. If successful, the connection enters the
1448
+ # "_authenticated_" state.
1449
+ #
1450
+ # +mechanism+ is the name of the \SASL authentication mechanism to be used.
1451
+ #
1452
+ # +sasl_ir+ allows or disallows sending an "initial response" (see the
1453
+ # +SASL-IR+ capability, below). Defaults to the #config value for
1454
+ # {sasl_ir}[rdoc-ref:Config#sasl_ir], which defaults to +true+.
1455
+ #
1456
+ # The +registry+ kwarg can be used to select the mechanism implementation
1457
+ # from a custom registry. See SASL.authenticator and SASL::Authenticators.
1458
+ #
1459
+ # All other arguments are forwarded to the registered SASL authenticator for
1460
+ # the requested mechanism. <em>The documentation for each individual
1461
+ # mechanism must be consulted for its specific parameters.</em>
1462
+ #
1463
+ # Related: #login, #starttls, #auth_capable?, #auth_mechanisms
1464
+ #
1465
+ # ==== Mechanisms
1466
+ #
1467
+ # Each mechanism has different properties and requirements. Please consult
1468
+ # the documentation for the specific mechanisms you are using:
1469
+ #
1470
+ # +ANONYMOUS+::
1471
+ # See AnonymousAuthenticator[rdoc-ref:Net::IMAP::SASL::AnonymousAuthenticator].
1472
+ #
1473
+ # Allows the user to gain access to public services or resources without
1474
+ # authenticating or disclosing an identity.
1475
+ #
1476
+ # +EXTERNAL+::
1477
+ # See ExternalAuthenticator[rdoc-ref:Net::IMAP::SASL::ExternalAuthenticator].
1478
+ #
1479
+ # Authenticates using already established credentials, such as a TLS
1480
+ # certificate or IPsec.
1481
+ #
1482
+ # +OAUTHBEARER+::
1483
+ # See OAuthBearerAuthenticator[rdoc-ref:Net::IMAP::SASL::OAuthBearerAuthenticator].
1484
+ #
1485
+ # Login using an OAuth2 Bearer token. This is the standard mechanism
1486
+ # for using OAuth2 with \SASL, but it is not yet deployed as widely as
1487
+ # +XOAUTH2+.
1488
+ #
1489
+ # +PLAIN+::
1490
+ # See PlainAuthenticator[rdoc-ref:Net::IMAP::SASL::PlainAuthenticator].
1491
+ #
1492
+ # Login using clear-text username and password.
1493
+ #
1494
+ # +SCRAM-SHA-1+::
1495
+ # +SCRAM-SHA-256+::
1496
+ # See ScramAuthenticator[rdoc-ref:Net::IMAP::SASL::ScramAuthenticator].
1497
+ #
1498
+ # Login by username and password. The password is not sent to the
1499
+ # server but is used in a salted challenge/response exchange.
1500
+ # +SCRAM-SHA-1+ and +SCRAM-SHA-256+ are directly supported by
1501
+ # Net::IMAP::SASL. New authenticators can easily be added for any other
1502
+ # <tt>SCRAM-*</tt> mechanism if the digest algorithm is supported by
1503
+ # OpenSSL::Digest.
1504
+ #
1505
+ # +XOAUTH2+::
1506
+ # See XOAuth2Authenticator[rdoc-ref:Net::IMAP::SASL::XOAuth2Authenticator].
1507
+ #
1508
+ # Login using a username and an OAuth2 access token. Non-standard and
1509
+ # obsoleted by +OAUTHBEARER+, but widely supported.
1510
+ #
1511
+ # See the {SASL mechanism
1512
+ # registry}[https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml]
1513
+ # for a list of all SASL mechanisms and their specifications. To register
1514
+ # new authenticators, see Authenticators.
1515
+ #
1516
+ # ===== Deprecated mechanisms
1517
+ #
1518
+ # <em>Obsolete mechanisms should be avoided, but are still available for
1519
+ # backwards compatibility. See</em> Net::IMAP::SASL@Deprecated+mechanisms.
1520
+ # <em>Using a deprecated mechanism will print a warning.</em>
1521
+ #
1522
+ # ==== Capabilities
1523
+ #
1524
+ # <tt>"AUTH=#{mechanism}"</tt> capabilities indicate server support for
1525
+ # mechanisms. Use #auth_capable? or #auth_mechanisms to check for support
1526
+ # before using a particular mechanism.
1527
+ #
1528
+ # if imap.auth_capable? "XOAUTH2"
1529
+ # imap.authenticate "XOAUTH2", username, oauth2_access_token
1530
+ # elsif imap.auth_capable? "PLAIN"
1531
+ # imap.authenticate "PLAIN", username, password
1532
+ # elsif !imap.capability? "LOGINDISABLED"
1533
+ # imap.login username, password
1534
+ # else
1535
+ # raise "No acceptable authentication mechanism is available"
1536
+ # end
1537
+ #
1538
+ # Although servers should list all supported \SASL mechanisms, they may
1539
+ # allow authentication with an unlisted +mechanism+.
1540
+ #
1541
+ # If [SASL-IR[https://www.rfc-editor.org/rfc/rfc4959.html]] is supported
1542
+ # and the appropriate <tt>"AUTH=#{mechanism}"</tt> capability is present,
1543
+ # an "initial response" may be sent as an argument to the +AUTHENTICATE+
1544
+ # command, saving a round-trip. The SASL exchange allows for server
1545
+ # challenges and client responses, but many mechanisms expect the client to
1546
+ # "respond" first. The initial response will only be sent for
1547
+ # "client-first" mechanisms.
1548
+ #
1549
+ # Server capabilities may change after #starttls, #login, and #authenticate.
1550
+ # Previously cached #capabilities will be cleared when this method
1551
+ # completes. If the TaggedResponse to #authenticate includes updated
1552
+ # capabilities, they will be cached.
1553
+ def authenticate(*args, sasl_ir: config.sasl_ir, **props, &callback)
1554
+ sasl_adapter.authenticate(*args, sasl_ir: sasl_ir, **props, &callback)
1555
+ .tap do state_authenticated! _1 end
1556
+ end
1557
+
1558
+ # Sends a {LOGIN command [IMAP4rev1 §6.2.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.3]
1559
+ # to identify the client and carries the plaintext +password+ authenticating
1560
+ # this +user+. If successful, the connection enters the "_authenticated_"
1561
+ # state.
1562
+ #
1563
+ # Using #authenticate {should be
1564
+ # preferred}[https://www.rfc-editor.org/rfc/rfc9051.html#name-login-command]
1565
+ # over #login. The LOGIN command is not the same as #authenticate with the
1566
+ # "LOGIN" +mechanism+.
1567
+ #
1568
+ # A Net::IMAP::NoResponseError is raised if authentication fails.
1569
+ #
1570
+ # Related: #authenticate, #starttls
1571
+ #
1572
+ # ==== Capabilities
1573
+ #
1574
+ # An IMAP client MUST NOT call #login when the server advertises the
1575
+ # +LOGINDISABLED+ capability. By default, Net::IMAP will raise a
1576
+ # LoginDisabledError when that capability is present. See
1577
+ # Config#enforce_logindisabled.
1578
+ #
1579
+ # Server capabilities may change after #starttls, #login, and #authenticate.
1580
+ # Cached capabilities _must_ be invalidated after this method completes.
1581
+ # The TaggedResponse to #login may include updated capabilities in its
1582
+ # ResponseCode.
1583
+ #
1584
+ def login(user, password)
1585
+ if enforce_logindisabled? && capability?("LOGINDISABLED")
1586
+ raise LoginDisabledError
1587
+ end
1588
+ send_command("LOGIN", user, password)
1589
+ .tap do state_authenticated! _1 end
1590
+ end
1591
+
1592
+ # Sends a {SELECT command [IMAP4rev1 §6.3.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.1]
1593
+ # to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
1594
+ #
1595
+ # After you have selected a mailbox, you may retrieve the number of items in
1596
+ # that mailbox from <tt>imap.responses("EXISTS", &:last)</tt>, and the
1597
+ # number of recent messages from <tt>imap.responses("RECENT", &:last)</tt>.
1598
+ # Note that these values can change if new messages arrive during a session
1599
+ # or when existing messages are expunged; see #add_response_handler for a
1600
+ # way to detect these events.
1601
+ #
1602
+ # When the +condstore+ keyword argument is true, the server is told to
1603
+ # enable the extension. If +mailbox+ supports persistence of mod-sequences,
1604
+ # the +HIGHESTMODSEQ+ ResponseCode will be sent as an untagged response to
1605
+ # #select and all `FETCH` responses will include FetchData#modseq.
1606
+ # Otherwise, the +NOMODSEQ+ ResponseCode will be sent.
1607
+ #
1608
+ # A Net::IMAP::NoResponseError is raised if the mailbox does not
1609
+ # exist or is for some reason non-selectable.
1610
+ #
1611
+ # Related: #examine
1612
+ #
1613
+ # ==== Capabilities
1614
+ #
1615
+ # If [UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]] is supported,
1616
+ # the server may return an untagged "NO" response with a "UIDNOTSTICKY"
1617
+ # response code indicating that the mailstore does not support persistent
1618
+ # UIDs:
1619
+ # imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
1620
+ #
1621
+ # If [CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html]] is supported,
1622
+ # the +condstore+ keyword parameter may be used.
1623
+ # imap.select("mbox", condstore: true)
1624
+ # modseq = imap.responses("HIGHESTMODSEQ", &:last)
1625
+ def select(mailbox, condstore: false)
1626
+ args = ["SELECT", mailbox]
1627
+ args << ["CONDSTORE"] if condstore
1628
+ synchronize do
1629
+ state_unselected! # implicitly closes current mailbox
1630
+ @responses.clear
1631
+ send_command(*args)
1632
+ .tap do state_selected! end
1633
+ end
1634
+ end
1635
+
1636
+ # Sends a {EXAMINE command [IMAP4rev1 §6.3.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.2]
1637
+ # to select a +mailbox+ so that messages in the +mailbox+ can be accessed.
1638
+ # Behaves the same as #select, except that the selected +mailbox+ is
1639
+ # identified as read-only.
1640
+ #
1641
+ # A Net::IMAP::NoResponseError is raised if the mailbox does not
1642
+ # exist or is for some reason non-examinable.
1643
+ #
1644
+ # Related: #select
1645
+ def examine(mailbox, condstore: false)
1646
+ args = ["EXAMINE", mailbox]
1647
+ args << ["CONDSTORE"] if condstore
1648
+ synchronize do
1649
+ state_unselected! # implicitly closes current mailbox
1650
+ @responses.clear
1651
+ send_command(*args)
1652
+ .tap do state_selected! end
1653
+ end
1654
+ end
1655
+
1656
+ # Sends a {CREATE command [IMAP4rev1 §6.3.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.3]
1657
+ # to create a new +mailbox+.
1658
+ #
1659
+ # A Net::IMAP::NoResponseError is raised if a mailbox with that name
1660
+ # cannot be created.
1661
+ #
1662
+ # Related: #rename, #delete
1663
+ def create(mailbox)
1664
+ send_command("CREATE", mailbox)
1665
+ end
1666
+
1667
+ # Sends a {DELETE command [IMAP4rev1 §6.3.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.4]
1668
+ # to remove the +mailbox+.
1669
+ #
1670
+ # A Net::IMAP::NoResponseError is raised if a mailbox with that name
1671
+ # cannot be deleted, either because it does not exist or because the
1672
+ # client does not have permission to delete it.
1673
+ #
1674
+ # Related: #create, #rename
1675
+ def delete(mailbox)
1676
+ send_command("DELETE", mailbox)
1677
+ end
1678
+
1679
+ # Sends a {RENAME command [IMAP4rev1 §6.3.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.5]
1680
+ # to change the name of the +mailbox+ to +newname+.
1681
+ #
1682
+ # A Net::IMAP::NoResponseError is raised if a mailbox with the
1683
+ # name +mailbox+ cannot be renamed to +newname+ for whatever
1684
+ # reason; for instance, because +mailbox+ does not exist, or
1685
+ # because there is already a mailbox with the name +newname+.
1686
+ #
1687
+ # Related: #create, #delete
1688
+ def rename(mailbox, newname)
1689
+ send_command("RENAME", mailbox, newname)
1690
+ end
1691
+
1692
+ # Sends a {SUBSCRIBE command [IMAP4rev1 §6.3.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.6]
1693
+ # to add the specified +mailbox+ name to the server's set of "active" or
1694
+ # "subscribed" mailboxes as returned by #lsub.
1695
+ #
1696
+ # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
1697
+ # subscribed to; for instance, because it does not exist.
1698
+ #
1699
+ # Related: #unsubscribe, #lsub, #list
1700
+ def subscribe(mailbox)
1701
+ send_command("SUBSCRIBE", mailbox)
1702
+ end
1703
+
1704
+ # Sends an {UNSUBSCRIBE command [IMAP4rev1 §6.3.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.7]
1705
+ # to remove the specified +mailbox+ name from the server's set of "active"
1706
+ # or "subscribed" mailboxes.
1707
+ #
1708
+ # A Net::IMAP::NoResponseError is raised if +mailbox+ cannot be
1709
+ # unsubscribed from; for instance, because the client is not currently
1710
+ # subscribed to it.
1711
+ #
1712
+ # Related: #subscribe, #lsub, #list
1713
+ def unsubscribe(mailbox)
1714
+ send_command("UNSUBSCRIBE", mailbox)
1715
+ end
1716
+
1717
+ # Sends a {LIST command [IMAP4rev1 §6.3.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.8]
1718
+ # and returns a subset of names from the complete set of all names available
1719
+ # to the client. +refname+ provides a context (for instance, a base
1720
+ # directory in a directory-based mailbox hierarchy). +mailbox+ specifies a
1721
+ # mailbox or (via wildcards) mailboxes under that context. Two wildcards
1722
+ # may be used in +mailbox+: <tt>"*"</tt>, which matches all characters
1723
+ # *including* the hierarchy delimiter (for instance, "/" on a UNIX-hosted
1724
+ # directory-based mailbox hierarchy); and <tt>"%"</tt>, which matches all
1725
+ # characters *except* the hierarchy delimiter.
1726
+ #
1727
+ # If +refname+ is empty, +mailbox+ is used directly to determine
1728
+ # which mailboxes to match. If +mailbox+ is empty, the root
1729
+ # name of +refname+ and the hierarchy delimiter are returned.
1730
+ #
1731
+ # The return value is an array of MailboxList.
1732
+ #
1733
+ # Related: #lsub, MailboxList
1734
+ #
1735
+ # ==== For example:
1736
+ #
1737
+ # imap.create("foo/bar")
1738
+ # imap.create("foo/baz")
1739
+ # p imap.list("", "foo/%")
1740
+ # #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
1741
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
1742
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
1743
+ #
1744
+ #--
1745
+ # TODO: support LIST-EXTENDED extension [RFC5258]. Needed for IMAP4rev2.
1746
+ #++
1747
+ def list(refname, mailbox)
1748
+ synchronize do
1749
+ send_command("LIST", refname, mailbox)
1750
+ clear_responses("LIST")
1751
+ end
1752
+ end
1753
+
1754
+ # Sends a {NAMESPACE command [RFC2342 §5]}[https://www.rfc-editor.org/rfc/rfc2342#section-5]
1755
+ # and returns the namespaces that are available. The NAMESPACE command
1756
+ # allows a client to discover the prefixes of namespaces used by a server
1757
+ # for personal mailboxes, other users' mailboxes, and shared mailboxes.
1758
+ #
1759
+ # The return value is a Namespaces object which has +personal+, +other+, and
1760
+ # +shared+ fields, each an array of Namespace objects. These arrays will be
1761
+ # empty when the server responds with +nil+.
1762
+ #
1763
+ # Many \IMAP servers are configured with the default personal namespaces as
1764
+ # <tt>("" "/")</tt>: no prefix and the "+/+" hierarchy delimiter. In that
1765
+ # common case, the naive client may not have any trouble naming mailboxes.
1766
+ # But many servers are configured with the default personal namespace as
1767
+ # e.g. <tt>("INBOX." ".")</tt>, placing all personal folders under INBOX,
1768
+ # with "+.+" as the hierarchy delimiter. If the client does not check for
1769
+ # this, but naively assumes it can use the same folder names for all
1770
+ # servers, then folder creation (and listing, moving, etc) can lead to
1771
+ # errors.
1772
+ #
1773
+ # From RFC2342[https://www.rfc-editor.org/rfc/rfc2342]:
1774
+ # >>>
1775
+ # <em>Although typically a server will support only a single Personal
1776
+ # Namespace, and a single Other User's Namespace, circumstances exist
1777
+ # where there MAY be multiples of these, and a client MUST be prepared
1778
+ # for them. If a client is configured such that it is required to create
1779
+ # a certain mailbox, there can be circumstances where it is unclear which
1780
+ # Personal Namespaces it should create the mailbox in. In these
1781
+ # situations a client SHOULD let the user select which namespaces to
1782
+ # create the mailbox in.</em>
1783
+ #
1784
+ # Related: #list, Namespaces, Namespace
1785
+ #
1786
+ # ==== For example:
1787
+ #
1788
+ # if capable?("NAMESPACE")
1789
+ # namespaces = imap.namespace
1790
+ # if namespace = namespaces.personal.first
1791
+ # prefix = namespace.prefix # e.g. "" or "INBOX."
1792
+ # delim = namespace.delim # e.g. "/" or "."
1793
+ # # personal folders should use the prefix and delimiter
1794
+ # imap.create(prefix + "foo")
1795
+ # imap.create(prefix + "bar")
1796
+ # imap.create(prefix + %w[path to my folder].join(delim))
1797
+ # end
1798
+ # end
1799
+ #
1800
+ # ==== Capabilities
1801
+ #
1802
+ # The server's capabilities must include either +IMAP4rev2+ or +NAMESPACE+
1803
+ # [RFC2342[https://www.rfc-editor.org/rfc/rfc2342]].
1804
+ def namespace
1805
+ synchronize do
1806
+ send_command("NAMESPACE")
1807
+ clear_responses("NAMESPACE").last
1808
+ end
1809
+ end
1810
+
1811
+ # Sends a XLIST command, and returns a subset of names from
1812
+ # the complete set of all names available to the client.
1813
+ # +refname+ provides a context (for instance, a base directory
1814
+ # in a directory-based mailbox hierarchy). +mailbox+ specifies
1815
+ # a mailbox or (via wildcards) mailboxes under that context.
1816
+ # Two wildcards may be used in +mailbox+: '*', which matches
1817
+ # all characters *including* the hierarchy delimiter (for instance,
1818
+ # '/' on a UNIX-hosted directory-based mailbox hierarchy); and '%',
1819
+ # which matches all characters *except* the hierarchy delimiter.
1820
+ #
1821
+ # If +refname+ is empty, +mailbox+ is used directly to determine
1822
+ # which mailboxes to match. If +mailbox+ is empty, the root
1823
+ # name of +refname+ and the hierarchy delimiter are returned.
1824
+ #
1825
+ # The XLIST command is like the LIST command except that the flags
1826
+ # returned refer to the function of the folder/mailbox, e.g. :Sent
1827
+ #
1828
+ # The return value is an array of MailboxList objects. For example:
1829
+ #
1830
+ # imap.create("foo/bar")
1831
+ # imap.create("foo/baz")
1832
+ # p imap.xlist("", "foo/%")
1833
+ # #=> [#<Net::IMAP::MailboxList attr=[:Noselect], delim="/", name="foo/">, \\
1834
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors, :Marked], delim="/", name="foo/bar">, \\
1835
+ # #<Net::IMAP::MailboxList attr=[:Noinferiors], delim="/", name="foo/baz">]
1836
+ #
1837
+ # Related: #list, MailboxList
1838
+ #
1839
+ # ==== Capabilities
1840
+ #
1841
+ # The server's capabilities must include +XLIST+,
1842
+ # a deprecated Gmail extension (replaced by +SPECIAL-USE+).
1843
+ #--
1844
+ # TODO: Net::IMAP doesn't yet have full SPECIAL-USE support. Supporting
1845
+ # servers MAY return SPECIAL-USE attributes, but are not *required* to
1846
+ # unless the SPECIAL-USE return option is supplied.
1847
+ #++
1848
+ def xlist(refname, mailbox)
1849
+ synchronize do
1850
+ send_command("XLIST", refname, mailbox)
1851
+ clear_responses("XLIST")
1852
+ end
1853
+ end
1854
+
1855
+ # Sends a {GETQUOTAROOT command [RFC2087 §4.3]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.3]
1856
+ # along with the specified +mailbox+. This command is generally available
1857
+ # to both admin and user. If this mailbox exists, it returns an array
1858
+ # containing objects of type MailboxQuotaRoot and MailboxQuota.
1859
+ #
1860
+ # *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
1861
+ # resource type. This is usually +STORAGE+, but you may need to verify this
1862
+ # with UntaggedResponse#raw_data.
1863
+ #
1864
+ # Related: #getquota, #setquota, MailboxQuotaRoot, MailboxQuota
1865
+ #
1866
+ # ==== Capabilities
1867
+ #
1868
+ # Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1869
+ # capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1870
+ # {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1871
+ # resource type.
1872
+ def getquotaroot(mailbox)
1873
+ synchronize do
1874
+ send_command("GETQUOTAROOT", mailbox)
1875
+ result = []
1876
+ result.concat(clear_responses("QUOTAROOT"))
1877
+ result.concat(clear_responses("QUOTA"))
1878
+ return result
1879
+ end
1880
+ end
1881
+
1882
+ # Sends a {GETQUOTA command [RFC2087 §4.2]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.2]
1883
+ # for the +quota_root+. If this quota root exists, then an array
1884
+ # containing a MailboxQuota object is returned.
1885
+ #
1886
+ # The names of quota roots that are applicable to a particular mailbox can
1887
+ # be discovered with #getquotaroot.
1888
+ #
1889
+ # *NOTE:* Currently, Net::IMAP only supports +QUOTA+ responses with a single
1890
+ # resource type. This is usually +STORAGE+, but you may need to verify this
1891
+ # with UntaggedResponse#raw_data.
1892
+ #
1893
+ # Related: #getquotaroot, #setquota, MailboxQuota
1894
+ #
1895
+ # ==== Capabilities
1896
+ #
1897
+ # Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1898
+ # capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1899
+ # {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1900
+ # resource type.
1901
+ def getquota(quota_root)
1902
+ synchronize do
1903
+ send_command("GETQUOTA", quota_root)
1904
+ clear_responses("QUOTA")
1905
+ end
1906
+ end
1907
+
1908
+ # Sends a {SETQUOTA command [RFC2087 §4.1]}[https://www.rfc-editor.org/rfc/rfc2087#section-4.1]
1909
+ # along with the specified +quota_root+ and +storage_limit+. If
1910
+ # +storage_limit+ is +nil+, resource limits are unset for that quota root.
1911
+ # If +storage_limit+ is a number, it sets the +STORAGE+ resource limit.
1912
+ #
1913
+ # imap.setquota "#user/alice", 100
1914
+ # imap.getquota "#user/alice"
1915
+ # # => [#<struct Net::IMAP::MailboxQuota mailbox="#user/alice" usage=54 quota=100>]
1916
+ #
1917
+ # Typically one needs to be logged in as a server admin for this to work.
1918
+ #
1919
+ # *NOTE:* Currently, Net::IMAP only supports setting +STORAGE+ quota limits.
1920
+ #
1921
+ # Related: #getquota, #getquotaroot
1922
+ #
1923
+ # ==== Capabilities
1924
+ #
1925
+ # Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
1926
+ # capability, or a capability prefixed with <tt>QUOTA=RES-*</tt>
1927
+ # {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208] for each supported
1928
+ # resource type.
1929
+ def setquota(quota_root, storage_limit)
1930
+ if storage_limit.nil?
1931
+ list = []
1932
+ else
1933
+ list = ["STORAGE", Integer(storage_limit)]
1934
+ end
1935
+ send_command("SETQUOTA", quota_root, list)
1936
+ end
1937
+
1938
+ # Sends a {SETACL command [RFC4314 §3.1]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.1]
1939
+ # along with +mailbox+, +user+ and the +rights+ that user is to have on that
1940
+ # mailbox. If +rights+ is nil, then that user will be stripped of any
1941
+ # rights to that mailbox.
1942
+ #
1943
+ # Related: #getacl
1944
+ #
1945
+ # ==== Capabilities
1946
+ #
1947
+ # The server's capabilities must include +ACL+
1948
+ # [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
1949
+ def setacl(mailbox, user, rights)
1950
+ if rights.nil?
1951
+ send_command("SETACL", mailbox, user, "")
1952
+ else
1953
+ send_command("SETACL", mailbox, user, rights)
1954
+ end
1955
+ end
1956
+
1957
+ # Sends a {GETACL command [RFC4314 §3.3]}[https://www.rfc-editor.org/rfc/rfc4314#section-3.3]
1958
+ # along with a specified +mailbox+. If this mailbox exists, an array
1959
+ # containing objects of MailboxACLItem will be returned.
1960
+ #
1961
+ # Related: #setacl, MailboxACLItem
1962
+ #
1963
+ # ==== Capabilities
1964
+ #
1965
+ # The server's capabilities must include +ACL+
1966
+ # [RFC4314[https://www.rfc-editor.org/rfc/rfc4314]].
1967
+ def getacl(mailbox)
1968
+ synchronize do
1969
+ send_command("GETACL", mailbox)
1970
+ clear_responses("ACL").last
1971
+ end
1972
+ end
1973
+
1974
+ # Sends a {LSUB command [IMAP4rev1 §6.3.9]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.9]
1975
+ # and returns a subset of names from the set of names that the user has
1976
+ # declared as being "active" or "subscribed." +refname+ and +mailbox+ are
1977
+ # interpreted as for #list.
1978
+ #
1979
+ # The return value is an array of MailboxList objects.
1980
+ #
1981
+ # Related: #subscribe, #unsubscribe, #list, MailboxList
1982
+ def lsub(refname, mailbox)
1983
+ synchronize do
1984
+ send_command("LSUB", refname, mailbox)
1985
+ clear_responses("LSUB")
1986
+ end
1987
+ end
1988
+
1989
+ # Sends a {STATUS command [IMAP4rev1 §6.3.10]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.10]
1990
+ # and returns the status of the indicated +mailbox+. +attr+ is a list of one
1991
+ # or more attributes whose statuses are to be requested.
1992
+ #
1993
+ # The return value is a hash of attributes. Most status attributes return
1994
+ # integer values, but some return other value types (documented below).
1995
+ #
1996
+ # A Net::IMAP::NoResponseError is raised if status values
1997
+ # for +mailbox+ cannot be returned; for instance, because it
1998
+ # does not exist.
1999
+ #
2000
+ # ==== Supported attributes
2001
+ #
2002
+ # +MESSAGES+:: The number of messages in the mailbox.
2003
+ #
2004
+ # +UIDNEXT+:: The next unique identifier value of the mailbox.
2005
+ #
2006
+ # +UIDVALIDITY+:: The unique identifier validity value of the mailbox.
2007
+ #
2008
+ # +UNSEEN+:: The number of messages without the <tt>\Seen</tt> flag.
2009
+ #
2010
+ # +DELETED+:: The number of messages with the <tt>\Deleted</tt> flag.
2011
+ #
2012
+ # +SIZE+::
2013
+ # The approximate size of the mailbox---must be greater than or equal to
2014
+ # the sum of all messages' +RFC822.SIZE+ fetch item values.
2015
+ #
2016
+ # +HIGHESTMODSEQ+::
2017
+ # The highest mod-sequence value of all messages in the mailbox. See
2018
+ # +CONDSTORE+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
2019
+ #
2020
+ # +MAILBOXID+::
2021
+ # A server-allocated unique _string_ identifier for the mailbox. See
2022
+ # +OBJECTID+ {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
2023
+ #
2024
+ # +RECENT+::
2025
+ # The number of messages with the <tt>\Recent</tt> flag.
2026
+ # _NOTE:_ +RECENT+ was removed from IMAP4rev2.
2027
+ #
2028
+ # Unsupported attributes may be requested. The attribute value will be
2029
+ # either an Integer or an ExtensionData object.
2030
+ #
2031
+ # ==== For example:
2032
+ #
2033
+ # p imap.status("inbox", ["MESSAGES", "RECENT"])
2034
+ # #=> {"RECENT"=>0, "MESSAGES"=>44}
2035
+ #
2036
+ # ==== Capabilities
2037
+ #
2038
+ # +SIZE+ requires the server's capabilities to include either +IMAP4rev2+ or
2039
+ # <tt>STATUS=SIZE</tt>
2040
+ # {[RFC8483]}[https://www.rfc-editor.org/rfc/rfc8483.html].
2041
+ #
2042
+ # +DELETED+ must be supported when the server's capabilities includes
2043
+ # +IMAP4rev2+.
2044
+ # or <tt>QUOTA=RES-MESSAGES</tt>
2045
+ # {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208.html].
2046
+ #
2047
+ # +HIGHESTMODSEQ+ requires the server's capabilities to include +CONDSTORE+
2048
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
2049
+ #
2050
+ # +MAILBOXID+ requires the server's capabilities to include +OBJECTID+
2051
+ # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html].
2052
+ def status(mailbox, attr)
2053
+ synchronize do
2054
+ send_command("STATUS", mailbox, attr)
2055
+ clear_responses("STATUS").last&.attr
2056
+ end
2057
+ end
2058
+
2059
+ # Sends an {APPEND command [IMAP4rev1 §6.3.11]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.3.11]
2060
+ # to append the +message+ to the end of the +mailbox+. The optional +flags+
2061
+ # argument is an array of flags initially passed to the new message. The
2062
+ # optional +date_time+ argument specifies the creation time to assign to the
2063
+ # new message; it defaults to the current time.
2064
+ #
2065
+ # For example:
2066
+ #
2067
+ # imap.append("inbox", <<EOF.gsub(/\n/, "\r\n"), [:Seen], Time.now)
2068
+ # Subject: hello
2069
+ # From: shugo@ruby-lang.org
2070
+ # To: shugo@ruby-lang.org
2071
+ #
2072
+ # hello world
2073
+ # EOF
2074
+ #
2075
+ # A Net::IMAP::NoResponseError is raised if the mailbox does
2076
+ # not exist (it is not created automatically), or if the flags,
2077
+ # date_time, or message arguments contain errors.
2078
+ #
2079
+ # ==== Capabilities
2080
+ #
2081
+ # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
2082
+ # supported and the destination supports persistent UIDs, the server's
2083
+ # response should include an +APPENDUID+ response code with UIDPlusData.
2084
+ # This will report the UIDVALIDITY of the destination mailbox and the
2085
+ # assigned UID of the appended message.
2086
+ #
2087
+ #--
2088
+ # TODO: add MULTIAPPEND support
2089
+ #++
2090
+ def append(mailbox, message, flags = nil, date_time = nil)
2091
+ args = []
2092
+ if flags
2093
+ args.push(flags)
2094
+ end
2095
+ args.push(date_time) if date_time
2096
+ args.push(Literal.new(message))
2097
+ send_command("APPEND", mailbox, *args)
2098
+ end
2099
+
2100
+ # Sends a {CHECK command [IMAP4rev1 §6.4.1]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.1]
2101
+ # to request a checkpoint of the currently selected mailbox. This performs
2102
+ # implementation-specific housekeeping; for instance, reconciling the
2103
+ # mailbox's in-memory and on-disk state.
2104
+ #
2105
+ # Related: #idle, #noop
2106
+ def check
2107
+ send_command("CHECK")
2108
+ end
2109
+
2110
+ # Sends a {CLOSE command [IMAP4rev1 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.2]
2111
+ # to close the currently selected mailbox. The CLOSE command permanently
2112
+ # removes from the mailbox all messages that have the <tt>\\Deleted</tt>
2113
+ # flag set.
2114
+ #
2115
+ # Related: #unselect
2116
+ def close
2117
+ send_command("CLOSE")
2118
+ .tap do state_authenticated! end
2119
+ end
2120
+
2121
+ # Sends an {UNSELECT command [RFC3691 §2]}[https://www.rfc-editor.org/rfc/rfc3691#section-3]
2122
+ # {[IMAP4rev2 §6.4.2]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.2]
2123
+ # to free the session resources for a mailbox and return to the
2124
+ # "_authenticated_" state. This is the same as #close, except that
2125
+ # <tt>\\Deleted</tt> messages are not removed from the mailbox.
2126
+ #
2127
+ # Related: #close
2128
+ #
2129
+ # ==== Capabilities
2130
+ #
2131
+ # The server's capabilities must include either +IMAP4rev2+ or +UNSELECT+
2132
+ # [RFC3691[https://www.rfc-editor.org/rfc/rfc3691]].
2133
+ def unselect
2134
+ send_command("UNSELECT")
2135
+ .tap do state_authenticated! end
2136
+ end
2137
+
2138
+ # call-seq:
2139
+ # expunge -> array of message sequence numbers
2140
+ # expunge -> VanishedData of UIDs
2141
+ #
2142
+ # Sends an {EXPUNGE command [IMAP4rev1 §6.4.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.3]
2143
+ # to permanently remove all messages with the +\Deleted+ flag from the
2144
+ # currently selected mailbox.
2145
+ #
2146
+ # Returns either an array of expunged message <em>sequence numbers</em> or
2147
+ # (when the appropriate capability is enabled) VanishedData of expunged
2148
+ # UIDs. Previously unhandled +EXPUNGE+ or +VANISHED+ responses are merged
2149
+ # with the direct response to this command. <tt>VANISHED (EARLIER)</tt>
2150
+ # responses will _not_ be merged.
2151
+ #
2152
+ # When no messages have been expunged, an empty array is returned,
2153
+ # regardless of which extensions are enabled. In a future release, an empty
2154
+ # VanishedData may be returned, based on the currently enabled extensions.
2155
+ #
2156
+ # Related: #uid_expunge
2157
+ #
2158
+ # ==== Capabilities
2159
+ #
2160
+ # When either QRESYNC[https://www.rfc-editor.org/rfc/rfc7162] or
2161
+ # UIDONLY[https://www.rfc-editor.org/rfc/rfc9586] are enabled, #expunge
2162
+ # returns VanishedData, which contains UIDs---<em>not message sequence
2163
+ # numbers</em>.
2164
+ def expunge
2165
+ expunge_internal("EXPUNGE")
2166
+ end
2167
+
2168
+ # call-seq:
2169
+ # uid_expunge(uid_set) -> array of message sequence numbers
2170
+ # uid_expunge(uid_set) -> VanishedData of UIDs
2171
+ #
2172
+ # Sends a {UID EXPUNGE command [RFC4315 §2.1]}[https://www.rfc-editor.org/rfc/rfc4315#section-2.1]
2173
+ # {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
2174
+ # to permanently remove all messages that have both the <tt>\\Deleted</tt>
2175
+ # flag set and a UID that is included in +uid_set+.
2176
+ #
2177
+ # Returns the same result type as #expunge.
2178
+ #
2179
+ # By using #uid_expunge instead of #expunge when resynchronizing with
2180
+ # the server, the client can ensure that it does not inadvertantly
2181
+ # remove any messages that have been marked as <tt>\\Deleted</tt> by other
2182
+ # clients between the time that the client was last connected and
2183
+ # the time the client resynchronizes.
2184
+ #
2185
+ # Related: #expunge
2186
+ #
2187
+ # ==== Capabilities
2188
+ #
2189
+ # The server's capabilities must include either +IMAP4rev2+ or +UIDPLUS+
2190
+ # [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
2191
+ #
2192
+ # Otherwise, #uid_expunge is updated by extensions in the same way as
2193
+ # #expunge.
2194
+ def uid_expunge(uid_set)
2195
+ expunge_internal("UID EXPUNGE", SequenceSet.new(uid_set))
2196
+ end
2197
+
2198
+ # :call-seq:
2199
+ # search(criteria, charset = nil) -> result
2200
+ # search(criteria, charset: nil, return: nil) -> result
2201
+ #
2202
+ # Sends a {SEARCH command [IMAP4rev1 §6.4.4]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4]
2203
+ # to search the mailbox for messages that match the given search +criteria+,
2204
+ # and returns either a SearchResult or an ESearchResult. SearchResult
2205
+ # inherits from Array (for backward compatibility) but adds
2206
+ # SearchResult#modseq when the +CONDSTORE+ capability has been enabled.
2207
+ # ESearchResult also implements {#to_a}[rdoc-ref:ESearchResult#to_a], for
2208
+ # compatibility with SearchResult.
2209
+ #
2210
+ # +criteria+ is one or more search keys and their arguments, which may be
2211
+ # provided as an array or a string.
2212
+ # See {"Argument translation"}[rdoc-ref:#search@Argument+translation]
2213
+ # and {"Search criteria"}[rdoc-ref:#search@Search+criteria], below.
2214
+ # <em>Please note</em> the warning for when +criteria+ is a String.
2215
+ #
2216
+ # +return+ options control what kind of information is returned about
2217
+ # messages matching the search +criteria+. Specifying +return+ should force
2218
+ # the server to return an ESearchResult instead of a SearchResult, but some
2219
+ # servers disobey this requirement. <em>Requires an extended search
2220
+ # capability, such as +ESEARCH+ or +IMAP4rev2+.</em>
2221
+ # See {"Argument translation"}[rdoc-ref:#search@Argument+translation] and
2222
+ # {"Supported return options"}[rdoc-ref:#search@Supported+return+options],
2223
+ # below.
2224
+ #
2225
+ # +charset+ is the name of the {registered character
2226
+ # set}[https://www.iana.org/assignments/character-sets/character-sets.xhtml]
2227
+ # used by strings in the search +criteria+. When +charset+ isn't specified,
2228
+ # either <tt>"US-ASCII"</tt> or <tt>"UTF-8"</tt> is assumed, depending on
2229
+ # the server's capabilities.
2230
+ #
2231
+ # _NOTE:_ Return options and charset may be sent as part of +criteria+. Do
2232
+ # not use the +return+ or +charset+ arguments when either return options or
2233
+ # charset are embedded in +criteria+.
2234
+ #
2235
+ # Related: #uid_search
2236
+ #
2237
+ # ==== For example:
2238
+ #
2239
+ # imap.search(["SUBJECT", "hello", "NOT", "SEEN"])
2240
+ # #=> [1, 6, 7, 8]
2241
+ #
2242
+ # The following assumes the server supports +ESEARCH+ and +CONDSTORE+:
2243
+ #
2244
+ # result = imap.uid_search(["UID", 12345.., "MODSEQ", 620_162_338],
2245
+ # return: %w(all count min max))
2246
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0123", uid=true,
2247
+ # # data=[["ALL", Net::IMAP::SequenceSet["12346:12349,22222:22230"]],
2248
+ # # ["COUNT", 13], ["MIN", 12346], ["MAX", 22230],
2249
+ # # ["MODSEQ", 917162488]]>
2250
+ # result.to_a # => [12346, 12347, 12348, 12349, 22222, 22223, 22224,
2251
+ # # 22225, 22226, 22227, 22228, 22229, 22230]
2252
+ # result.uid? # => true
2253
+ # result.count # => 13
2254
+ # result.min # => 12346
2255
+ # result.max # => 22230
2256
+ # result.modseq # => 917162488
2257
+ #
2258
+ # Using +return+ options to limit the result to only min, max, and count:
2259
+ #
2260
+ # result = imap.uid_search(["UID", 12345..,], return: %w(count min max))
2261
+ # # => #<data Net::IMAP::ESearchResult tag="RUBY0124", uid=true,
2262
+ # # data=[["COUNT", 13], ["MIN", 12346], ["MAX", 22230]]>
2263
+ # result.to_a # => []
2264
+ # result.count # => 13
2265
+ # result.min # => 12346
2266
+ # result.max # => 22230
2267
+ #
2268
+ # Return options and charset may be sent as keyword args or embedded in the
2269
+ # +criteria+ arg, but they must be in the correct order: <tt>"RETURN (...)
2270
+ # CHARSET ... criteria..."</tt>. The following searches
2271
+ # send the exact same command to the server:
2272
+ #
2273
+ # # Return options and charset as keyword arguments (preferred)
2274
+ # imap.search(%w(OR UNSEEN FLAGGED), return: %w(MIN MAX), charset: "UTF-8")
2275
+ # # Embedding return and charset in the criteria array
2276
+ # imap.search(["RETURN", %w(MIN MAX), "CHARSET", "UTF-8", *%w(OR UNSEEN FLAGGED)])
2277
+ # # Embedding return and charset in the criteria string
2278
+ # imap.search("RETURN (MIN MAX) CHARSET UTF-8 OR UNSEEN FLAGGED")
2279
+ #
2280
+ # Sending charset as the second positional argument is supported for
2281
+ # backward compatibility. Future versions may print a deprecation warning:
2282
+ # imap.search(%w(OR UNSEEN FLAGGED), "UTF-8", return: %w(MIN MAX))
2283
+ #
2284
+ # ==== Argument translation
2285
+ #
2286
+ # [+return+ options]
2287
+ # Must be an Array. Return option names may be either strings or symbols.
2288
+ # +Range+ elements which begin and end with negative integers are encoded
2289
+ # for use with +PARTIAL+--any other ranges are converted to SequenceSet.
2290
+ # Unlike +criteria+, other return option arguments are not automatically
2291
+ # converted to SequenceSet.
2292
+ #
2293
+ # [When +criteria+ is an Array]
2294
+ # When the array begins with <tt>"RETURN"</tt> (case insensitive), the
2295
+ # second array element is translated like the +return+ parameter (as
2296
+ # described above).
2297
+ #
2298
+ # Every other member is a +SEARCH+ command argument:
2299
+ # [SequenceSet]
2300
+ # Encoded as an \IMAP +sequence-set+ with SequenceSet#valid_string.
2301
+ # [Set, Range, <tt>-1</tt>, +:*+, responds to +#to_sequence_set+]
2302
+ # Converted to SequenceSet for validation and encoding.
2303
+ # [nested sequence-set +Array+]
2304
+ # When every element in a nested array is one of the above types, a
2305
+ # positive +Integer+, a sequence-set formatted +String+, or a deeply
2306
+ # nested +Array+ of these same types, the array will be converted to
2307
+ # SequenceSet for validation and encoding.
2308
+ # [Any other nested +Array+]
2309
+ # Otherwise, a nested array is encoded as a parenthesized list, to
2310
+ # combine multiple search keys (e.g., for use with +OR+ and +NOT+).
2311
+ # [+String+]
2312
+ # Sent verbatim when it is a valid \IMAP +atom+, and encoded as an \IMAP
2313
+ # +quoted+ or +literal+ string otherwise. Every standard search key
2314
+ # name is a valid \IMAP +atom+ and every standard search key string
2315
+ # argument is an +astring+ which may be encoded as +atom+, +quoted+, or
2316
+ # +literal+.
2317
+ #
2318
+ # *Note:* <tt>*</tt> is not a valid \IMAP +atom+ character. Any string
2319
+ # containing <tt>*</tt> will be encoded as a +quoted+ string, _not_ a
2320
+ # +sequence-set+.
2321
+ # [+Integer+ (except for <tt>-1</tt>)]
2322
+ # Encoded using +#to_s+.
2323
+ # [+Date+]
2324
+ # Encoded as an \IMAP date (see ::encode_date).
2325
+ #
2326
+ # [When +criteria+ is a String]
2327
+ # +criteria+ will be sent to the server <em>with minimal validation and no
2328
+ # encoding or formatting</em>.
2329
+ #
2330
+ # <em>*WARNING:* Although CRLF is prohibited, this is vulnerable to other
2331
+ # types of attribute injection attack if unvetted user input is used.</em>
2332
+ #
2333
+ # ==== Supported return options
2334
+ #
2335
+ # For full definitions of the standard return options and return data, see
2336
+ # the relevant RFCs.
2337
+ #
2338
+ # [+ALL+]
2339
+ # Returns ESearchResult#all with a SequenceSet of all matching sequence
2340
+ # numbers or UIDs. This is the default, when return options are empty.
2341
+ #
2342
+ # For compatibility with SearchResult, ESearchResult#to_a returns an
2343
+ # Array of message sequence numbers or UIDs.
2344
+ #
2345
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2346
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2347
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2348
+ #
2349
+ # [+COUNT+]
2350
+ # Returns ESearchResult#count with the number of matching messages.
2351
+ #
2352
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2353
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2354
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2355
+ #
2356
+ # [+MAX+]
2357
+ # Returns ESearchResult#max with the highest matching sequence number or
2358
+ # UID.
2359
+ #
2360
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2361
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2362
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2363
+ #
2364
+ # [+MIN+]
2365
+ # Returns ESearchResult#min with the lowest matching sequence number or
2366
+ # UID.
2367
+ #
2368
+ # <em>Requires either the +ESEARCH+ or +IMAP4rev2+ capabability.</em>
2369
+ # {[RFC4731]}[https://rfc-editor.org/rfc/rfc4731]
2370
+ # {[RFC9051]}[https://rfc-editor.org/rfc/rfc9051]
2371
+ #
2372
+ # [+PARTIAL+ _range_]
2373
+ # Returns ESearchResult#partial with a SequenceSet of a subset of
2374
+ # matching sequence numbers or UIDs, as selected by _range_. As with
2375
+ # sequence numbers, the first result is +1+: <tt>1..500</tt> selects the
2376
+ # first 500 search results (in mailbox order), <tt>501..1000</tt> the
2377
+ # second 500, and so on. _range_ may also be negative: <tt>-500..-1</tt>
2378
+ # selects the last 500 search results.
2379
+ #
2380
+ # <em>Requires either the <tt>CONTEXT=SEARCH</tt> or +PARTIAL+ capabability.</em>
2381
+ # {[RFC5267]}[https://rfc-editor.org/rfc/rfc5267]
2382
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
2383
+ #
2384
+ # ===== +MODSEQ+ return data
2385
+ #
2386
+ # ESearchResult#modseq return data does not have a corresponding return
2387
+ # option. Instead, it is returned if the +MODSEQ+ search key is used or
2388
+ # when the +CONDSTORE+ extension is enabled for the selected mailbox.
2389
+ # See [{RFC4731 §3.2}[https://www.rfc-editor.org/rfc/rfc4731#section-3.2]]
2390
+ # or [{RFC7162 §2.1.5}[https://www.rfc-editor.org/rfc/rfc7162#section-3.1.5]].
2391
+ #
2392
+ # ===== +RFC4466+ compatible extensions
2393
+ #
2394
+ # {RFC4466 §2.6}[https://www.rfc-editor.org/rfc/rfc4466.html#section-2.6]
2395
+ # defines standard syntax for search extensions. Net::IMAP allows sending
2396
+ # unsupported search return options and will parse unsupported search
2397
+ # extensions' return values into ExtensionData. Please note that this is an
2398
+ # intentionally _unstable_ API. Future releases may return different
2399
+ # (incompatible) objects, <em>without deprecation or warning</em>.
2400
+ #
2401
+ # ==== Search keys
2402
+ #
2403
+ # For full definitions of the standard search +criteria+,
2404
+ # see [{IMAP4rev1 §6.4.4}[https://www.rfc-editor.org/rfc/rfc3501.html#section-6.4.4]],
2405
+ # or [{IMAP4rev2 §6.4.4}[https://www.rfc-editor.org/rfc/rfc9051.html#section-6.4.4]],
2406
+ # in addition to documentation for
2407
+ # any #capabilities which may define additional search filters, such as
2408
+ # +CONDSTORE+, +WITHIN+, +FILTERS+, <tt>SEARCH=FUZZY</tt>, +OBJECTID+, or
2409
+ # +SAVEDATE+.
2410
+ #
2411
+ # With the exception of <em>sequence-set</em> and <em>parenthesized
2412
+ # list</em>, all search keys are composed of prefix label with zero or more
2413
+ # arguments. The number and type of arguments is specific to each search
2414
+ # key.
2415
+ #
2416
+ # ===== Search keys that match all messages
2417
+ #
2418
+ # [+ALL+]
2419
+ # The default initial key. Matches every message in the mailbox.
2420
+ #
2421
+ # [+SAVEDATESUPPORTED+]
2422
+ # Matches every message in the mailbox when the mailbox supports the save
2423
+ # date attribute. Otherwise, it matches no messages.
2424
+ #
2425
+ # <em>Requires +SAVEDATE+ capability</em>.
2426
+ # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2427
+ #
2428
+ # ===== Sequence set search keys
2429
+ #
2430
+ # [_sequence-set_]
2431
+ # Matches messages with message sequence numbers in _sequence-set_.
2432
+ #
2433
+ # _Note:_ this search key has no label.
2434
+ #
2435
+ # <em>+UIDONLY+ must *not* be enabled.</em>
2436
+ # {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.html]
2437
+ #
2438
+ # [+UID+ _sequence-set_]
2439
+ # Matches messages with a UID in _sequence-set_.
2440
+ #
2441
+ # ===== Compound search keys
2442
+ #
2443
+ # [(_search-key_ _search-key_...)]
2444
+ # Combines one or more _search-key_ arguments to match
2445
+ # messages which match all contained search keys. Useful for +OR+, +NOT+,
2446
+ # and other search keys with _search-key_ arguments.
2447
+ #
2448
+ # _Note:_ this search key has no label.
2449
+ #
2450
+ # [+OR+ _search-key_ _search-key_]
2451
+ # Matches messages which match either _search-key_ argument.
2452
+ #
2453
+ # [+NOT+ _search-key_]
2454
+ # Matches messages which do not match _search-key_.
2455
+ #
2456
+ # [+FUZZY+ _search-key_]
2457
+ # Uses fuzzy matching for the specified search key.
2458
+ #
2459
+ # <em>Requires <tt>SEARCH=FUZZY</tt> capability.</em>
2460
+ # {[RFC6203]}[https://www.rfc-editor.org/rfc/rfc6203.html#section-6].
2461
+ #
2462
+ # ===== Flags search keys
2463
+ #
2464
+ # [+ANSWERED+, +UNANSWERED+]
2465
+ # Matches messages with or without the <tt>\\Answered</tt> flag.
2466
+ # [+DELETED+, +UNDELETED+]
2467
+ # Matches messages with or without the <tt>\\Deleted</tt> flag.
2468
+ # [+DRAFT+, +UNDRAFT+]
2469
+ # Matches messages with or without the <tt>\\Draft</tt> flag.
2470
+ # [+FLAGGED+, +UNFLAGGED+]
2471
+ # Matches messages with or without the <tt>\\Flagged</tt> flag.
2472
+ # [+SEEN+, +UNSEEN+]
2473
+ # Matches messages with or without the <tt>\\Seen</tt> flag.
2474
+ # [+KEYWORD+ _keyword_, +UNKEYWORD+ _keyword_]
2475
+ # Matches messages with or without the specified _keyword_.
2476
+ #
2477
+ # [+RECENT+, +UNRECENT+]
2478
+ # Matches messages with or without the <tt>\\Recent</tt> flag.
2479
+ #
2480
+ # *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
2481
+ # [+NEW+]
2482
+ # Equivalent to <tt>(RECENT UNSEEN)</tt>.
2483
+ #
2484
+ # *NOTE:* The <tt>\\Recent</tt> flag has been removed from +IMAP4rev2+.
2485
+ #
2486
+ # ===== Header field substring search keys
2487
+ #
2488
+ # [+BCC+ _substring_]
2489
+ # Matches when _substring_ is in the envelope's +BCC+ field.
2490
+ # [+CC+ _substring_]
2491
+ # Matches when _substring_ is in the envelope's +CC+ field.
2492
+ # [+FROM+ _substring_]
2493
+ # Matches when _substring_ is in the envelope's +FROM+ field.
2494
+ # [+SUBJECT+ _substring_]
2495
+ # Matches when _substring_ is in the envelope's +SUBJECT+ field.
2496
+ # [+TO+ _substring_]
2497
+ # Matches when _substring_ is in the envelope's +TO+ field.
2498
+ #
2499
+ # [+HEADER+ _field_ _substring_]
2500
+ # Matches when _substring_ is in the specified header _field_.
2501
+ #
2502
+ # ===== Body text search keys
2503
+ # [+BODY+ _string_]
2504
+ # Matches when _string_ is in the body of the message.
2505
+ # Does not match on header fields.
2506
+ #
2507
+ # The server _may_ use flexible matching, rather than simple substring
2508
+ # matches. For example, this may use stemming or match only full words.
2509
+ #
2510
+ # [+TEXT+ _string_]
2511
+ # Matches when _string_ is in the header or body of the message.
2512
+ #
2513
+ # The server _may_ use flexible matching, rather than simple substring
2514
+ # matches. For example, this may use stemming or match only full words.
2515
+ #
2516
+ # ===== Date/Time search keys
2517
+ #
2518
+ # [+SENTBEFORE+ _date_]
2519
+ # [+SENTON+ _date_]
2520
+ # [+SENTSINCE+ _date_]
2521
+ # Matches when the +Date+ header is earlier than, on, or later than _date_.
2522
+ #
2523
+ # [+BEFORE+ _date_]
2524
+ # [+ON+ _date_]
2525
+ # [+SINCE+ _date_]
2526
+ # Matches when the +INTERNALDATE+ is earlier than, on, or later than
2527
+ # _date_.
2528
+ #
2529
+ # [+OLDER+ _interval_]
2530
+ # [+YOUNGER+ _interval_]
2531
+ # Matches when the +INTERNALDATE+ is more/less than _interval_ seconds ago.
2532
+ #
2533
+ # <em>Requires +WITHIN+ capability</em>.
2534
+ # {[RFC5032]}[https://www.rfc-editor.org/rfc/rfc5032.html]
2535
+ #
2536
+ # [+SAVEDBEFORE+ _date_]
2537
+ # [+SAVEDON+ _date_]
2538
+ # [+SAVEDSINCE+ _date_]
2539
+ # Matches when the save date is earlier than, on, or later than _date_.
2540
+ #
2541
+ # <em>Requires +SAVEDATE+ capability.</em>
2542
+ # {[RFC8514]}[https://www.rfc-editor.org/rfc/rfc8514.html#section-4.3]
2543
+ #
2544
+ # ===== Other message attribute search keys
2545
+ #
2546
+ # [+SMALLER+ _bytes_]
2547
+ # [+LARGER+ _bytes_]
2548
+ # Matches when +RFC822.SIZE+ is smaller or larger than _bytes_.
2549
+ #
2550
+ # [+ANNOTATION+ _entry_ _attr_ _value_]
2551
+ # Matches messages that have annotations with entries matching _entry_,
2552
+ # attributes matching _attr_, and _value_ in the attribute's values.
2553
+ #
2554
+ # <em>Requires +ANNOTATE-EXPERIMENT-1+ capability</em>.
2555
+ # {[RFC5257]}[https://www.rfc-editor.org/rfc/rfc5257.html].
2556
+ #
2557
+ # [+FILTER+ _filter_]
2558
+ # References a _filter_ that is stored on the server and matches all
2559
+ # messages which would be matched by that filter's search criteria.
2560
+ #
2561
+ # <em>Requires +FILTERS+ capability</em>.
2562
+ # {[RFC5466]}[https://www.rfc-editor.org/rfc/rfc5466.html#section-3.1]
2563
+ #
2564
+ # [+MODSEQ+ _modseq_]
2565
+ # Matches when +MODSEQ+ is greater than or equal to _modseq_.
2566
+ #
2567
+ # <em>Requires +CONDSTORE+ capability</em>.
2568
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
2569
+ #
2570
+ # [+MODSEQ+ _entry_ _entry-type_ _modseq_]
2571
+ # Matches when a specific metadata _entry_ has been updated since
2572
+ # _modseq_.
2573
+ #
2574
+ # For flags, the corresponding _entry_ name is
2575
+ # <tt>"/flags/#{flag_name}"</tt>, where _flag_name_ includes the
2576
+ # <tt>\\</tt> prefix. _entry-type_ can be one of <tt>"shared"</tt>,
2577
+ # <tt>"priv"</tt> (private), or <tt>"all"</tt>.
2578
+ #
2579
+ # <em>Requires +CONDSTORE+ capability</em>.
2580
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1.5].
2581
+ #
2582
+ # [+EMAILID+ _objectid_]
2583
+ # [+THREADID+ _objectid_]
2584
+ # Matches when +EMAILID+/+THREADID+ is equal to _objectid_
2585
+ # (substring matches are not supported).
2586
+ #
2587
+ # <em>Requires +OBJECTID+ capability</em>.
2588
+ # {[RFC8474]}[https://www.rfc-editor.org/rfc/rfc8474.html#section-6]
2589
+ #
2590
+ # ==== Capabilities
2591
+ #
2592
+ # Return options should only be specified when the server supports
2593
+ # +IMAP4rev2+ or an extension that allows them, such as +ESEARCH+
2594
+ # [RFC4731[https://rfc-editor.org/rfc/rfc4731#section-3.1]].
2595
+ #
2596
+ # When +IMAP4rev2+ is enabled, or when the server supports +IMAP4rev2+ but
2597
+ # not +IMAP4rev1+, ESearchResult is always returned instead of SearchResult.
2598
+ #
2599
+ # If CONDSTORE[https://www.rfc-editor.org/rfc/rfc7162.html] is supported
2600
+ # and enabled for the selected mailbox, a non-empty SearchResult will
2601
+ # include a +MODSEQ+ value.
2602
+ # imap.select("mbox", condstore: true)
2603
+ # result = imap.search(["SUBJECT", "hi there", "not", "new"])
2604
+ # #=> Net::IMAP::SearchResult[1, 6, 7, 8, modseq: 5594]
2605
+ # result.modseq # => 5594
2606
+ #
2607
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2608
+ # the +SEARCH+ command is prohibited. Use #uid_search instead.
2609
+ def search(...)
2610
+ search_internal("SEARCH", ...)
2611
+ end
2612
+
2613
+ # :call-seq:
2614
+ # uid_search(criteria, charset = nil) -> result
2615
+ # uid_search(criteria, charset: nil, return: nil) -> result
2616
+ #
2617
+ # Sends a {UID SEARCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2618
+ # to search the mailbox for messages that match the given searching
2619
+ # criteria, and returns unique identifiers (<tt>UID</tt>s).
2620
+ #
2621
+ # Returns a SearchResult object. SearchResult inherits from Array (for
2622
+ # backward compatibility) but adds SearchResult#modseq when the +CONDSTORE+
2623
+ # capability has been enabled.
2624
+ #
2625
+ # See #search for documentation of parameters. <em>Please note</em> the
2626
+ # warning for when +criteria+ is a String.
2627
+ #
2628
+ # ==== Capabilities
2629
+ #
2630
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2631
+ # #uid_search must be used instead of #search, and the <tt><message
2632
+ # set></tt> search criterion is prohibited. Use +ALL+ or <tt>UID
2633
+ # sequence-set</tt> instead.
2634
+ #
2635
+ # Otherwise, #uid_search is updated by extensions in the same way as
2636
+ # #search.
2637
+ def uid_search(...)
2638
+ search_internal("UID SEARCH", ...)
2639
+ end
2640
+
2641
+ # :call-seq:
2642
+ # fetch(set, attr, changedsince: nil) -> array of FetchData
2643
+ #
2644
+ # Sends a {FETCH command [IMAP4rev1 §6.4.5]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.5]
2645
+ # to retrieve data associated with a message in the mailbox.
2646
+ #
2647
+ # +set+ is the message sequence numbers to fetch, and may be any valid input
2648
+ # to {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
2649
+ # (For UIDs, use #uid_fetch instead.)
2650
+ #
2651
+ # +attr+ is a list of attributes to fetch; see FetchStruct documentation for
2652
+ # a list of supported attributes.
2653
+ # >>>
2654
+ # When +attr+ is a String, it will be sent <em>with minimal validation and
2655
+ # no encoding or formatting</em>. When +attr+ is an Array, each String in
2656
+ # +attr+ will be sent this way.
2657
+ #
2658
+ # <em>*WARNING:* Although CRLF is prohibited, this is vulnerable to other
2659
+ # types of attribute injection attack if unvetted user input is used.</em>
2660
+ #
2661
+ # +changedsince+ is an optional integer mod-sequence. It limits results to
2662
+ # messages with a mod-sequence greater than +changedsince+.
2663
+ #
2664
+ # The return value is an array of FetchData.
2665
+ #
2666
+ # Related: #uid_fetch, FetchData
2667
+ #
2668
+ # ==== For example:
2669
+ #
2670
+ # p imap.fetch(6..8, "UID")
2671
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"UID"=>98}>, \\
2672
+ # #<Net::IMAP::FetchData seqno=7, attr={"UID"=>99}>, \\
2673
+ # #<Net::IMAP::FetchData seqno=8, attr={"UID"=>100}>]
2674
+ # p imap.fetch(6, "BODY[HEADER.FIELDS (SUBJECT)]")
2675
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"BODY[HEADER.FIELDS (SUBJECT)]"=>"Subject: test\r\n\r\n"}>]
2676
+ # data = imap.uid_fetch(98, ["RFC822.SIZE", "INTERNALDATE"])[0]
2677
+ # p data.seqno
2678
+ # #=> 6
2679
+ # p data.attr["RFC822.SIZE"]
2680
+ # #=> 611
2681
+ # p data.attr["INTERNALDATE"]
2682
+ # #=> "12-Oct-2000 22:40:59 +0900"
2683
+ # p data.attr["UID"]
2684
+ # #=> 98
2685
+ #
2686
+ # ==== Capabilities
2687
+ #
2688
+ # Many extensions define new message +attr+ names. See FetchStruct for a
2689
+ # list of supported extension fields.
2690
+ #
2691
+ # The server's capabilities must include +CONDSTORE+
2692
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
2693
+ # +changedsince+ argument. Using +changedsince+ implicitly enables the
2694
+ # +CONDSTORE+ extension.
2695
+ #
2696
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2697
+ # +FETCH+ command is prohibited. Use #uid_fetch instead.
2698
+ def fetch(...)
2699
+ fetch_internal("FETCH", ...)
2700
+ end
2701
+
2702
+ # :call-seq:
2703
+ # uid_fetch(set, attr, changedsince: nil, partial: nil) -> array of FetchData (or UIDFetchData)
2704
+ #
2705
+ # Sends a {UID FETCH command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2706
+ # to retrieve data associated with a message in the mailbox.
2707
+ #
2708
+ # +set+ is the message UIDs to fetch, and may be any valid input to
2709
+ # {SequenceSet[...]}[rdoc-ref:SequenceSet@Creating+sequence+sets].
2710
+ # (For message sequence numbers, use #fetch instead.)
2711
+ #
2712
+ # +attr+ behaves the same as with #fetch. <em>Please note</em> the #fetch
2713
+ # warning on the +attr+ argument.
2714
+ # >>>
2715
+ # *Note:* Servers _MUST_ implicitly include the +UID+ message data item as
2716
+ # part of any +FETCH+ response caused by a +UID+ command, regardless of
2717
+ # whether a +UID+ was specified as a message data item to the +FETCH+.
2718
+ #
2719
+ # +changedsince+ (optional) behaves the same as with #fetch.
2720
+ #
2721
+ # +partial+ is an optional range to limit the number of results returned.
2722
+ # It's useful when +set+ contains an unknown number of messages.
2723
+ # <tt>1..500</tt> returns the first 500 messages in +set+ (in mailbox
2724
+ # order), <tt>501..1000</tt> the second 500, and so on. +partial+ may also
2725
+ # be negative: <tt>-500..-1</tt> selects the last 500 messages in +set+.
2726
+ # <em>Requires the +PARTIAL+ capabability.</em>
2727
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394]
2728
+ #
2729
+ # For example:
2730
+ #
2731
+ # # Without partial, the size of the results may be unknown beforehand:
2732
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS))
2733
+ # # ... maybe wait for a long time ... and allocate a lot of memory ...
2734
+ # results.size # => 0..2**32-1
2735
+ # process results # may also take a long time and use a lot of memory...
2736
+ #
2737
+ # # Using partial, the results may be paginated:
2738
+ # loop do
2739
+ # results = imap.uid_fetch(next_uid_to_fetch.., %w(UID FLAGS),
2740
+ # partial: 1..500)
2741
+ # # fetch should return quickly and allocate little memory
2742
+ # results.size # => 0..500
2743
+ # break if results.empty?
2744
+ # results.sort_by!(&:uid) # server may return results out of order
2745
+ # next_uid_to_fetch = results.last.uid + 1
2746
+ # process results
2747
+ # end
2748
+ #
2749
+ # Related: #fetch, FetchData
2750
+ #
2751
+ # ==== Capabilities
2752
+ #
2753
+ # The server's capabilities must include +PARTIAL+
2754
+ # {[RFC9394]}[https://rfc-editor.org/rfc/rfc9394] in order to use the
2755
+ # +partial+ argument.
2756
+ #
2757
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2758
+ # #uid_fetch must be used instead of #fetch, and UIDFetchData will be
2759
+ # returned instead of FetchData.
2760
+ #
2761
+ # Otherwise, #uid_fetch is updated by extensions in the same way as #fetch.
2762
+ def uid_fetch(...)
2763
+ fetch_internal("UID FETCH", ...)
2764
+ end
2765
+
2766
+ # :call-seq:
2767
+ # store(set, attr, value, unchangedsince: nil) -> array of FetchData
2768
+ #
2769
+ # Sends a {STORE command [IMAP4rev1 §6.4.6]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.6]
2770
+ # to alter data associated with messages in the mailbox, in particular their
2771
+ # flags.
2772
+ #
2773
+ # +set+ is a number, an array of numbers, or a Range object. Each number is
2774
+ # a message sequence number.
2775
+ #
2776
+ # +attr+ is the name of a data item to store. The semantics of +value+
2777
+ # varies based on +attr+:
2778
+ # * When +attr+ is <tt>"FLAGS"</tt>, the flags in +value+ replace the
2779
+ # message's flag list.
2780
+ # * When +attr+ is <tt>"+FLAGS"</tt>, the flags in +value+ are added to
2781
+ # the flags for the message.
2782
+ # * When +attr+ is <tt>"-FLAGS"</tt>, the flags in +value+ are removed
2783
+ # from the message.
2784
+ #
2785
+ # +unchangedsince+ is an optional integer mod-sequence. It prohibits any
2786
+ # changes to messages with +mod-sequence+ greater than the specified
2787
+ # +unchangedsince+ value. A SequenceSet of any messages that fail this
2788
+ # check will be returned in a +MODIFIED+ ResponseCode.
2789
+ #
2790
+ # The return value is an array of FetchData.
2791
+ #
2792
+ # Related: #uid_store
2793
+ #
2794
+ # ==== For example:
2795
+ #
2796
+ # p imap.store(6..8, "+FLAGS", [:Deleted])
2797
+ # #=> [#<Net::IMAP::FetchData seqno=6, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2798
+ # #<Net::IMAP::FetchData seqno=7, attr={"FLAGS"=>[:Seen, :Deleted]}>,
2799
+ # #<Net::IMAP::FetchData seqno=8, attr={"FLAGS"=>[:Seen, :Deleted]}>]
2800
+ #
2801
+ # ==== Capabilities
2802
+ #
2803
+ # Extensions may define new data items to be used with #store.
2804
+ #
2805
+ # The server's capabilities must include +CONDSTORE+
2806
+ # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162] in order to use the
2807
+ # +unchangedsince+ argument. Using +unchangedsince+ implicitly enables the
2808
+ # +CONDSTORE+ extension.
2809
+ #
2810
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2811
+ # +STORE+ command is prohibited. Use #uid_store instead.
2812
+ def store(set, attr, flags, unchangedsince: nil)
2813
+ store_internal("STORE", set, attr, flags, unchangedsince: unchangedsince)
2814
+ end
2815
+
2816
+ # :call-seq:
2817
+ # uid_store(set, attr, value, unchangedsince: nil) -> array of FetchData (or UIDFetchData)
2818
+ #
2819
+ # Sends a {UID STORE command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2820
+ # to alter data associated with messages in the mailbox, in particular their
2821
+ # flags.
2822
+ #
2823
+ # Similar to #store, but +set+ contains unique identifiers instead of
2824
+ # message sequence numbers.
2825
+ #
2826
+ # Related: #store
2827
+ #
2828
+ # ==== Capabilities
2829
+ #
2830
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2831
+ # #uid_store must be used instead of #store, and UIDFetchData will be
2832
+ # returned instead of FetchData.
2833
+ #
2834
+ # Otherwise, #uid_store is updated by extensions in the same way as #store.
2835
+ def uid_store(set, attr, flags, unchangedsince: nil)
2836
+ store_internal("UID STORE", set, attr, flags, unchangedsince: unchangedsince)
2837
+ end
2838
+
2839
+ # Sends a {COPY command [IMAP4rev1 §6.4.7]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.7]
2840
+ # to copy the specified message(s) to the end of the specified destination
2841
+ # +mailbox+. The +set+ parameter is a number, an array of numbers, or a
2842
+ # Range object. The number is a message sequence number.
2843
+ #
2844
+ # Related: #uid_copy
2845
+ #
2846
+ # ==== Capabilities
2847
+ #
2848
+ # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
2849
+ # supported, the server's response should include a +COPYUID+ response code
2850
+ # with UIDPlusData. This will report the UIDVALIDITY of the destination
2851
+ # mailbox, the UID set of the source messages, and the assigned UID set of
2852
+ # the moved messages.
2853
+ #
2854
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2855
+ # +COPY+ command is prohibited. Use #uid_copy instead.
2856
+ def copy(set, mailbox)
2857
+ copy_internal("COPY", set, mailbox)
2858
+ end
2859
+
2860
+ # Sends a {UID COPY command [IMAP4rev1 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.4.8]
2861
+ # to copy the specified message(s) to the end of the specified destination
2862
+ # +mailbox+.
2863
+ #
2864
+ # Similar to #copy, but +set+ contains unique identifiers.
2865
+ #
2866
+ # ==== Capabilities
2867
+ #
2868
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] in enabled,
2869
+ # #uid_copy must be used instead of #copy.
2870
+ #
2871
+ # Otherwise, #uid_copy is updated by extensions in the same way as #copy.
2872
+ def uid_copy(set, mailbox)
2873
+ copy_internal("UID COPY", set, mailbox)
2874
+ end
2875
+
2876
+ # Sends a {MOVE command [RFC6851 §3.1]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.1]
2877
+ # {[IMAP4rev2 §6.4.8]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.8]
2878
+ # to move the specified message(s) to the end of the specified destination
2879
+ # +mailbox+. The +set+ parameter is a number, an array of numbers, or a
2880
+ # Range object. The number is a message sequence number.
2881
+ #
2882
+ # Related: #uid_move
2883
+ #
2884
+ # ==== Capabilities
2885
+ #
2886
+ # The server's capabilities must include either +IMAP4rev2+ or +MOVE+
2887
+ # [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
2888
+ #
2889
+ # If +UIDPLUS+ [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]] is
2890
+ # supported, the server's response should include a +COPYUID+ response code
2891
+ # with UIDPlusData. This will report the UIDVALIDITY of the destination
2892
+ # mailbox, the UID set of the source messages, and the assigned UID set of
2893
+ # the moved messages.
2894
+ #
2895
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled, the
2896
+ # +MOVE+ command is prohibited. Use #uid_move instead.
2897
+ def move(set, mailbox)
2898
+ copy_internal("MOVE", set, mailbox)
2899
+ end
2900
+
2901
+ # Sends a {UID MOVE command [RFC6851 §3.2]}[https://www.rfc-editor.org/rfc/rfc6851#section-3.2]
2902
+ # {[IMAP4rev2 §6.4.9]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.4.9]
2903
+ # to move the specified message(s) to the end of the specified destination
2904
+ # +mailbox+.
2905
+ #
2906
+ # Similar to #move, but +set+ contains unique identifiers.
2907
+ #
2908
+ # Related: #move
2909
+ #
2910
+ # ==== Capabilities
2911
+ #
2912
+ # The server's capabilities must include either +IMAP4rev2+ or +MOVE+
2913
+ # [RFC6851[https://www.rfc-editor.org/rfc/rfc6851]].
2914
+ #
2915
+ # When UIDONLY[https://www.rfc-editor.org/rfc/rfc9586.html] is enabled,
2916
+ # #uid_move must be used instead of #move.
2917
+ #
2918
+ # Otherwise, #uid_move is updated by extensions in the same way as #move.
2919
+ def uid_move(set, mailbox)
2920
+ copy_internal("UID MOVE", set, mailbox)
2921
+ end
2922
+
2923
+ # Sends a {SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
2924
+ # to search a mailbox for messages that match +search_keys+ and return an
2925
+ # array of message sequence numbers, sorted by +sort_keys+.
2926
+ #
2927
+ # +search_keys+ are interpreted the same as the +criteria+ argument for
2928
+ # #search. <em>Please note</em> the #search warning for String +criteria+.
2929
+ #
2930
+ #--
2931
+ # TODO: describe +sort_keys+
2932
+ #++
2933
+ #
2934
+ # Related: #uid_sort, #search, #uid_search, #thread, #uid_thread
2935
+ #
2936
+ # ==== For example:
2937
+ #
2938
+ # p imap.sort(["FROM"], ["ALL"], "US-ASCII")
2939
+ # #=> [1, 2, 3, 5, 6, 7, 8, 4, 9]
2940
+ # p imap.sort(["DATE"], ["SUBJECT", "hello"], "US-ASCII")
2941
+ # #=> [6, 7, 8, 1]
2942
+ #
2943
+ # ==== Capabilities
2944
+ #
2945
+ # The server's capabilities must include +SORT+
2946
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2947
+ def sort(sort_keys, search_keys, charset)
2948
+ return sort_internal("SORT", sort_keys, search_keys, charset)
2949
+ end
2950
+
2951
+ # Sends a {UID SORT command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
2952
+ # to search a mailbox for messages that match +search_keys+ and return an
2953
+ # array of unique identifiers, sorted by +sort_keys+.
2954
+ #
2955
+ # +search_keys+ are interpreted the same as the +criteria+ argument for
2956
+ # #search. <em>Please note</em> the #search warning for String +criteria+.
2957
+ #
2958
+ # Related: #sort, #search, #uid_search, #thread, #uid_thread
2959
+ #
2960
+ # ==== Capabilities
2961
+ #
2962
+ # The server's capabilities must include +SORT+
2963
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2964
+ def uid_sort(sort_keys, search_keys, charset)
2965
+ return sort_internal("UID SORT", sort_keys, search_keys, charset)
2966
+ end
2967
+
2968
+ # Sends a {THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
2969
+ # to search a mailbox and return message sequence numbers in threaded
2970
+ # format, as a ThreadMember tree.
2971
+ #
2972
+ # +search_keys+ are interpreted the same as the +criteria+ argument for
2973
+ # #search. <em>Please note</em> the #search warning for String +criteria+.
2974
+ #
2975
+ # The supported algorithms are:
2976
+ #
2977
+ # ORDEREDSUBJECT:: split into single-level threads according to subject,
2978
+ # ordered by date.
2979
+ # REFERENCES:: split into threads by parent/child relationships determined
2980
+ # by which message is a reply to which.
2981
+ #
2982
+ # Unlike #search, +charset+ is a required argument. US-ASCII
2983
+ # and UTF-8 are sample values.
2984
+ #
2985
+ # Related: #uid_thread, #search, #uid_search, #sort, #uid_sort
2986
+ #
2987
+ # ==== Capabilities
2988
+ #
2989
+ # The server's capabilities must include +THREAD+
2990
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
2991
+ def thread(algorithm, search_keys, charset)
2992
+ return thread_internal("THREAD", algorithm, search_keys, charset)
2993
+ end
2994
+
2995
+ # Sends a {UID THREAD command [RFC5256 §3]}[https://www.rfc-editor.org/rfc/rfc5256#section-3]
2996
+ # Similar to #thread, but returns unique identifiers instead of
2997
+ # message sequence numbers.
2998
+ #
2999
+ # +search_keys+ are interpreted the same as the +criteria+ argument for
3000
+ # #search. <em>Please note</em> the #search warning for String +criteria+.
3001
+ #
3002
+ # Related: #thread, #search, #uid_search, #sort, #uid_sort
3003
+ #
3004
+ # ==== Capabilities
3005
+ #
3006
+ # The server's capabilities must include +THREAD+
3007
+ # [RFC5256[https://www.rfc-editor.org/rfc/rfc5256]].
3008
+ def uid_thread(algorithm, search_keys, charset)
3009
+ return thread_internal("UID THREAD", algorithm, search_keys, charset)
3010
+ end
3011
+
3012
+ # Sends an {ENABLE command [RFC5161 §3.2]}[https://www.rfc-editor.org/rfc/rfc5161#section-3.1]
3013
+ # {[IMAP4rev2 §6.3.1]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.3.1]
3014
+ # to enable the specified server +capabilities+. Each capability may be an
3015
+ # array, string, or symbol. Returns a list of the capabilities that were
3016
+ # enabled.
3017
+ #
3018
+ # The +ENABLE+ command is only valid in the _authenticated_ state, before
3019
+ # any mailbox is selected.
3020
+ #
3021
+ # Related: #capable?, #capabilities, #capability
3022
+ #
3023
+ # ==== Capabilities
3024
+ #
3025
+ # The server's capabilities must include
3026
+ # +ENABLE+ [RFC5161[https://www.rfc-editor.org/rfc/rfc5161]]
3027
+ # or +IMAP4REV2+ [RFC9051[https://www.rfc-editor.org/rfc/rfc9051]].
3028
+ #
3029
+ # Additionally, the server capabilities must include a capability matching
3030
+ # each enabled extension (usually the same name as the enabled extension).
3031
+ # The following capabilities may be enabled:
3032
+ #
3033
+ # [+CONDSTORE+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
3034
+ #
3035
+ # Updates various commands to return +CONDSTORE+ extension responses. It
3036
+ # is not necessary to explicitly enable +CONDSTORE+—using any of the
3037
+ # command parameters defined by the extension will implicitly enable it.
3038
+ # See {[RFC7162 §3.1]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.1].
3039
+ #
3040
+ # [+QRESYNC+ {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html]]
3041
+ # *NOTE:* Enabling QRESYNC will replace +EXPUNGE+ with +VANISHED+, but
3042
+ # the extension arguments to #select, #examine, and #uid_fetch are not
3043
+ # supported yet.
3044
+ #
3045
+ # Adds quick resynchronization options to #select, #examine, and
3046
+ # #uid_fetch. +QRESYNC+ _must_ be explicitly enabled before using any of
3047
+ # the extension's command parameters. All +EXPUNGE+ responses will be
3048
+ # replaced with +VANISHED+ responses. Enabling +QRESYNC+ implicitly
3049
+ # enables +CONDSTORE+ as well.
3050
+ # See {[RFC7162 §3.2]}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.2].
3051
+ #
3052
+ # [+:utf8+ --- an alias for <tt>"UTF8=ACCEPT"</tt>]
3053
+ #
3054
+ # In a future release, <tt>enable(:utf8)</tt> will enable either
3055
+ # <tt>"UTF8=ACCEPT"</tt> or <tt>"IMAP4rev2"</tt>, depending on server
3056
+ # capabilities.
3057
+ #
3058
+ # [<tt>"UTF8=ACCEPT"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
3059
+ #
3060
+ # The server's capabilities must include <tt>UTF8=ACCEPT</tt> _or_
3061
+ # <tt>UTF8=ONLY</tt>.
3062
+ #
3063
+ # This allows the server to send strings encoded as UTF-8 which might
3064
+ # otherwise need to use a 7-bit encoding, such as {modified
3065
+ # UTF-7}[::decode_utf7] for mailbox names, or RFC2047 encoded-words for
3066
+ # message headers.
3067
+ #
3068
+ # *Note:* <em>A future update may set string encodings slightly
3069
+ # differently</em>, e.g: "US-ASCII" when UTF-8 is not enabled, and "UTF-8"
3070
+ # when it is. Currently, the encoding of strings sent as "quoted" or
3071
+ # "text" will _always_ be "UTF-8", even when only ASCII characters are
3072
+ # used (e.g. "Subject: Agenda") And currently, string "literals" sent
3073
+ # by the server will always have an "ASCII-8BIT" (binary)
3074
+ # encoding, even if they generally contain UTF-8 data, if they are
3075
+ # text at all.
3076
+ #
3077
+ # [<tt>"UTF8=ONLY"</tt> [RFC6855[https://www.rfc-editor.org/rfc/rfc6855]]]
3078
+ #
3079
+ # A server that reports the <tt>UTF8=ONLY</tt> capability _requires_ that
3080
+ # the client <tt>enable("UTF8=ACCEPT")</tt> before any mailboxes may be
3081
+ # selected. For convenience, <tt>enable("UTF8=ONLY")</tt> is aliased to
3082
+ # <tt>enable("UTF8=ACCEPT")</tt>.
3083
+ #
3084
+ # [+UIDONLY+ {[RFC9586]}[https://www.rfc-editor.org/rfc/rfc9586.pdf]]
3085
+ #
3086
+ # When UIDONLY is enabled, the #fetch, #store, #search, #copy, and #move
3087
+ # commands are prohibited and result in a tagged BAD response. Clients
3088
+ # should instead use uid_fetch, uid_store, uid_search, uid_copy, or
3089
+ # uid_move, respectively. All +FETCH+ responses that would be returned are
3090
+ # replaced by +UIDFETCH+ responses. All +EXPUNGED+ responses that would be
3091
+ # returned are replaced by +VANISHED+ responses. The "<sequence set>"
3092
+ # uid_search criterion is prohibited.
3093
+ #
3094
+ # ===== Unsupported capabilities
3095
+ #
3096
+ # *Note:* Some extensions that use ENABLE permit the server to send syntax
3097
+ # that Net::IMAP cannot parse, which may raise an exception and disconnect.
3098
+ # Some extensions may work, but the support may be incomplete, untested, or
3099
+ # experimental.
3100
+ #
3101
+ # Until a capability is documented here as supported, enabling it may result
3102
+ # in undocumented behavior and a future release may update with incompatible
3103
+ # behavior <em>without warning or deprecation</em>.
3104
+ #
3105
+ # <em>Caution is advised.</em>
3106
+ #
3107
+ def enable(*capabilities)
3108
+ capabilities = capabilities
3109
+ .flatten
3110
+ .map {|e| ENABLE_ALIASES[e] || e }
3111
+ .flat_map { _1.is_a?(String) && !_1.empty? ? _1.split(/ /, -1) : [_1] }
3112
+ .uniq
3113
+ .map { Atom[_1] }
3114
+ synchronize do
3115
+ send_command("ENABLE", *capabilities)
3116
+ result = clear_responses("ENABLED").last || []
3117
+ @utf8_strings ||= result.include? "UTF8=ACCEPT"
3118
+ @utf8_strings ||= result.include? "IMAP4REV2"
3119
+ result
3120
+ end
3121
+ end
3122
+
3123
+ # Sends an {IDLE command [RFC2177 §3]}[https://www.rfc-editor.org/rfc/rfc6851#section-3]
3124
+ # {[IMAP4rev2 §6.3.13]}[https://www.rfc-editor.org/rfc/rfc9051#section-6.3.13]
3125
+ # that waits for notifications of new or expunged messages. Yields
3126
+ # responses from the server during the IDLE.
3127
+ #
3128
+ # Use #idle_done to leave IDLE.
3129
+ #
3130
+ # If +timeout+ is given, this method returns after +timeout+ seconds passed.
3131
+ # +timeout+ can be used for keep-alive. For example, the following code
3132
+ # checks the connection for each 60 seconds.
3133
+ #
3134
+ # loop do
3135
+ # imap.idle(60) do |response|
3136
+ # do_something_with(response)
3137
+ # imap.idle_done if some_condition?(response)
3138
+ # end
3139
+ # end
3140
+ #
3141
+ # Returns the server's response to indicate the IDLE state has ended.
3142
+ # Returns +nil+ if the server does not respond to #idle_done within
3143
+ # {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]
3144
+ # seconds.
3145
+ #
3146
+ # Related: #idle_done, #noop, #check
3147
+ #
3148
+ # ==== Capabilities
3149
+ #
3150
+ # The server's capabilities must include either +IMAP4rev2+ or +IDLE+
3151
+ # [RFC2177[https://www.rfc-editor.org/rfc/rfc2177]].
3152
+ def idle(timeout = nil, &response_handler)
3153
+ raise LocalJumpError, "no block given" unless response_handler
3154
+
3155
+ response = nil
3156
+
3157
+ synchronize do
3158
+ tag = Thread.current[:net_imap_tag] = generate_tag
3159
+ guard_against_tagged_response_skipping_handler!(tag, "IDLE")
3160
+ put_string("#{tag} IDLE#{CRLF}")
3161
+
3162
+ begin
3163
+ add_response_handler(&response_handler)
3164
+ @idle_done_cond = new_cond
3165
+ @idle_done_cond.wait(timeout)
3166
+ @idle_done_cond = nil
3167
+ if @receiver_thread_terminating
3168
+ raise @exception || Net::IMAP::Error.new("connection closed")
3169
+ end
3170
+ ensure
3171
+ remove_response_handler(response_handler)
3172
+ unless @receiver_thread_terminating
3173
+ put_string("DONE#{CRLF}")
3174
+ response = get_tagged_response(tag, "IDLE", idle_response_timeout)
3175
+ end
3176
+ end
3177
+ end
3178
+
3179
+ return response
3180
+ end
3181
+
3182
+ # Leaves IDLE, allowing #idle to return.
3183
+ #
3184
+ # If the server does not respond within
3185
+ # {config.idle_response_timeout}[rdoc-ref:Config#idle_response_timeout]
3186
+ # seconds, #idle will return +nil+.
3187
+ #
3188
+ # Related: #idle
3189
+ def idle_done
3190
+ synchronize do
3191
+ if @idle_done_cond.nil?
3192
+ raise Net::IMAP::Error, "not during IDLE"
3193
+ end
3194
+ @idle_done_cond.signal
3195
+ end
3196
+ end
3197
+
3198
+ RESPONSES_DEPRECATION_MSG =
3199
+ "Pass a type or block to #responses, " \
3200
+ "set config.responses_without_block to :frozen_dup " \
3201
+ "or :silence_deprecation_warning, " \
3202
+ "or use #extract_responses or #clear_responses."
3203
+ private_constant :RESPONSES_DEPRECATION_MSG
3204
+
3205
+ # :call-seq:
3206
+ # responses -> hash of {String => Array} (see config.responses_without_block)
3207
+ # responses(type) -> frozen array
3208
+ # responses {|hash| ...} -> block result
3209
+ # responses(type) {|array| ...} -> block result
3210
+ #
3211
+ # Yields or returns unhandled server responses. Unhandled responses are
3212
+ # stored in a hash, with arrays of UntaggedResponse#data keyed by
3213
+ # UntaggedResponse#name and <em>non-+nil+</em> untagged ResponseCode#data
3214
+ # keyed by ResponseCode#name.
3215
+ #
3216
+ # When a block is given, yields unhandled responses and returns the block's
3217
+ # result. Without a block, returns the unhandled responses.
3218
+ #
3219
+ # [With +type+]
3220
+ # Yield or return only the array of responses for that +type+.
3221
+ # When no block is given, the returned array is a frozen copy.
3222
+ # [Without +type+]
3223
+ # Yield or return the entire responses hash.
3224
+ #
3225
+ # When no block is given, the behavior is determined by
3226
+ # Config#responses_without_block:
3227
+ # >>>
3228
+ # [+:silence_deprecation_warning+ <em>(original behavior)</em>]
3229
+ # Returns the mutable responses hash (without any warnings).
3230
+ # <em>This is not thread-safe.</em>
3231
+ #
3232
+ # [+:warn+ <em>(default since +v0.5+)</em>]
3233
+ # Prints a warning and returns the mutable responses hash.
3234
+ # <em>This is not thread-safe.</em>
3235
+ #
3236
+ # [+:frozen_dup+ <em>(planned default for +v0.6+)</em>]
3237
+ # Returns a frozen copy of the unhandled responses hash, with frozen
3238
+ # array values.
3239
+ #
3240
+ # [+:raise+]
3241
+ # Raise an +ArgumentError+ with the deprecation warning.
3242
+ #
3243
+ # For example:
3244
+ #
3245
+ # imap.select("inbox")
3246
+ # p imap.responses("EXISTS").last
3247
+ # #=> 2
3248
+ # p imap.responses("UIDNEXT", &:last)
3249
+ # #=> 123456
3250
+ # p imap.responses("UIDVALIDITY", &:last)
3251
+ # #=> 968263756
3252
+ # p imap.responses {|responses|
3253
+ # {
3254
+ # exists: responses.delete("EXISTS").last,
3255
+ # uidnext: responses.delete("UIDNEXT").last,
3256
+ # uidvalidity: responses.delete("UIDVALIDITY").last,
3257
+ # }
3258
+ # }
3259
+ # #=> {:exists=>2, :uidnext=>123456, :uidvalidity=>968263756}
3260
+ # # "EXISTS", "UIDNEXT", and "UIDVALIDITY" have been removed:
3261
+ # p imap.responses(&:keys)
3262
+ # #=> ["FLAGS", "OK", "PERMANENTFLAGS", "RECENT", "HIGHESTMODSEQ"]
3263
+ #
3264
+ # Related: #extract_responses, #clear_responses, #response_handlers, #greeting
3265
+ #
3266
+ # ==== Thread safety
3267
+ # >>>
3268
+ # *Note:* Access to the responses hash is synchronized for thread-safety.
3269
+ # The receiver thread and response_handlers cannot process new responses
3270
+ # until the block completes. Accessing either the response hash or its
3271
+ # response type arrays outside of the block is unsafe. They can be safely
3272
+ # updated inside the block. Consider using #clear_responses or
3273
+ # #extract_responses instead.
3274
+ #
3275
+ # Net::IMAP will add and remove responses from the responses hash and its
3276
+ # array values, in the calling threads for commands and in the receiver
3277
+ # thread, but will not modify any responses after adding them to the
3278
+ # responses hash.
3279
+ #
3280
+ # ==== Clearing responses
3281
+ #
3282
+ # Previously unhandled responses are automatically cleared before entering a
3283
+ # mailbox with #select or #examine. Long-lived connections can receive many
3284
+ # unhandled server responses, which must be pruned or they will continually
3285
+ # consume more memory. Update or clear the responses hash or arrays inside
3286
+ # the block, or remove responses with #extract_responses, #clear_responses,
3287
+ # or #add_response_handler.
3288
+ #
3289
+ # ==== Missing responses
3290
+ #
3291
+ # Only non-+nil+ data is stored. Many important response codes have no data
3292
+ # of their own, but are used as "tags" on the ResponseText object they are
3293
+ # attached to. ResponseText will be accessible by its response types:
3294
+ # "+OK+", "+NO+", "+BAD+", "+BYE+", or "+PREAUTH+".
3295
+ #
3296
+ # TaggedResponse#data is not saved to #responses, nor is any
3297
+ # ResponseCode#data on tagged responses. Although some command methods do
3298
+ # return the TaggedResponse directly, #add_response_handler must be used to
3299
+ # handle all response codes.
3300
+ def responses(type = nil)
3301
+ if block_given?
3302
+ synchronize { yield(type ? @responses[type.to_s.upcase] : @responses) }
3303
+ elsif type
3304
+ synchronize { @responses[type.to_s.upcase].dup.freeze }
3305
+ else
3306
+ case config.responses_without_block
3307
+ when :raise
3308
+ raise ArgumentError, RESPONSES_DEPRECATION_MSG
3309
+ when :warn
3310
+ warn(RESPONSES_DEPRECATION_MSG, uplevel: 1, category: :deprecated)
3311
+ when :frozen_dup
3312
+ synchronize {
3313
+ responses = @responses.transform_values { _1.dup.freeze }
3314
+ responses.default_proc = nil
3315
+ responses.default = [].freeze
3316
+ return responses.freeze
3317
+ }
3318
+ end
3319
+ @responses
3320
+ end
3321
+ end
3322
+
3323
+ # :call-seq:
3324
+ # clear_responses -> hash
3325
+ # clear_responses(type) -> array
3326
+ #
3327
+ # Clears and returns the unhandled #responses hash or the unhandled
3328
+ # responses array for a single response +type+.
3329
+ #
3330
+ # Clearing responses is synchronized with other threads. The lock is
3331
+ # released before returning.
3332
+ #
3333
+ # Related: #extract_responses, #responses, #response_handlers
3334
+ def clear_responses(type = nil)
3335
+ synchronize {
3336
+ if type
3337
+ @responses.delete(type) || []
3338
+ else
3339
+ @responses.dup.transform_values(&:freeze)
3340
+ .tap { _1.default = [].freeze }
3341
+ .tap { @responses.clear }
3342
+ end
3343
+ }
3344
+ .freeze
3345
+ end
3346
+
3347
+ # :call-seq:
3348
+ # extract_responses(type) {|response| ... } -> array
3349
+ #
3350
+ # Yields all of the unhandled #responses for a single response +type+.
3351
+ # Removes and returns the responses for which the block returns a true
3352
+ # value.
3353
+ #
3354
+ # Extracting responses is synchronized with other threads. The lock is
3355
+ # released before returning.
3356
+ #
3357
+ # Related: #responses, #clear_responses
3358
+ def extract_responses(type)
3359
+ type = String.try_convert(type) or
3360
+ raise ArgumentError, "type must be a string"
3361
+ raise ArgumentError, "must provide a block" unless block_given?
3362
+ extracted = []
3363
+ responses(type) do |all|
3364
+ all.reject! do |response|
3365
+ extracted << response if yield response
3366
+ end
3367
+ end
3368
+ extracted
3369
+ end
3370
+
3371
+ # Returns all response handlers, including those that are added internally
3372
+ # by commands. Each response handler will be called with every new
3373
+ # UntaggedResponse, TaggedResponse, and ContinuationRequest.
3374
+ #
3375
+ # Response handlers are called with a mutex inside the receiver thread. New
3376
+ # responses cannot be processed and commands from other threads must wait
3377
+ # until all response_handlers return. An exception will shut-down the
3378
+ # receiver thread and close the connection.
3379
+ #
3380
+ # For thread-safety, the returned array is a frozen copy of the internal
3381
+ # array.
3382
+ #
3383
+ # Related: #add_response_handler, #remove_response_handler
3384
+ def response_handlers
3385
+ synchronize { @response_handlers.clone.freeze }
3386
+ end
3387
+
3388
+ # Adds a response handler. For example, to detect when
3389
+ # the server sends a new EXISTS response (which normally
3390
+ # indicates new messages being added to the mailbox),
3391
+ # add the following handler after selecting the
3392
+ # mailbox:
3393
+ #
3394
+ # imap.add_response_handler { |resp|
3395
+ # if resp.kind_of?(Net::IMAP::UntaggedResponse) and resp.name == "EXISTS"
3396
+ # puts "Mailbox now has #{resp.data} messages"
3397
+ # end
3398
+ # }
3399
+ #
3400
+ # Response handlers can also be added when the client is created before the
3401
+ # receiver thread is started, by the +response_handlers+ argument to ::new.
3402
+ # This ensures every server response is handled, including the #greeting.
3403
+ #
3404
+ # Related: #remove_response_handler, #response_handlers
3405
+ def add_response_handler(handler = nil, &block)
3406
+ raise ArgumentError, "two Procs are passed" if handler && block
3407
+ synchronize do
3408
+ @response_handlers.push(block || handler)
3409
+ end
3410
+ end
3411
+
3412
+ # Removes the response handler.
3413
+ #
3414
+ # Related: #add_response_handler, #response_handlers
3415
+ def remove_response_handler(handler)
3416
+ synchronize do
3417
+ @response_handlers.delete(handler)
3418
+ end
3419
+ end
3420
+
3421
+ private
3422
+
3423
+ CRLF = "\r\n" # :nodoc:
3424
+ PORT = 143 # :nodoc:
3425
+ SSL_PORT = 993 # :nodoc:
3426
+
3427
+ def start_imap_connection
3428
+ @greeting = get_server_greeting
3429
+ @capabilities = capabilities_from_resp_code @greeting
3430
+ @response_handlers.each do |handler| handler.call(@greeting) end
3431
+ @receiver_thread = start_receiver_thread
3432
+ rescue Exception
3433
+ state_logout!
3434
+ @sock.close
3435
+ raise
3436
+ end
3437
+
3438
+ def get_server_greeting
3439
+ greeting = get_response
3440
+ raise Error, "No server greeting - connection closed" unless greeting
3441
+ record_untagged_response_code greeting
3442
+ case greeting.name
3443
+ when "PREAUTH" then state_authenticated!
3444
+ when "BYE" then state_logout!; raise ByeResponseError, greeting
3445
+ end
3446
+ greeting
3447
+ end
3448
+
3449
+ def start_receiver_thread
3450
+ Thread.start do
3451
+ receive_responses
3452
+ rescue Exception => ex
3453
+ @receiver_thread_exception = ex
3454
+ # don't exit the thread with an exception
3455
+ end
3456
+ end
3457
+
3458
+ def tcp_socket(host, port)
3459
+ s = Socket.tcp(host, port, :connect_timeout => open_timeout)
3460
+ s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)
3461
+ s
3462
+ rescue Errno::ETIMEDOUT
3463
+ raise Net::OpenTimeout, "Timeout to open TCP connection to " +
3464
+ "#{host}:#{port} (exceeds #{open_timeout} seconds)"
3465
+ end
3466
+
3467
+ def receive_responses
3468
+ connection_closed = false
3469
+ until connection_closed
3470
+ synchronize do
3471
+ @exception = nil
3472
+ end
3473
+ begin
3474
+ resp = get_response
3475
+ rescue Exception => e
3476
+ synchronize do
3477
+ state_logout!
3478
+ @sock.close
3479
+ @exception = e
3480
+ end
3481
+ break
3482
+ end
3483
+ unless resp
3484
+ synchronize do
3485
+ @exception = EOFError.new("end of file reached")
3486
+ end
3487
+ break
3488
+ end
3489
+ begin
3490
+ synchronize do
3491
+ case resp
3492
+ when TaggedResponse
3493
+ @tagged_responses[resp.tag] = resp
3494
+ @tagged_response_arrival.broadcast
3495
+ case resp.tag
3496
+ when @logout_command_tag
3497
+ state_logout!
3498
+ return
3499
+ when @continued_command_tag
3500
+ @continuation_request_exception =
3501
+ RESPONSE_ERRORS[resp.name].new(resp)
3502
+ @continuation_request_arrival.signal
3503
+ end
3504
+ when UntaggedResponse
3505
+ record_untagged_response(resp)
3506
+ if resp.name == "BYE" && @logout_command_tag.nil?
3507
+ state_logout!
3508
+ @sock.close
3509
+ @exception = ByeResponseError.new(resp)
3510
+ connection_closed = true
3511
+ end
3512
+ when ContinuationRequest
3513
+ @continuation_request_arrival.signal
3514
+ end
3515
+ state_unselected! if resp in {data: {code: {name: "CLOSED"}}}
3516
+ @response_handlers.each do |handler|
3517
+ handler.call(resp)
3518
+ end
3519
+ end
3520
+ rescue Exception => e
3521
+ @exception = e
3522
+ synchronize do
3523
+ @tagged_response_arrival.broadcast
3524
+ @continuation_request_arrival.broadcast
3525
+ end
3526
+ end
3527
+ end
3528
+ synchronize do
3529
+ @receiver_thread_terminating = true
3530
+ @tagged_response_arrival.broadcast
3531
+ @continuation_request_arrival.broadcast
3532
+ if @idle_done_cond
3533
+ @idle_done_cond.signal
3534
+ end
3535
+ end
3536
+ ensure
3537
+ state_logout!
3538
+ end
3539
+
3540
+ def get_tagged_response(tag, cmd, timeout = nil)
3541
+ if timeout
3542
+ deadline = Time.now + timeout
3543
+ end
3544
+ until @tagged_responses.key?(tag)
3545
+ raise @exception if @exception
3546
+ if timeout
3547
+ timeout = deadline - Time.now
3548
+ if timeout <= 0
3549
+ return nil
3550
+ end
3551
+ end
3552
+ @tagged_response_arrival.wait(timeout)
3553
+ end
3554
+ resp = @tagged_responses.delete(tag)
3555
+ case resp.name
3556
+ when /\A(?:OK)\z/ni
3557
+ return resp
3558
+ when /\A(?:NO)\z/ni
3559
+ raise NoResponseError, resp
3560
+ when /\A(?:BAD)\z/ni
3561
+ raise BadResponseError, resp
3562
+ else
3563
+ disconnect
3564
+ raise InvalidResponseError, "invalid tagged resp: %p" % [resp.raw.chomp]
3565
+ end
3566
+ end
3567
+
3568
+ def get_response
3569
+ buff = @reader.read_response_buffer
3570
+ return nil if buff.length == 0
3571
+ $stderr.print(buff.gsub(/^/n, "S: ")) if config.debug?
3572
+ @parser.parse(buff)
3573
+ end
3574
+
3575
+ #############################
3576
+ # built-in response handlers
3577
+
3578
+ # store name => [..., data]
3579
+ def record_untagged_response(resp)
3580
+ @responses[resp.name] << resp.data
3581
+ record_untagged_response_code resp
3582
+ end
3583
+
3584
+ # store code.name => [..., code.data]
3585
+ def record_untagged_response_code(resp)
3586
+ return unless resp.data.is_a?(ResponseText)
3587
+ return unless (code = resp.data.code)
3588
+ @responses[code.name] << code.data
3589
+ end
3590
+
3591
+ # NOTE: only call this for greeting, login, and authenticate
3592
+ def capabilities_from_resp_code(resp)
3593
+ return unless %w[PREAUTH OK].any? { _1.casecmp? resp.name }
3594
+ return unless (code = resp.data.code)
3595
+ return unless code.name.casecmp?("CAPABILITY")
3596
+ code.data.freeze
3597
+ end
3598
+
3599
+ #############################
3600
+
3601
+ # Calls send_command, yielding the text of each ContinuationRequest and
3602
+ # responding with each block result. Returns TaggedResponse. Raises
3603
+ # NoResponseError or BadResponseError.
3604
+ def send_command_with_continuations(cmd, *args)
3605
+ send_command(cmd, *args) do |server_response|
3606
+ if server_response.instance_of?(ContinuationRequest)
3607
+ client_response = yield server_response.data.text
3608
+ put_string(client_response + CRLF)
3609
+ end
3610
+ end
3611
+ end
3612
+
3613
+ def send_command(cmd, *args, &block)
3614
+ synchronize do
3615
+ args.each do |i|
3616
+ validate_data(i)
3617
+ end
3618
+ tag = generate_tag
3619
+ put_string(tag + " " + cmd)
3620
+ args.each do |i|
3621
+ put_string(" ")
3622
+ send_data(i, tag)
3623
+ end
3624
+ guard_against_tagged_response_skipping_handler!(tag, cmd)
3625
+ put_string(CRLF)
3626
+ if cmd == "LOGOUT"
3627
+ @logout_command_tag = tag
3628
+ end
3629
+ if block
3630
+ add_response_handler(&block)
3631
+ end
3632
+ begin
3633
+ return get_tagged_response(tag, cmd)
3634
+ ensure
3635
+ if block
3636
+ remove_response_handler(block)
3637
+ end
3638
+ end
3639
+ end
3640
+ rescue InvalidResponseError
3641
+ disconnect
3642
+ raise
3643
+ end
3644
+
3645
+ def guard_against_tagged_response_skipping_handler!(tag, cmd)
3646
+ return unless (resp = @tagged_responses[tag])&.name&.upcase == "OK"
3647
+ raise InvalidResponseError, format(
3648
+ "Received tagged 'OK' to incomplete %s command (tag=%s). " \
3649
+ "This could indicate a malicious server, a man-in-the-middle, or " \
3650
+ "client-side command injection. Disconnecting.",
3651
+ cmd, tag
3652
+ )
3653
+ end
3654
+
3655
+ def generate_tag
3656
+ @tagno += 1
3657
+ return format("%s%04d", @tag_prefix, @tagno)
3658
+ end
3659
+
3660
+ def put_string(str)
3661
+ @sock.print(str)
3662
+ if config.debug?
3663
+ if @debug_output_bol
3664
+ $stderr.print("C: ")
3665
+ end
3666
+ $stderr.print(str.gsub(/\n/n) { $'.empty? ? $& : "\nC: " })
3667
+ if /\n\z/n.match(str)
3668
+ @debug_output_bol = true
3669
+ else
3670
+ @debug_output_bol = false
3671
+ end
3672
+ end
3673
+ end
3674
+
3675
+ def enforce_logindisabled?
3676
+ if config.enforce_logindisabled == :when_capabilities_cached
3677
+ capabilities_cached?
3678
+ else
3679
+ config.enforce_logindisabled
3680
+ end
3681
+ end
3682
+
3683
+ def expunge_internal(...)
3684
+ synchronize do
3685
+ send_command(...)
3686
+ expunged_array = clear_responses("EXPUNGE")
3687
+ vanished_array = extract_responses("VANISHED") { !_1.earlier? }
3688
+ if vanished_array.empty?
3689
+ expunged_array
3690
+ elsif vanished_array.length == 1
3691
+ vanished_array.first
3692
+ else
3693
+ merged_uids = SequenceSet[*vanished_array.map(&:uids)]
3694
+ VanishedData[uids: merged_uids, earlier: false]
3695
+ end
3696
+ end
3697
+ end
3698
+
3699
+ RETURN_WHOLE = /\ARETURN\z/i
3700
+ RETURN_START = /\ARETURN\b/i
3701
+ private_constant :RETURN_WHOLE, :RETURN_START
3702
+
3703
+ def search_args(keys, charset_arg = nil, return: nil, charset: nil)
3704
+ {return:} => {return: return_kw}
3705
+ case [return_kw, keys]
3706
+ in [nil, Array[RETURN_WHOLE, return_opts, *keys]]
3707
+ return_opts = convert_return_opts(return_opts)
3708
+ esearch = true
3709
+ in [nil => return_opts, RETURN_START]
3710
+ esearch = true
3711
+ in [nil => return_opts, keys]
3712
+ esearch = false
3713
+ in [_, Array[RETURN_WHOLE, _, *] | RETURN_START]
3714
+ raise ArgumentError, "conflicting return options"
3715
+ in [_, Array[RETURN_WHOLE, _, *]] # workaround for https://bugs.ruby-lang.org/issues/20956
3716
+ raise ArgumentError, "conflicting return options"
3717
+ in [_, RETURN_START] # workaround for https://bugs.ruby-lang.org/issues/20956
3718
+ raise ArgumentError, "conflicting return options"
3719
+ in [return_opts, keys]
3720
+ return_opts = convert_return_opts(return_opts)
3721
+ esearch = true
3722
+ end
3723
+ if charset && charset_arg
3724
+ raise ArgumentError, "multiple charset arguments"
3725
+ end
3726
+ charset ||= charset_arg
3727
+ # NOTE: not handling combined RETURN and CHARSET for raw strings
3728
+ if charset && keys in /\ACHARSET\b/i | Array[/\ACHARSET\z/i, *]
3729
+ raise ArgumentError, "multiple charset arguments"
3730
+ end
3731
+ args = normalize_searching_criteria(keys)
3732
+ args.prepend("CHARSET", charset) if charset
3733
+ args.prepend("RETURN", return_opts) if return_opts
3734
+ return args, esearch
3735
+ end
3736
+
3737
+ def convert_return_opts(unconverted)
3738
+ return_opts = Array.try_convert(unconverted) or
3739
+ raise TypeError, "expected return options to be Array, got %s" % [
3740
+ unconverted.class
3741
+ ]
3742
+ return_opts.map {|opt|
3743
+ case opt
3744
+ when Symbol then opt.to_s
3745
+ when PartialRange::Negative then PartialRange[opt]
3746
+ when Range then SequenceSet[opt]
3747
+ else opt
3748
+ end
3749
+ }
3750
+ end
3751
+
3752
+ def search_internal(cmd, ...)
3753
+ args, esearch = search_args(...)
3754
+ synchronize do
3755
+ tagged = send_command(cmd, *args)
3756
+ tag = tagged.tag
3757
+ # Only the last ESEARCH or SEARCH is used. Excess results are ignored.
3758
+ esearch_result = extract_responses("ESEARCH") {|response|
3759
+ response in ESearchResult(tag: ^tag)
3760
+ }.last
3761
+ search_result = clear_responses("SEARCH").last
3762
+ if esearch_result
3763
+ # silently ignore SEARCH results, if any
3764
+ esearch_result
3765
+ elsif search_result
3766
+ # warn EXPECTED_ESEARCH_RESULT if esearch
3767
+ search_result
3768
+ elsif esearch
3769
+ # warn NO_SEARCH_RESPONSE
3770
+ ESearchResult[tag:, uid: cmd.start_with?("UID ")]
3771
+ else
3772
+ # warn NO_SEARCH_RESPONSE
3773
+ SearchResult[]
3774
+ end
3775
+ end
3776
+ end
3777
+
3778
+ def fetch_internal(cmd, set, attr, mod = nil, partial: nil, changedsince: nil)
3779
+ if partial && !cmd.start_with?("UID ")
3780
+ raise ArgumentError, "partial can only be used with uid_fetch"
3781
+ end
3782
+ set = SequenceSet[set]
3783
+ if partial
3784
+ mod ||= []
3785
+ mod << "PARTIAL" << PartialRange[partial]
3786
+ end
3787
+ if changedsince
3788
+ mod ||= []
3789
+ mod << "CHANGEDSINCE" << Integer(changedsince)
3790
+ end
3791
+ case attr
3792
+ when String then
3793
+ attr = RawData.new(attr)
3794
+ when Array then
3795
+ attr = attr.map { |arg|
3796
+ arg.is_a?(String) ? RawData.new(arg) : arg
3797
+ }
3798
+ end
3799
+
3800
+ args = [cmd, set, attr]
3801
+ args << mod if mod
3802
+ send_command_returning_fetch_results(*args)
3803
+ end
3804
+
3805
+ def store_internal(cmd, set, attr, flags, unchangedsince: nil)
3806
+ attr = Atom.new(attr) if attr.instance_of?(String)
3807
+ args = [SequenceSet.new(set)]
3808
+ args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
3809
+ args << attr << flags
3810
+ send_command_returning_fetch_results(cmd, *args)
3811
+ end
3812
+
3813
+ def send_command_returning_fetch_results(...)
3814
+ synchronize do
3815
+ clear_responses("FETCH")
3816
+ clear_responses("UIDFETCH")
3817
+ send_command(...)
3818
+ fetches = clear_responses("FETCH")
3819
+ uidfetches = clear_responses("UIDFETCH")
3820
+ uidfetches.any? ? uidfetches : fetches
3821
+ end
3822
+ end
3823
+
3824
+ def copy_internal(cmd, set, mailbox)
3825
+ send_command(cmd, SequenceSet.new(set), mailbox)
3826
+ end
3827
+
3828
+ def sort_internal(cmd, sort_keys, search_keys, charset)
3829
+ search_keys = normalize_searching_criteria(search_keys)
3830
+ synchronize do
3831
+ send_command(cmd, sort_keys, charset, *search_keys)
3832
+ clear_responses("SORT").last || []
3833
+ end
3834
+ end
3835
+
3836
+ def thread_internal(cmd, algorithm, search_keys, charset)
3837
+ search_keys = normalize_searching_criteria(search_keys)
3838
+ synchronize do
3839
+ send_command(cmd, algorithm, charset, *search_keys)
3840
+ clear_responses("THREAD").last || []
3841
+ end
3842
+ end
3843
+
3844
+ def normalize_searching_criteria(criteria)
3845
+ return [RawData.new(criteria)] if criteria.is_a?(String)
3846
+ criteria.map {|i|
3847
+ if coerce_search_arg_to_seqset?(i)
3848
+ SequenceSet[i]
3849
+ else
3850
+ i
3851
+ end
3852
+ }
3853
+ end
3854
+
3855
+ def coerce_search_arg_to_seqset?(obj)
3856
+ case obj
3857
+ when Set, -1, :* then true
3858
+ when Range then true
3859
+ when Array then obj.all? { coerce_search_array_arg_to_seqset? _1 }
3860
+ else obj.respond_to?(:to_sequence_set)
3861
+ end
3862
+ end
3863
+
3864
+ def coerce_search_array_arg_to_seqset?(obj)
3865
+ case obj
3866
+ when Integer then obj.positive? || obj == -1
3867
+ when String then ResponseParser::Patterns::SEQUENCE_SET_STR.match?(obj.b)
3868
+ else
3869
+ coerce_search_arg_to_seqset?(obj)
3870
+ end
3871
+ end
3872
+
3873
+ def build_ssl_ctx(ssl)
3874
+ if ssl
3875
+ params = (Hash.try_convert(ssl) || {}).freeze
3876
+ context = SSLContext.new
3877
+ context.set_params(params)
3878
+ if defined?(VerifyCallbackProc)
3879
+ context.verify_callback = VerifyCallbackProc
3880
+ end
3881
+ context.freeze
3882
+ [params, context]
3883
+ else
3884
+ false
3885
+ end
3886
+ end
3887
+
3888
+ def start_tls_session
3889
+ raise "SSL extension not installed" unless defined?(OpenSSL::SSL)
3890
+ raise "already using SSL" if @sock.kind_of?(OpenSSL::SSL::SSLSocket)
3891
+ raise "cannot start TLS without SSLContext" unless ssl_ctx
3892
+ @sock = SSLSocket.new(@sock, ssl_ctx)
3893
+ @reader = ResponseReader.new(self, @sock)
3894
+ @sock.sync_close = true
3895
+ @sock.hostname = @host if @sock.respond_to? :hostname=
3896
+ ssl_socket_connect(@sock, open_timeout)
3897
+ if ssl_ctx.verify_mode != VERIFY_NONE
3898
+ @sock.post_connection_check(@host)
3899
+ @tls_verified = true
3900
+ end
3901
+ end
3902
+
3903
+ def state_authenticated!(resp = nil)
3904
+ synchronize do
3905
+ @capabilities = capabilities_from_resp_code resp if resp
3906
+ @connection_state = ConnectionState::Authenticated.new
3907
+ end
3908
+ end
3909
+
3910
+ def state_selected!
3911
+ synchronize do
3912
+ @connection_state = ConnectionState::Selected.new
3913
+ end
3914
+ end
3915
+
3916
+ def state_unselected!
3917
+ synchronize do
3918
+ state_authenticated! if connection_state.to_sym == :selected
3919
+ end
3920
+ end
3921
+
3922
+ def state_logout!
3923
+ return true if connection_state in [:logout, *]
3924
+ synchronize do
3925
+ return true if connection_state in [:logout, *]
3926
+ @connection_state = ConnectionState::Logout.new
3927
+ end
3928
+ end
3929
+
3930
+ # don't wait to aqcuire the lock
3931
+ def try_state_logout?
3932
+ return true if connection_state in [:logout, *]
3933
+ return false unless acquired_lock = mon_try_enter
3934
+ state_logout!
3935
+ true
3936
+ ensure
3937
+ mon_exit if acquired_lock
3938
+ end
3939
+
3940
+ def sasl_adapter
3941
+ SASLAdapter.new(self, &method(:send_command_with_continuations))
3942
+ end
3943
+
3944
+ #--
3945
+ # We could get the saslprep method by extending the SASLprep module
3946
+ # directly. It's done indirectly, so SASLprep can be lazily autoloaded,
3947
+ # because most users won't need it.
3948
+ #++
3949
+ # Delegates to Net::IMAP::StringPrep::SASLprep#saslprep.
3950
+ def self.saslprep(string, **opts)
3951
+ Net::IMAP::StringPrep::SASLprep.saslprep(string, **opts)
3952
+ end
3953
+
3954
+ end
3955
+ end
3956
+
3957
+ require_relative "imap/errors"
3958
+ require_relative "imap/config"
3959
+ require_relative "imap/command_data"
3960
+ require_relative "imap/data_encoding"
3961
+ require_relative "imap/data_lite"
3962
+ require_relative "imap/flags"
3963
+ require_relative "imap/response_data"
3964
+ require_relative "imap/response_parser"
3965
+ require_relative "imap/authenticators"
3966
+
3967
+ require_relative "imap/deprecated_client_options"
3968
+ Net::IMAP.prepend Net::IMAP::DeprecatedClientOptions