net-imap 0.4.24 → 0.5.0

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.
@@ -129,25 +129,8 @@ module Net
129
129
  def self.global; @global if defined?(@global) end
130
130
 
131
131
  # A hash of hard-coded configurations, indexed by version number or name.
132
- # Values can be accessed with any object that responds to +to_sym+ or
133
- # +to_r+/+to_f+ with a non-zero number.
134
- #
135
- # Config::[] gets named or numbered versions from this hash.
136
- #
137
- # For example:
138
- # Net::IMAP::Config.version_defaults[0.5] == Net::IMAP::Config[0.5]
139
- # Net::IMAP::Config[0.5] == Net::IMAP::Config[0.5r] # => true
140
- # Net::IMAP::Config["current"] == Net::IMAP::Config[:current] # => true
141
- # Net::IMAP::Config["0.5.6"] == Net::IMAP::Config[0.5r] # => true
142
132
  def self.version_defaults; @version_defaults end
143
- @version_defaults = Hash.new {|h, k|
144
- # NOTE: String responds to both so the order is significant.
145
- # And ignore non-numeric conversion to zero, because: "wat!?".to_r == 0
146
- (h.fetch(k.to_r, nil) || h.fetch(k.to_f, nil) if k.is_a?(Numeric)) ||
147
- (h.fetch(k.to_sym, nil) if k.respond_to?(:to_sym)) ||
148
- (h.fetch(k.to_r, nil) if k.respond_to?(:to_r) && k.to_r != 0r) ||
149
- (h.fetch(k.to_f, nil) if k.respond_to?(:to_f) && k.to_f != 0.0)
150
- }
133
+ @version_defaults = {}
151
134
 
152
135
  # :call-seq:
153
136
  # Net::IMAP::Config[number] -> versioned config
@@ -170,17 +153,18 @@ module Net
170
153
  elsif config.nil? && global.nil? then nil
171
154
  elsif config.respond_to?(:to_hash) then new(global, **config).freeze
172
155
  else
173
- version_defaults[config] or
156
+ version_defaults.fetch(config) do
174
157
  case config
175
158
  when Numeric
176
159
  raise RangeError, "unknown config version: %p" % [config]
177
- when String, Symbol
160
+ when Symbol
178
161
  raise KeyError, "unknown config name: %p" % [config]
179
162
  else
180
163
  raise TypeError, "no implicit conversion of %s to %s" % [
181
164
  config.class, Config
182
165
  ]
183
166
  end
167
+ end
184
168
  end
185
169
  end
186
170
 
@@ -207,13 +191,10 @@ module Net
207
191
 
208
192
  # Seconds to wait until a connection is opened.
209
193
  #
210
- # Applied separately for establishing TCP connection and starting a TLS
211
- # connection.
212
- #
213
194
  # If the IMAP object cannot open a connection within this time,
214
195
  # it raises a Net::OpenTimeout exception.
215
196
  #
216
- # See Net::IMAP.new and Net::IMAP#starttls.
197
+ # See Net::IMAP.new.
217
198
  #
218
199
  # The default value is +30+ seconds.
219
200
  attr_accessor :open_timeout, type: Integer
@@ -242,40 +223,29 @@ module Net
242
223
  # Use +SASL-IR+ when it is supported by the server and the mechanism.
243
224
  attr_accessor :sasl_ir, type: :boolean
244
225
 
245
- # The maximum allowed server response size. When +nil+, there is no limit
246
- # on response size.
226
+ # Controls the behavior of Net::IMAP#login when the +LOGINDISABLED+
227
+ # capability is present. When enforced, Net::IMAP will raise a
228
+ # LoginDisabledError when that capability is present.
247
229
  #
248
- # The default value (512 MiB, since +v0.5.7+) is <em>very high</em> and
249
- # unlikely to be reached. To use a lower limit, fetch message bodies in
250
- # chunks rather than all at once. A _much_ lower value should be used
251
- # with untrusted servers (for example, when connecting to a user-provided
252
- # hostname).
230
+ # <em>(Support for +LOGINDISABLED+ was added in +v0.5.0+.)</em>
253
231
  #
254
- # <em>Please Note:</em> this only limits the size per response. It does
255
- # not prevent a flood of individual responses and it does not limit how
256
- # many unhandled responses may be stored on the responses hash. See
257
- # Net::IMAP@Unbounded+memory+use.
258
- #
259
- # Socket reads are limited to the maximum remaining bytes for the current
260
- # response: max_response_size minus the bytes that have already been read.
261
- # When the limit is reached, or reading a +literal+ _would_ go over the
262
- # limit, ResponseTooLargeError is raised and the connection is closed.
263
- # See also #socket_read_limit.
232
+ # ==== Valid options
264
233
  #
265
- # Note that changes will not take effect immediately, because the receiver
266
- # thread may already be waiting for the next response using the previous
267
- # value. Net::IMAP#noop can force a response and enforce the new setting
268
- # immediately.
234
+ # [+false+ <em>(original behavior, before support was added)</em>]
235
+ # Send the +LOGIN+ command without checking for +LOGINDISABLED+.
269
236
  #
270
- # ==== Versioned Defaults
237
+ # [+:when_capabilities_cached+]
238
+ # Enforce the requirement when Net::IMAP#capabilities_cached? is true,
239
+ # but do not send a +CAPABILITY+ command to discover the capabilities.
271
240
  #
272
- # Net::IMAP#max_response_size <em>was added in +v0.2.5+ and +v0.3.9+ as an
273
- # attr_accessor, and in +v0.4.20+ and +v0.5.7+ as a delegator to this
274
- # config attribute.</em>
241
+ # [+true+ <em>(default since +v0.5+)</em>]
242
+ # Only send the +LOGIN+ command if the +LOGINDISABLED+ capability is not
243
+ # present. When capabilities are unknown, Net::IMAP will automatically
244
+ # send a +CAPABILITY+ command first before sending +LOGIN+.
275
245
  #
276
- # * original: +nil+ <em>(no limit)</em>
277
- # * +0.5+: 512 MiB
278
- attr_accessor :max_response_size, type: Integer?
246
+ attr_accessor :enforce_logindisabled, type: [
247
+ false, :when_capabilities_cached, true
248
+ ]
279
249
 
280
250
  # Controls the behavior of Net::IMAP#responses when called without any
281
251
  # arguments (+type+ or +block+).
@@ -303,7 +273,7 @@ module Net
303
273
  # Raise an ArgumentError with the deprecation warning.
304
274
  #
305
275
  # Note: #responses_without_args is an alias for #responses_without_block.
306
- attr_accessor :responses_without_block, type: Enum[
276
+ attr_accessor :responses_without_block, type: [
307
277
  :silence_deprecation_warning, :warn, :frozen_dup, :raise,
308
278
  ]
309
279
 
@@ -315,67 +285,6 @@ module Net
315
285
  #
316
286
  # Alias for responses_without_block
317
287
 
318
- # Whether ResponseParser should use the deprecated UIDPlusData or
319
- # CopyUIDData for +COPYUID+ response codes, and UIDPlusData or
320
- # AppendUIDData for +APPENDUID+ response codes.
321
- #
322
- # UIDPlusData stores its data in arrays of numbers, which is vulnerable to
323
- # a memory exhaustion denial of service attack from an untrusted or
324
- # compromised server. Set this option to +false+ to completely block this
325
- # vulnerability. Otherwise, parser_max_deprecated_uidplus_data_size
326
- # mitigates this vulnerability.
327
- #
328
- # AppendUIDData and CopyUIDData are _mostly_ backward-compatible with
329
- # UIDPlusData. Most applications should be able to upgrade with little
330
- # or no changes.
331
- #
332
- # <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
333
- #
334
- # <em>(Config option added in +v0.4.19+ and +v0.5.6+.)</em>
335
- #
336
- # <em>UIDPlusData will be removed in +v0.6+ and this config setting will
337
- # be ignored.</em>
338
- #
339
- # ==== Valid options
340
- #
341
- # [+true+ <em>(original default)</em>]
342
- # ResponseParser only uses UIDPlusData.
343
- #
344
- # [+:up_to_max_size+ <em>(default since +v0.5.6+)</em>]
345
- # ResponseParser uses UIDPlusData when the +uid-set+ size is below
346
- # parser_max_deprecated_uidplus_data_size. Above that size,
347
- # ResponseParser uses AppendUIDData or CopyUIDData.
348
- #
349
- # [+false+ <em>(planned default for +v0.6+)</em>]
350
- # ResponseParser _only_ uses AppendUIDData and CopyUIDData.
351
- attr_accessor :parser_use_deprecated_uidplus_data, type: Enum[
352
- true, :up_to_max_size, false
353
- ]
354
-
355
- # The maximum +uid-set+ size that ResponseParser will parse into
356
- # deprecated UIDPlusData. This limit only applies when
357
- # parser_use_deprecated_uidplus_data is not +false+.
358
- #
359
- # <em>(Parser support for +UIDPLUS+ added in +v0.3.2+.)</em>
360
- #
361
- # <em>Support for limiting UIDPlusData to a maximum size was added in
362
- # +v0.3.8+, +v0.4.19+, and +v0.5.6+.</em>
363
- #
364
- # <em>UIDPlusData will be removed in +v0.6+.</em>
365
- #
366
- # ==== Versioned Defaults
367
- #
368
- # Because this limit guards against a remote server causing catastrophic
369
- # memory exhaustion, the versioned default (used by #load_defaults) also
370
- # applies to versions without the feature.
371
- #
372
- # * +0.3+ and prior: <tt>10,000</tt>
373
- # * +0.4+: <tt>1,000</tt>
374
- # * +0.5+: <tt>100</tt>
375
- # * +0.6+: <tt>0</tt>
376
- #
377
- attr_accessor :parser_max_deprecated_uidplus_data_size, type: Integer
378
-
379
288
  # Creates a new config object and initialize its attribute with +attrs+.
380
289
  #
381
290
  # If +parent+ is not given, the global config is used by default.
@@ -454,71 +363,38 @@ module Net
454
363
  open_timeout: 30,
455
364
  idle_response_timeout: 5,
456
365
  sasl_ir: true,
457
- max_response_size: nil,
458
- responses_without_block: :silence_deprecation_warning,
459
- parser_use_deprecated_uidplus_data: true,
460
- parser_max_deprecated_uidplus_data_size: 1000,
366
+ enforce_logindisabled: true,
367
+ responses_without_block: :warn,
461
368
  ).freeze
462
369
 
463
370
  @global = default.new
464
371
 
465
372
  version_defaults[:default] = Config[default.send(:defaults_hash)]
373
+ version_defaults[:current] = Config[:default]
466
374
 
467
- version_defaults[0r] = Config[:default].dup.update(
375
+ version_defaults[0] = Config[:current].dup.update(
468
376
  sasl_ir: false,
469
- max_response_size: nil,
470
- parser_use_deprecated_uidplus_data: true,
471
- parser_max_deprecated_uidplus_data_size: 10_000,
377
+ responses_without_block: :silence_deprecation_warning,
378
+ enforce_logindisabled: false,
472
379
  ).freeze
473
- version_defaults[0.0r] = Config[0r]
474
- version_defaults[0.1r] = Config[0r]
475
- version_defaults[0.2r] = Config[0r]
476
- version_defaults[0.3r] = Config[0r]
380
+ version_defaults[0.0] = Config[0]
381
+ version_defaults[0.1] = Config[0]
382
+ version_defaults[0.2] = Config[0]
383
+ version_defaults[0.3] = Config[0]
477
384
 
478
- version_defaults[0.4r] = Config[0.3r].dup.update(
385
+ version_defaults[0.4] = Config[0.3].dup.update(
479
386
  sasl_ir: true,
480
- parser_max_deprecated_uidplus_data_size: 1000,
481
387
  ).freeze
482
388
 
483
- version_defaults[0.5r] = Config[0.4r].dup.update(
484
- max_response_size: 512 << 20, # 512 MiB
485
- responses_without_block: :warn,
486
- parser_use_deprecated_uidplus_data: :up_to_max_size,
487
- parser_max_deprecated_uidplus_data_size: 100,
488
- ).freeze
389
+ version_defaults[0.5] = Config[:current]
489
390
 
490
- version_defaults[0.6r] = Config[0.5r].dup.update(
391
+ version_defaults[0.6] = Config[0.5].dup.update(
491
392
  responses_without_block: :frozen_dup,
492
- parser_use_deprecated_uidplus_data: false,
493
- parser_max_deprecated_uidplus_data_size: 0,
494
- ).freeze
495
-
496
- version_defaults[0.7r] = Config[0.6r].dup.update(
497
393
  ).freeze
498
-
499
- # Safe conversions one way only:
500
- # 0.6r.to_f == 0.6 # => true
501
- # 0.6 .to_r == 0.6r # => false
502
- version_defaults.to_a.each do |k, v|
503
- next unless k.is_a? Rational
504
- version_defaults[k.to_f] = v
505
- end
506
-
507
- current = VERSION.to_r
508
- version_defaults[:original] = Config[0]
509
- version_defaults[:current] = Config[current]
510
- version_defaults[:next] = Config[current + 0.1r]
511
-
512
- version_defaults[:future] = Config[0.7r]
394
+ version_defaults[:next] = Config[0.6]
395
+ version_defaults[:future] = Config[:next]
513
396
 
514
397
  version_defaults.freeze
515
-
516
- if ($VERBOSE || $DEBUG) && self[:current].to_h != self[:default].to_h
517
- warn "Misconfigured Net::IMAP::Config[:current] => %p,\n" \
518
- " not equal to Net::IMAP::Config[:default] => %p" % [
519
- self[:current].to_h, self[:default].to_h
520
- ]
521
- end
522
398
  end
523
399
  end
524
400
  end
@@ -186,7 +186,7 @@ module Net
186
186
 
187
187
  # Ensure argument is 'number' or raise DataFormatError
188
188
  def ensure_number(num)
189
- return if valid_number?(num)
189
+ return num if valid_number?(num)
190
190
 
191
191
  msg = "number must be unsigned 32-bit integer: #{num}"
192
192
  raise DataFormatError, msg
@@ -194,7 +194,7 @@ module Net
194
194
 
195
195
  # Ensure argument is 'nz_number' or raise DataFormatError
196
196
  def ensure_nz_number(num)
197
- return if valid_nz_number?(num)
197
+ return num if valid_nz_number?(num)
198
198
 
199
199
  msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}"
200
200
  raise DataFormatError, msg
@@ -202,7 +202,7 @@ module Net
202
202
 
203
203
  # Ensure argument is 'mod_sequence_value' or raise DataFormatError
204
204
  def ensure_mod_sequence_value(num)
205
- return if valid_mod_sequence_value?(num)
205
+ return num if valid_mod_sequence_value?(num)
206
206
 
207
207
  msg = "mod_sequence_value must be unsigned 64-bit integer: #{num}"
208
208
  raise DataFormatError, msg
@@ -83,10 +83,12 @@ module Net
83
83
  elsif deprecated.empty?
84
84
  super host, port: port_or_options
85
85
  elsif deprecated.shift
86
- warn "DEPRECATED: Call Net::IMAP.new with keyword options", uplevel: 1
86
+ warn("DEPRECATED: Call Net::IMAP.new with keyword options",
87
+ uplevel: 1, category: :deprecated)
87
88
  super host, port: port_or_options, ssl: create_ssl_params(*deprecated)
88
89
  else
89
- warn "DEPRECATED: Call Net::IMAP.new with keyword options", uplevel: 1
90
+ warn("DEPRECATED: Call Net::IMAP.new with keyword options",
91
+ uplevel: 1, category: :deprecated)
90
92
  super host, port: port_or_options, ssl: false
91
93
  end
92
94
  end
@@ -113,7 +115,8 @@ module Net
113
115
  elsif deprecated.first.respond_to?(:to_hash)
114
116
  super(**Hash.try_convert(deprecated.first))
115
117
  else
116
- warn "DEPRECATED: Call Net::IMAP#starttls with keyword options", uplevel: 1
118
+ warn("DEPRECATED: Call Net::IMAP#starttls with keyword options",
119
+ uplevel: 1, category: :deprecated)
117
120
  super(**create_ssl_params(*deprecated))
118
121
  end
119
122
  end
@@ -7,41 +7,14 @@ module Net
7
7
  class Error < StandardError
8
8
  end
9
9
 
10
- # Error raised when data is in the incorrect format.
11
- class DataFormatError < Error
12
- end
13
-
14
- # Error raised when the socket cannot be read, due to a Config limit.
15
- class ResponseReadError < Error
16
- end
17
-
18
- # Error raised when a response is larger than IMAP#max_response_size.
19
- class ResponseTooLargeError < ResponseReadError
20
- attr_reader :bytes_read, :literal_size
21
- attr_reader :max_response_size
22
-
23
- def initialize(msg = nil, *args,
24
- bytes_read: nil,
25
- literal_size: nil,
26
- max_response_size: nil,
27
- **kwargs)
28
- @bytes_read = bytes_read
29
- @literal_size = literal_size
30
- @max_response_size = max_response_size
31
- msg ||= [
32
- "Response size", response_size_msg, "exceeds max_response_size",
33
- max_response_size && "(#{max_response_size}B)",
34
- ].compact.join(" ")
35
- super(msg, *args, **kwargs)
10
+ class LoginDisabledError < Error
11
+ def initialize(msg = "Remote server has disabled the LOGIN command", ...)
12
+ super
36
13
  end
14
+ end
37
15
 
38
- private
39
-
40
- def response_size_msg
41
- if bytes_read && literal_size
42
- "(#{bytes_read}B read + #{literal_size}B literal)"
43
- end
44
- end
16
+ # Error raised when data is in the incorrect format.
17
+ class DataFormatError < Error
45
18
  end
46
19
 
47
20
  # Error raised when a response from the server is non-parsable.
@@ -5,9 +5,6 @@ module Net
5
5
  autoload :FetchData, "#{__dir__}/fetch_data"
6
6
  autoload :SearchResult, "#{__dir__}/search_result"
7
7
  autoload :SequenceSet, "#{__dir__}/sequence_set"
8
- autoload :UIDPlusData, "#{__dir__}/uidplus_data"
9
- autoload :AppendUIDData, "#{__dir__}/uidplus_data"
10
- autoload :CopyUIDData, "#{__dir__}/uidplus_data"
11
8
 
12
9
  # Net::IMAP::ContinuationRequest represents command continuation requests.
13
10
  #
@@ -295,14 +292,6 @@ module Net
295
292
  # because the server doesn't allow deletion of mailboxes with children.
296
293
  # #data is +nil+.
297
294
  #
298
- # ==== <tt>QUOTA=RES-*</tt> response codes
299
- # See {[RFC9208]}[https://www.rfc-editor.org/rfc/rfc9208.html#section-4.3].
300
- # * +OVERQUOTA+ (also in RFC5530[https://www.rfc-editor.org/rfc/rfc5530]),
301
- # with a tagged +NO+ response to an +APPEND+/+COPY+/+MOVE+ command when
302
- # the command would put the target mailbox over any quota, and with an
303
- # untagged +NO+ when a mailbox exceeds a soft quota (which may be caused
304
- # be external events). #data is +nil+.
305
- #
306
295
  # ==== +CONDSTORE+ extension
307
296
  # See {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
308
297
  # * +NOMODSEQ+, when selecting a mailbox that does not support
@@ -335,6 +324,60 @@ module Net
335
324
  # code data can take.
336
325
  end
337
326
 
327
+ # Net::IMAP::UIDPlusData represents the ResponseCode#data that accompanies
328
+ # the +APPENDUID+ and +COPYUID+ response codes.
329
+ #
330
+ # See [[UIDPLUS[https://www.rfc-editor.org/rfc/rfc4315.html]].
331
+ #
332
+ # ==== Capability requirement
333
+ #
334
+ # The +UIDPLUS+ capability[rdoc-ref:Net::IMAP#capability] must be supported.
335
+ # A server that supports +UIDPLUS+ should send a UIDPlusData object inside
336
+ # every TaggedResponse returned by the append[rdoc-ref:Net::IMAP#append],
337
+ # copy[rdoc-ref:Net::IMAP#copy], move[rdoc-ref:Net::IMAP#move], {uid
338
+ # copy}[rdoc-ref:Net::IMAP#uid_copy], and {uid
339
+ # move}[rdoc-ref:Net::IMAP#uid_move] commands---unless the destination
340
+ # mailbox reports +UIDNOTSTICKY+.
341
+ #
342
+ #--
343
+ # TODO: support MULTIAPPEND
344
+ #++
345
+ #
346
+ class UIDPlusData < Struct.new(:uidvalidity, :source_uids, :assigned_uids)
347
+ ##
348
+ # method: uidvalidity
349
+ # :call-seq: uidvalidity -> nonzero uint32
350
+ #
351
+ # The UIDVALIDITY of the destination mailbox.
352
+
353
+ ##
354
+ # method: source_uids
355
+ # :call-seq: source_uids -> nil or an array of nonzero uint32
356
+ #
357
+ # The UIDs of the copied or moved messages.
358
+ #
359
+ # Note:: Returns +nil+ for Net::IMAP#append.
360
+
361
+ ##
362
+ # method: assigned_uids
363
+ # :call-seq: assigned_uids -> an array of nonzero uint32
364
+ #
365
+ # The newly assigned UIDs of the copied, moved, or appended messages.
366
+ #
367
+ # Note:: This always returns an array, even when it contains only one UID.
368
+
369
+ ##
370
+ # :call-seq: uid_mapping -> nil or a hash
371
+ #
372
+ # Returns a hash mapping each source UID to the newly assigned destination
373
+ # UID.
374
+ #
375
+ # Note:: Returns +nil+ for Net::IMAP#append.
376
+ def uid_mapping
377
+ source_uids&.zip(assigned_uids)&.to_h
378
+ end
379
+ end
380
+
338
381
  # Net::IMAP::MailboxList represents contents of the LIST response,
339
382
  # representing a single mailbox path.
340
383
  #
@@ -377,24 +420,12 @@ module Net
377
420
  # Net::IMAP#getquotaroot returns an array containing both MailboxQuotaRoot
378
421
  # and MailboxQuota objects.
379
422
  #
380
- # ==== Required capability
381
- #
382
- # Requires +QUOTA+ [RFC2087[https://www.rfc-editor.org/rfc/rfc2087]]
383
- # or <tt>QUOTA=RES-STORAGE</tt>
384
- # [RFC9208[https://www.rfc-editor.org/rfc/rfc9208]] capability.
385
423
  class MailboxQuota < Struct.new(:mailbox, :usage, :quota)
386
424
  ##
387
425
  # method: mailbox
388
426
  # :call-seq: mailbox -> string
389
427
  #
390
- # The quota root with the associated quota.
391
- #
392
- # NOTE: this was mistakenly named "mailbox". But the quota root's name may
393
- # differ from the mailbox. A single quota root may cover multiple
394
- # mailboxes, and a single mailbox may be governed by multiple quota roots.
395
-
396
- # The quota root with the associated quota.
397
- alias quota_root mailbox
428
+ # The mailbox with the associated quota.
398
429
 
399
430
  ##
400
431
  # method: usage
@@ -406,7 +437,7 @@ module Net
406
437
  # method: quota
407
438
  # :call-seq: quota -> Integer
408
439
  #
409
- # Storage limit imposed on the mailbox.
440
+ # Quota limit imposed on the mailbox.
410
441
  #
411
442
  end
412
443
 
@@ -908,7 +939,8 @@ module Net
908
939
  # for something else?
909
940
  #++
910
941
  def media_subtype
911
- warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
942
+ warn("media_subtype is obsolete, use subtype instead.\n",
943
+ uplevel: 1, category: :deprecated)
912
944
  return subtype
913
945
  end
914
946
  end
@@ -953,7 +985,8 @@ module Net
953
985
  # generate a warning message to +stderr+, then return
954
986
  # the value of +subtype+.
955
987
  def media_subtype
956
- warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
988
+ warn("media_subtype is obsolete, use subtype instead.\n",
989
+ uplevel: 1, category: :deprecated)
957
990
  return subtype
958
991
  end
959
992
  end
@@ -1009,77 +1042,6 @@ module Net
1009
1042
  end
1010
1043
  end
1011
1044
 
1012
- # BodyTypeAttachment is not used and will be removed in an upcoming release.
1013
- #
1014
- # === Bug Analysis
1015
- #
1016
- # \IMAP body structures are parenthesized lists and assign their fields
1017
- # positionally, so missing fields change the interpretation of all
1018
- # following fields. Additionally, different body types have a different
1019
- # number of required fields, followed by optional "extension" fields.
1020
- #
1021
- # BodyTypeAttachment was previously returned when a "message/rfc822" part,
1022
- # which should be sent as <tt>body-type-msg</tt> with ten required fields,
1023
- # was actually sent as a <tt>body-type-basic</tt> with _seven_ required
1024
- # fields.
1025
- #
1026
- # basic => type, subtype, param, id, desc, enc, octets, md5=nil, dsp=nil, lang=nil, loc=nil, *ext
1027
- # msg => type, subtype, param, id, desc, enc, octets, envelope, body, lines, md5=nil, ...
1028
- #
1029
- # Normally, +envelope+ and +md5+ are incompatible, but Net::IMAP leniently
1030
- # allowed buggy servers to send +NIL+ for +envelope+. As a result, when a
1031
- # server sent a <tt>message/rfc822</tt> part with +NIL+ for +md5+ and a
1032
- # non-<tt>NIL</tt> +dsp+, Net::IMAP misinterpreted the
1033
- # <tt>Content-Disposition</tt> as if it were a strange body type. In all
1034
- # reported cases, the <tt>Content-Disposition</tt> was "attachment", so
1035
- # BodyTypeAttachment was created as the workaround.
1036
- #
1037
- # === Current behavior
1038
- #
1039
- # When interpreted strictly, +envelope+ and +md5+ are incompatible. So the
1040
- # current parsing algorithm peeks ahead after it has received the seventh
1041
- # body field. If the next token is not the start of an +envelope+, we assume
1042
- # the server has incorrectly sent us a <tt>body-type-basic</tt> and return
1043
- # BodyTypeBasic. As a result, what was previously BodyTypeMessage#body =>
1044
- # BodyTypeAttachment is now BodyTypeBasic#disposition => ContentDisposition.
1045
- #
1046
- class BodyTypeAttachment < Struct.new(:dsp_type, :_unused_, :param)
1047
- # *invalid for BodyTypeAttachment*
1048
- def media_type
1049
- warn(<<~WARN, uplevel: 1)
1050
- BodyTypeAttachment#media_type is obsolete. Use dsp_type instead.
1051
- WARN
1052
- dsp_type
1053
- end
1054
-
1055
- # *invalid for BodyTypeAttachment*
1056
- def subtype
1057
- warn("BodyTypeAttachment#subtype is obsolete.\n", uplevel: 1)
1058
- nil
1059
- end
1060
-
1061
- ##
1062
- # method: dsp_type
1063
- # :call-seq: dsp_type -> string
1064
- #
1065
- # Returns the content disposition type, as defined by
1066
- # [DISPOSITION[https://tools.ietf.org/html/rfc2183]].
1067
-
1068
- ##
1069
- # method: param
1070
- # :call-seq: param -> hash
1071
- #
1072
- # Returns a hash representing parameters of the Content-Disposition
1073
- # field, as defined by [DISPOSITION[https://tools.ietf.org/html/rfc2183]].
1074
-
1075
- ##
1076
- def multipart?
1077
- return false
1078
- end
1079
- end
1080
-
1081
- deprecate_constant :BodyTypeAttachment
1082
-
1083
1045
  # Net::IMAP::BodyTypeMultipart represents body structures of messages and
1084
1046
  # message parts, when <tt>Content-Type</tt> is <tt>multipart/*</tt>.
1085
1047
  class BodyTypeMultipart < Struct.new(:media_type, :subtype,
@@ -1151,29 +1113,11 @@ module Net
1151
1113
  # generate a warning message to +stderr+, then return
1152
1114
  # the value of +subtype+.
1153
1115
  def media_subtype
1154
- warn("media_subtype is obsolete, use subtype instead.\n", uplevel: 1)
1116
+ warn("media_subtype is obsolete, use subtype instead.\n",
1117
+ uplevel: 1, category: :deprecated)
1155
1118
  return subtype
1156
1119
  end
1157
1120
  end
1158
1121
 
1159
- # === Obsolete
1160
- # BodyTypeExtension is not used and will be removed in an upcoming release.
1161
- #
1162
- # >>>
1163
- # BodyTypeExtension was (incorrectly) used for <tt>message/*</tt> parts
1164
- # (besides <tt>message/rfc822</tt>, which correctly uses BodyTypeMessage).
1165
- #
1166
- # Net::IMAP now (correctly) parses all message types (other than
1167
- # <tt>message/rfc822</tt> or <tt>message/global</tt>) as BodyTypeBasic.
1168
- class BodyTypeExtension < Struct.new(:media_type, :subtype,
1169
- :params, :content_id,
1170
- :description, :encoding, :size)
1171
- def multipart?
1172
- return false
1173
- end
1174
- end
1175
-
1176
- deprecate_constant :BodyTypeExtension
1177
-
1178
1122
  end
1179
1123
  end