net-imap 0.4.17 → 0.5.6

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -1
  3. data/README.md +10 -4
  4. data/docs/styles.css +75 -14
  5. data/lib/net/imap/authenticators.rb +2 -2
  6. data/lib/net/imap/command_data.rb +59 -46
  7. data/lib/net/imap/config.rb +109 -13
  8. data/lib/net/imap/data_encoding.rb +3 -3
  9. data/lib/net/imap/data_lite.rb +226 -0
  10. data/lib/net/imap/deprecated_client_options.rb +6 -3
  11. data/lib/net/imap/errors.rb +6 -0
  12. data/lib/net/imap/esearch_result.rb +180 -0
  13. data/lib/net/imap/fetch_data.rb +126 -47
  14. data/lib/net/imap/response_data.rb +124 -237
  15. data/lib/net/imap/response_parser/parser_utils.rb +5 -0
  16. data/lib/net/imap/response_parser.rb +183 -34
  17. data/lib/net/imap/sasl/anonymous_authenticator.rb +3 -3
  18. data/lib/net/imap/sasl/authentication_exchange.rb +52 -20
  19. data/lib/net/imap/sasl/authenticators.rb +8 -4
  20. data/lib/net/imap/sasl/client_adapter.rb +77 -26
  21. data/lib/net/imap/sasl/cram_md5_authenticator.rb +4 -4
  22. data/lib/net/imap/sasl/digest_md5_authenticator.rb +218 -56
  23. data/lib/net/imap/sasl/external_authenticator.rb +2 -2
  24. data/lib/net/imap/sasl/gs2_header.rb +7 -7
  25. data/lib/net/imap/sasl/login_authenticator.rb +4 -3
  26. data/lib/net/imap/sasl/oauthbearer_authenticator.rb +6 -6
  27. data/lib/net/imap/sasl/plain_authenticator.rb +7 -7
  28. data/lib/net/imap/sasl/protocol_adapters.rb +60 -4
  29. data/lib/net/imap/sasl/scram_authenticator.rb +8 -8
  30. data/lib/net/imap/sasl.rb +7 -4
  31. data/lib/net/imap/sasl_adapter.rb +0 -1
  32. data/lib/net/imap/search_result.rb +2 -2
  33. data/lib/net/imap/sequence_set.rb +211 -81
  34. data/lib/net/imap/stringprep/nameprep.rb +1 -1
  35. data/lib/net/imap/stringprep/trace.rb +4 -4
  36. data/lib/net/imap/uidplus_data.rb +244 -0
  37. data/lib/net/imap/vanished_data.rb +56 -0
  38. data/lib/net/imap.rb +831 -279
  39. data/net-imap.gemspec +1 -1
  40. data/rakelib/rfcs.rake +2 -0
  41. data/rakelib/string_prep_tables_generator.rb +2 -0
  42. metadata +8 -7
@@ -3,9 +3,9 @@
3
3
  module Net
4
4
  class IMAP < Protocol
5
5
 
6
- # Net::IMAP::FetchData represents the contents of a FETCH response.
7
- # Net::IMAP#fetch and Net::IMAP#uid_fetch both return an array of
8
- # FetchData objects.
6
+ # Net::IMAP::FetchStruct is the superclass for FetchData and UIDFetchData.
7
+ # Net::IMAP#fetch, Net::IMAP#uid_fetch, Net::IMAP#store, and
8
+ # Net::IMAP#uid_store all return arrays of FetchStruct objects.
9
9
  #
10
10
  # === Fetch attributes
11
11
  #
@@ -63,8 +63,7 @@ module Net
63
63
  # * <b><tt>"X-GM-MSGID"</tt></b> --- unique message ID. Access via #attr.
64
64
  # * <b><tt>"X-GM-THRID"</tt></b> --- Thread ID. Access via #attr.
65
65
  #
66
- # [Note:]
67
- # >>>
66
+ # [NOTE:]
68
67
  # Additional static fields are defined in other \IMAP extensions, but
69
68
  # Net::IMAP can't parse them yet.
70
69
  #
@@ -87,34 +86,23 @@ module Net
87
86
  # extension]}[https://developers.google.com/gmail/imap/imap-extensions]
88
87
  # * <b><tt>"X-GM-LABELS"</tt></b> --- Gmail labels. Access via #attr.
89
88
  #
90
- # [Note:]
91
- # >>>
89
+ # [NOTE:]
92
90
  # Additional dynamic fields are defined in other \IMAP extensions, but
93
91
  # Net::IMAP can't parse them yet.
94
92
  #
95
93
  # === Implicitly setting <tt>\Seen</tt> and using +PEEK+
96
94
  #
97
- # Unless the mailbox is has been opened as read-only, fetching
95
+ # Unless the mailbox has been opened as read-only, fetching
98
96
  # <tt>BODY[#{section}]</tt> or <tt>BINARY[#{section}]</tt>
99
97
  # will implicitly set the <tt>\Seen</tt> flag. To avoid this, fetch using
100
98
  # <tt>BODY.PEEK[#{section}]</tt> or <tt>BINARY.PEEK[#{section}]</tt>
101
99
  # instead.
102
100
  #
103
- # Note that the data will always be _returned_ without <tt>".PEEK"</tt>, in
104
- # <tt>BODY[#{specifier}]</tt> or <tt>BINARY[#{section}]</tt>.
101
+ # [NOTE:]
102
+ # The data will always be _returned_ without the <tt>".PEEK"</tt> suffix,
103
+ # as <tt>BODY[#{specifier}]</tt> or <tt>BINARY[#{section}]</tt>.
105
104
  #
106
- class FetchData < Struct.new(:seqno, :attr)
107
- ##
108
- # method: seqno
109
- # :call-seq: seqno -> Integer
110
- #
111
- # The message sequence number.
112
- #
113
- # [Note]
114
- # This is never the unique identifier (UID), not even for the
115
- # Net::IMAP#uid_fetch result. The UID is available from #uid, if it was
116
- # returned.
117
-
105
+ class FetchStruct < Struct
118
106
  ##
119
107
  # method: attr
120
108
  # :call-seq: attr -> hash
@@ -123,9 +111,6 @@ module Net
123
111
  # corresponding data item. Standard data items have corresponding
124
112
  # accessor methods. The definitions of each attribute type is documented
125
113
  # on its accessor.
126
- #
127
- # >>>
128
- # *Note:* #seqno is not a message attribute.
129
114
 
130
115
  # :call-seq: attr_upcase -> hash
131
116
  #
@@ -142,7 +127,7 @@ module Net
142
127
  #
143
128
  # This is the same as getting the value for <tt>"BODY"</tt> from #attr.
144
129
  #
145
- # [Note]
130
+ # [NOTE:]
146
131
  # Use #message, #part, #header, #header_fields, #header_fields_not,
147
132
  # #text, or #mime to retrieve <tt>BODY[#{section_spec}]</tt> attributes.
148
133
  def body; attr["BODY"] end
@@ -235,7 +220,7 @@ module Net
235
220
  fields && except and
236
221
  raise ArgumentError, "conflicting 'fields' and 'except' arguments"
237
222
  if fields
238
- text = "HEADER.FIELDS (%s)" % [fields.join(" ").upcase]
223
+ text = "HEADER.FIELDS (%s)" % [fields.join(" ").upcase]
239
224
  attr_upcase[body_section_attr(part_nums, text, offset: offset)]
240
225
  elsif except
241
226
  text = "HEADER.FIELDS.NOT (%s)" % [except.join(" ").upcase]
@@ -308,6 +293,7 @@ module Net
308
293
  # This is the same as getting the value for <tt>"BODYSTRUCTURE"</tt> from
309
294
  # #attr.
310
295
  def bodystructure; attr["BODYSTRUCTURE"] end
296
+
311
297
  alias body_structure bodystructure
312
298
 
313
299
  # :call-seq: envelope -> Envelope or nil
@@ -320,7 +306,7 @@ module Net
320
306
  # #attr.
321
307
  def envelope; attr["ENVELOPE"] end
322
308
 
323
- # :call-seq: flags -> array of Symbols and Strings
309
+ # :call-seq: flags -> array of Symbols and Strings, or nil
324
310
  #
325
311
  # A array of flags that are set for this message. System flags are
326
312
  # symbols that have been capitalized by String#capitalize. Keyword flags
@@ -328,7 +314,7 @@ module Net
328
314
  #
329
315
  # This is the same as getting the value for <tt>"FLAGS"</tt> from #attr.
330
316
  #
331
- # [Note]
317
+ # [NOTE:]
332
318
  # The +FLAGS+ field is dynamic, and can change for a uniquely identified
333
319
  # message.
334
320
  def flags; attr["FLAGS"] end
@@ -336,40 +322,41 @@ module Net
336
322
  # :call-seq: internaldate -> Time or nil
337
323
  #
338
324
  # The internal date and time of the message on the server. This is not
339
- # the date and time in the [RFC5322[https://tools.ietf.org/html/rfc5322]]
325
+ # the date and time in the [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]
340
326
  # header, but rather a date and time which reflects when the message was
341
327
  # received.
342
328
  #
343
329
  # This is similar to getting the value for <tt>"INTERNALDATE"</tt> from
344
330
  # #attr.
345
331
  #
346
- # [Note]
332
+ # [NOTE:]
347
333
  # <tt>attr["INTERNALDATE"]</tt> returns a string, and this method
348
334
  # returns a Time object.
349
335
  def internaldate
350
336
  attr["INTERNALDATE"]&.then { IMAP.decode_time _1 }
351
337
  end
338
+
352
339
  alias internal_date internaldate
353
340
 
354
- # :call-seq: rfc822 -> String
341
+ # :call-seq: rfc822 -> String or nil
355
342
  #
356
343
  # Semantically equivalent to #message with no arguments.
357
344
  #
358
345
  # This is the same as getting the value for <tt>"RFC822"</tt> from #attr.
359
346
  #
360
- # [Note]
347
+ # [NOTE:]
361
348
  # +IMAP4rev2+ deprecates <tt>RFC822</tt>.
362
349
  def rfc822; attr["RFC822"] end
363
350
 
364
- # :call-seq: rfc822_size -> Integer
351
+ # :call-seq: rfc822_size -> Integer or nil
365
352
  #
366
- # A number expressing the [RFC5322[https://tools.ietf.org/html/rfc5322]]
353
+ # A number expressing the [RFC5322[https://www.rfc-editor.org/rfc/rfc5322]]
367
354
  # size of the message.
368
355
  #
369
356
  # This is the same as getting the value for <tt>"RFC822.SIZE"</tt> from
370
357
  # #attr.
371
358
  #
372
- # [Note]
359
+ # [NOTE:]
373
360
  # \IMAP was originally developed for the older
374
361
  # RFC822[https://www.rfc-editor.org/rfc/rfc822.html] standard, and as a
375
362
  # consequence several fetch items in \IMAP incorporate "RFC822" in their
@@ -379,34 +366,45 @@ module Net
379
366
  # interpreted as a reference to the updated
380
367
  # RFC5322[https://www.rfc-editor.org/rfc/rfc5322.html] standard.
381
368
  def rfc822_size; attr["RFC822.SIZE"] end
382
- alias size rfc822_size
383
369
 
384
- # :call-seq: rfc822_header -> String
370
+ # NOTE: a bug in rdoc 6.7 prevents us from adding a call-seq to
371
+ # rfc822_size _and_ aliasing size => rfc822_size. Is it because this
372
+ # class inherits from Struct?
373
+
374
+ # Alias for: rfc822_size
375
+ def size; rfc822_size end
376
+
377
+
378
+ # :call-seq: rfc822_header -> String or nil
385
379
  #
386
380
  # Semantically equivalent to #header, with no arguments.
387
381
  #
388
382
  # This is the same as getting the value for <tt>"RFC822.HEADER"</tt> from #attr.
389
383
  #
390
- # [Note]
384
+ # [NOTE:]
391
385
  # +IMAP4rev2+ deprecates <tt>RFC822.HEADER</tt>.
392
386
  def rfc822_header; attr["RFC822.HEADER"] end
393
387
 
394
- # :call-seq: rfc822_text -> String
388
+ # :call-seq: rfc822_text -> String or nil
395
389
  #
396
390
  # Semantically equivalent to #text, with no arguments.
397
391
  #
398
392
  # This is the same as getting the value for <tt>"RFC822.TEXT"</tt> from
399
393
  # #attr.
400
394
  #
401
- # [Note]
395
+ # [NOTE:]
402
396
  # +IMAP4rev2+ deprecates <tt>RFC822.TEXT</tt>.
403
397
  def rfc822_text; attr["RFC822.TEXT"] end
404
398
 
405
- # :call-seq: uid -> Integer
399
+ # :call-seq: uid -> Integer or nil
406
400
  #
407
401
  # A number expressing the unique identifier of the message.
408
402
  #
409
403
  # This is the same as getting the value for <tt>"UID"</tt> from #attr.
404
+ #
405
+ # [NOTE:]
406
+ # For UIDFetchData, this returns the uniqueid at the beginning of the
407
+ # +UIDFETCH+ response, _not_ the value from #attr.
410
408
  def uid; attr["UID"] end
411
409
 
412
410
  # :call-seq:
@@ -452,7 +450,7 @@ module Net
452
450
  attr[section_attr("BINARY.SIZE", part_nums)]
453
451
  end
454
452
 
455
- # :call-seq: modseq -> Integer
453
+ # :call-seq: modseq -> Integer or nil
456
454
  #
457
455
  # The modification sequence number associated with this IMAP message.
458
456
  #
@@ -461,7 +459,7 @@ module Net
461
459
  # The server must support the +CONDSTORE+ extension
462
460
  # {[RFC7162]}[https://www.rfc-editor.org/rfc/rfc7162.html].
463
461
  #
464
- # [Note]
462
+ # [NOTE:]
465
463
  # The +MODSEQ+ field is dynamic, and can change for a uniquely
466
464
  # identified message.
467
465
  def modseq; attr["MODSEQ"] end
@@ -508,11 +506,92 @@ module Net
508
506
  spec = Array(part).flatten.map { Integer(_1) }
509
507
  spec << text if text
510
508
  spec = spec.join(".")
511
- if offset then "%s[%s]<%d>" % [attr, spec, Integer(offset)]
512
- else "%s[%s]" % [attr, spec]
513
- end
509
+ if offset then "%s[%s]<%d>" % [attr, spec, Integer(offset)] else "%s[%s]" % [attr, spec] end
514
510
  end
511
+ end
515
512
 
513
+ # Net::IMAP::FetchData represents the contents of a +FETCH+ response.
514
+ # Net::IMAP#fetch, Net::IMAP#uid_fetch, Net::IMAP#store, and
515
+ # Net::IMAP#uid_store all return arrays of FetchData objects, except when
516
+ # the +UIDONLY+ extension is enabled.
517
+ #
518
+ # See FetchStruct documentation for a list of standard message attributes.
519
+ class FetchData < FetchStruct.new(:seqno, :attr)
520
+ ##
521
+ # method: seqno
522
+ # :call-seq: seqno -> Integer
523
+ #
524
+ # The message sequence number.
525
+ #
526
+ # [NOTE:]
527
+ # This is not the same as the unique identifier (UID), not even for the
528
+ # Net::IMAP#uid_fetch result. The UID is available from #uid, if it was
529
+ # returned.
530
+ #
531
+ # [NOTE:]
532
+ # UIDFetchData will raise a NoMethodError.
533
+
534
+ ##
535
+ # method: attr
536
+ # :call-seq: attr -> hash
537
+ #
538
+ # Each key specifies a message attribute, and the value is the
539
+ # corresponding data item. Standard data items have corresponding
540
+ # accessor methods. The definitions of each attribute type is documented
541
+ # on its accessor.
542
+ #
543
+ # See FetchStruct documentation for message attribute accessors.
544
+ #
545
+ # [NOTE:]
546
+ # #seqno is not a message attribute.
547
+ end
548
+
549
+ # Net::IMAP::UIDFetchData represents the contents of a +UIDFETCH+ response,
550
+ # When the +UIDONLY+ extension has been enabled, Net::IMAP#uid_fetch and
551
+ # Net::IMAP#uid_store will both return an array of UIDFetchData objects.
552
+ #
553
+ # UIDFetchData contains the same message attributes as FetchData. However,
554
+ # +UIDFETCH+ responses return the UID at the beginning of the response,
555
+ # replacing FetchData#seqno. UIDFetchData never contains a message sequence
556
+ # number.
557
+ #
558
+ # See FetchStruct documentation for a list of standard message attributes.
559
+ class UIDFetchData < FetchStruct.new(:uid, :attr)
560
+ ##
561
+ # method: uid
562
+ # call-seq: uid -> Integer
563
+ #
564
+ # A number expressing the unique identifier of the message.
565
+ #
566
+ # [NOTE:]
567
+ # Although #attr may _also_ have a redundant +UID+ attribute, #uid
568
+ # returns the uniqueid at the beginning of the +UIDFETCH+ response.
569
+
570
+ ##
571
+ # method: attr
572
+ # call-seq: attr -> hash
573
+ #
574
+ # Each key specifies a message attribute, and the value is the
575
+ # corresponding data item. Standard data items have corresponding
576
+ # accessor methods. The definitions of each attribute type is documented
577
+ # on its accessor.
578
+ #
579
+ # See FetchStruct documentation for message attribute accessors.
580
+ #
581
+ # [NOTE:]
582
+ # #uid is not a message attribute. Although the server may return a
583
+ # +UID+ message attribute, it is not required to. #uid is taken from
584
+ # its corresponding +UIDFETCH+ field.
585
+
586
+ # UIDFetchData will print a warning if <tt>#attr["UID"]</tt> is present
587
+ # but not identical to #uid.
588
+ def initialize(...)
589
+ super
590
+ attr and
591
+ attr_uid = attr["UID"] and
592
+ attr_uid != uid and
593
+ warn "#{self.class} UIDs do not match (#{attr_uid} != #{uid})"
594
+ end
516
595
  end
517
596
  end
518
597
  end