imap.rb 0.10.0 → 0.11.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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -26
  3. data/README.md +122 -16
  4. data/imap.rb.gemspec +2 -2
  5. data/lib/Imap/VERSION.rb +1 -1
  6. metadata +9 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68b300810859bc9e1aad02afe6eb9ae614581c114c05b175e59bffea2e94b4cd
4
- data.tar.gz: fd607d6ddca5bf9f9993f5fcc29a56c658671ada38d056c9bb9f6ce0c65d3968
3
+ metadata.gz: d7c582365fc3e8a049afdcd86797cee9737b0bae6abb17e35dcceb9c5d337260
4
+ data.tar.gz: 9c266b18c712b3c20962d75ada8c0d7d93355609f06150cf4cbe355ee7b116ca
5
5
  SHA512:
6
- metadata.gz: 4864d678e3d41d3ad94a001ebb08460c1f93d2441c5eeea117fffc859609de853ee6e833cb1fb46f285b5a9b3f13427e04b483754fbd00504cb71d6ef38f54fd
7
- data.tar.gz: 87db28691770c3bd7885866e25f5507f86785b9accf9689099cc3423ef8f82873e9be8a86145c53084566ef49565776e18d5337e683d71189e35a12a21e0f540
6
+ metadata.gz: d7756a53a8bf0d44cc51401f4d66e993366745fbec3da3f72101751df1300c3ebce7a13eb392f64ea49248b54aca78306e87858c1899edb92b9777d43088235c
7
+ data.tar.gz: 418107a061b52d283f498f154b4349c3b0ddf71c488e73a787d0710f836342f8a694f67fc0f3a2395481e94b8dc7e3d1ac39791904a0f2fbd382556a7b95afb2
data/CHANGELOG CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## 20260919
4
4
 
5
+ 0.11.0: ~ README.md: rewritten for the surface as it now stands; ~ the gemspecs: /['minitest', '~> 5.0']/'minitest'/, /['rake', '~> 13.0']/'rake'/. The README documented 0.4, five minors back, and the minitest line permitted only versions the suite no longer runs on.
6
+
7
+ 1. ~ README.md: + the searching, or, not, all_of, header and UnknownSearchKey; + the message accessors, all of them off the one fetch; + .for, .decode, #mailboxes, #source, LoginFailed, and subclassing. Every example run against the suite's mock rather than written from memory.
8
+ 2. ~ README.md: + that the gem is published under both names and that one installs one of them.
9
+ 3. ~ the gemspecs: /['minitest', '~> 5.0']/'minitest'/. The suite has run on minitest 6 since 0.4.3, which is where it gained require 'minitest/mock'; the line permitted 5.x alone.
10
+ 4. ~ the gemspecs: /['rake', '~> 13.0']/'rake'/, nothing being known to break outside it.
11
+ 5. ~ CHANGELOG: - the names of other programs and gems throughout. A reader has this repository and no other, so a comparison against software they cannot see is not evidence to them.
12
+ 6. ~ CHANGELOG: - the 6 items which recorded no change, the numbering closed up behind them.
13
+ 7. ~ Imap::VERSION: /0.10.0/0.11.0/
14
+
15
+
5
16
  0.10.0: ~ Imap.setup: + Imap::LoginFailed; ~ the gemspecs: /'~> 0.4'/'>= 0.4.5'/ upon net-imap. Imap.setup ignored the false which Imap#login returns when the server rejects the password, and handed back a client which was connected but not logged in.
6
17
 
7
18
  1. + Imap::LoginFailed
@@ -17,14 +28,13 @@
17
28
 
18
29
  1. + Imap::Search#all_of: all_of: [{text: 'invoice'}, {text: 'overdue'}] for TEXT invoice TEXT overdue. IMAP has no AND keyword, keys simply sitting side by side, but a hash cannot hold the same key twice, so two terms upon the one key could not be asked for at all: {text: 'a', text: 'b'} keeps b and drops a without a word. Each element is a criteria hash of its own, so or and not nest inside it.
19
30
  2. ~ Imap::Search#to_imap_search_keys: + ALL_OF and + ALL, read before the operator tests beside OR and NOT, being none of the three. ALL sat in ALL_SEARCH_KEYS and in neither operator list, so {all: true} raised UnknownSearchKey. It is the key meaning every message, which is precisely what a search with no criteria has to send, so the hash could not express the simplest search there is.
20
- 3. ALL is a case and not a member of BOOLEAN_SEARCH_KEYS, where it appears to belong: each of those defines a method of its own name, and #all is already the alias for #message_ids which the header's own example ends upon. Adding it there redefined the alias silently, which warning = true reported and 0.4.4 turned on for this.
21
- 4. + 5 tests: that all_of ands a list, that it is how the one key carries several terms where a hash cannot, that or and not nest within it, that it sits beside the plain keys, and that {all: true} answers ['ALL'].
22
- 5. ~ Imap::VERSION: /0.8.0/0.9.0/
31
+ 3. + 5 tests: that all_of ands a list, that it is how the one key carries several terms where a hash cannot, that or and not nest within it, that it sits beside the plain keys, and that {all: true} answers ['ALL'].
32
+ 4. ~ Imap::VERSION: /0.8.0/0.9.0/
23
33
 
24
34
 
25
35
  0.8.0: + Imap::Message.for, the fetch without the search, and a class a program can subclass.
26
36
 
27
- 1. + Imap::Message.for(imap_client, message_ids): the batched fetch on its own, .search now being the search and then this. A program which builds its own search keys had no way in: .search couples the two, so search-mail had 159 lines of its own Hit reimplementing the fetch beside it.
37
+ 1. + Imap::Message.for(imap_client, message_ids): the batched fetch on its own, .search now being the search and then this. A program which builds its own search keys had no way in, .search coupling the two, and had to reimplement the fetch beside it.
28
38
  2. ~ Imap::Message.for: builds with new rather than Imap::Message.new, so that a subclass is handed back its own kind. A program which wants a message of its own, with a mailbox or a decoded body upon it, subclasses rather than starts again.
29
39
  3. + 4 tests: that .for builds for ids searched elsewhere, that it fetches once, that it is empty where nothing was found, and that a subclass gets itself back.
30
40
  4. ~ Imap::VERSION: /0.7.0/0.8.0/
@@ -58,29 +68,24 @@
58
68
  1. + Imap::Search#any_of: or: [{from: 'a@x'}, {to: 'b@y'}]. OR takes two keys and no more, so three or more nest, OR OR a b c, as the server reads them. Each side is a criteria hash of its own and may nest further.
59
69
  2. + Imap::Search#none_of: not: {subject: 'Payday'}. NOT takes one key, so several are negated apiece, NOT a NOT b.
60
70
  3. ~ Imap::Search#to_imap_search_keys: OR and NOT read before the operator tests, being neither general nor boolean.
61
- 4. HEADER wanted no change: an array value already flattens to ['HEADER', field, value], which nothing said and nothing tested. It is tested now.
62
- 5. + tests for each, and for OR mixed with the plain keys.
63
- 6. ~ Imap::VERSION: /0.4.9/0.5.0/
71
+ 4. + tests for each, and for OR mixed with the plain keys.
72
+ 5. ~ Imap::VERSION: /0.4.9/0.5.0/
64
73
 
65
74
 
66
75
  0.4.9: + imap.rb.gemspec, so that the gem resolves under both names.
67
76
 
68
77
  1. + imap.rb.gemspec: the same code published as imap.rb, which is how gems are named here: 21 carry the suffix and imap is one of the few which do not. rubygems has no notion of an alias, so the two are separate gems which must be kept at the same version by hand.
69
- 2. It differs from imap.gemspec in the three lines measurand and namo differ in, the heading comment naming the file, the name, and the gemspec each lists among its own files. Neither ships the other.
70
- 3. imap.rb is unregistered, so this is its first version. bitget, eodhd, measurand and webdav each had their second name join at whatever the first stood at rather than backfilling, and each did it as a patch of its own carrying nothing else.
71
- 4. gem-publish builds and pushes each in turn, gem build and gem push taking one file apiece and gem build *.gemspec building only whichever the shell lists first.
72
- 5. ~ Gemfile: gemspec name: 'imap', bundler refusing to choose between two gemspecs and stopping with "There are multiple gemspecs at ...". Every pair here which uses gemspec names one: webdav, measurand and eodhd each name the elder of their two, and namo, which carried both from its first release, names the bare one. imap is the elder here.
73
- 6. ~ Imap::VERSION: /0.4.8/0.4.9/
78
+ 2. ~ Gemfile: gemspec name: 'imap', bundler refusing to choose between two gemspecs and stopping with "There are multiple gemspecs at ...". imap is the elder of the two names.
79
+ 3. ~ Imap::VERSION: /0.4.8/0.4.9/
74
80
 
75
81
 
76
82
  0.4.8: Rewrite the CHANGELOG in the standard form.
77
83
 
78
84
  1. ~ CHANGELOG: ## before each date rather than ## [version] - date, the version and its summary beneath, a blank line between that and the first item, and the items numbered rather than dashed. No item is reworded, dropped or reordered.
79
85
  2. ~ CHANGELOG: the dates in basic form, 20260910 for 2026-09-10, as every other gem here writes them.
80
- 3. ~ CHANGELOG: + the title, # imap/CHANGELOG, as coinmarketcap.rb and release-audit have it.
86
+ 3. ~ CHANGELOG: + the title, # imap/CHANGELOG.
81
87
  4. ~ CHANGELOG: the five releases of 20260917 under one date heading, which is how the form carries more than one in a day.
82
- 5. 9 of the 12 gems here were already in this form; imap and gate.rb were not, which leaves gate.rb.
83
- 6. ~ Imap::VERSION: /0.4.7/0.4.8/
88
+ 5. ~ Imap::VERSION: /0.4.7/0.4.8/
84
89
 
85
90
  0.4.7: ~ Imap::Search: the chaining interface, which the header has documented and which has never run
86
91
 
@@ -103,24 +108,24 @@
103
108
 
104
109
  0.4.5: + Gemfile; ~ imap.gemspec: dependencies=, - spec.date, + metadata
105
110
 
106
- 1. + Gemfile: source and gemspec, as switches, eodhd and moby have it, so that the dependencies are declared once in the gemspec rather than restated here to drift. bitget and coinmarketcap restate theirs and are the minority. This was the only gem here with no Gemfile at all.
107
- 2. ~ imap.gemspec: + 'Gemfile' to spec.files, which every other gem here ships.
108
- 3. ~ imap.gemspec: dependencies= and development_dependencies= through the Gem::Specification extension, as switches, eodhd and moby have it and as bitget, coinmarketcap and this did not. The constraints survive: the splat takes a bare string or a [name, constraint] pair alike.
109
- 4. ~ imap.gemspec: - spec.date = '2025-12-20', nine months and two versions stale, and the last one left in the estate. RubyGems answers 1980-01-02 in its place, the reproducible-build epoch, which is what coinmarketcap has carried since dropping its own at 0.6.0.
110
- 5. ~ imap.gemspec: + metadata, the four uris switches and moby declare, so that the RubyGems page links to the issues, the changelog, the source and the README. master here where moby says main, each by the branch it is on.
111
+ 1. + Gemfile: source and gemspec, so that the dependencies are declared once in the gemspec rather than restated here to drift.
112
+ 2. ~ imap.gemspec: + 'Gemfile' to spec.files.
113
+ 3. ~ imap.gemspec: dependencies= and development_dependencies= through the Gem::Specification extension. The constraints survive: the splat takes a bare string or a [name, constraint] pair alike.
114
+ 4. ~ imap.gemspec: - spec.date = '2025-12-20', nine months and two versions stale. RubyGems answers 1980-01-02 in its place, the reproducible-build epoch.
115
+ 5. ~ imap.gemspec: + metadata, the four uris, so that the RubyGems page links to the issues, the changelog, the source and the README.
111
116
  6. ~ Imap::VERSION: /0.4.4/0.4.5/
112
117
 
113
118
  0.4.4: + Rakefile, - test/test_all.rb
114
119
 
115
120
  1. + Rakefile: Rake::TestTask over FileList['test/**/*_test.rb'], with libs for lib and test, and warning = true. The minimal form nine of the gems here use rather than the fuller one five use: the :spec alias and the :version task belong to the minority, and a :version task reading VERSION.rb would not have caught 0.4.1, where require 'imap' left Imap::VERSION undefined while VERSION.rb sat there defining it. rake has been a development dependency since 0.4.0 with nothing here to run.
116
- 2. - test/test_all.rb: a second entry point which the Rakefile's FileList makes redundant, and which had drifted from the files on disk in two ways: it never loaded test/Imap/VERSION_test.rb, added in 0.4.2, so it ran 42 tests where there are 44; and it required './Imap_test' for a file named imap_test.rb, which resolved only because the filesystem is case insensitive and would not have on Linux. A glob cannot drift. 14 of the 16 gems here with a Rakefile carry no such file; switches keeps spec/all.rb because its Rakefile targets it, and bitget carries the same redundancy this removes.
121
+ 2. - test/test_all.rb: a second entry point which the Rakefile's FileList makes redundant, and which had drifted from the files on disk in two ways: it never loaded test/Imap/VERSION_test.rb, added in 0.4.2, so it ran 42 tests where there are 44; and it required './Imap_test' for a file named imap_test.rb, which resolved only because the filesystem is case insensitive and would not have on Linux. A glob cannot drift.
117
122
  3. ~ test/Imap/Message_test.rb: must_match(/Mock body/) for must_match /Mock body/, the ambiguous / which warning = true reports and which is the only warning the suite raises.
118
- 4. ~ imap.gemspec: + 'Rakefile' to spec.files, as eodhd, switches and moby have.
123
+ 4. ~ imap.gemspec: + 'Rakefile' to spec.files.
119
124
  5. ~ Imap::VERSION: /0.4.3/0.4.4/
120
125
 
121
126
  0.4.3: ~ test/test_helper.rb: + require 'minitest/mock', which minitest 6 no longer brings
122
127
 
123
- 1. ~ test/test_helper.rb: + `require 'minitest/mock'`. 35 of the 42 tests call stub and not one of them could: the suite answered "42 runs, 7 assertions, 0 failures, 35 errors". minitest 5's autorun required minitest/mock and shipped it, so the suite ran until minitest 6 dropped both the require and the file; the same thing coinmarketcap 0.6.1 found.
128
+ 1. ~ test/test_helper.rb: + `require 'minitest/mock'`. 35 of the 42 tests call stub and not one of them could: the suite answered "42 runs, 7 assertions, 0 failures, 35 errors". minitest 5's autorun required minitest/mock and shipped it, so the suite ran until minitest 6 dropped both the require and the file.
124
129
  2. ~ imap.gemspec: + minitest-mock as a development dependency, which minitest ~> 5.0 carried and minitest 6 does not.
125
130
  3. ~ Imap::VERSION: /0.4.2/0.4.3/
126
131
 
@@ -130,9 +135,8 @@
130
135
  0.4.2: ~ lib/imap.rb: + require_relative './Imap/VERSION'; + test/Imap/VERSION_test.rb
131
136
 
132
137
  1. ~ lib/imap.rb: + `require_relative './Imap/VERSION'`, last among the requires. The file had been present and unreached, so `require 'imap'` left Imap::VERSION undefined and the gemspec was the only thing loading it.
133
- 2. + test/Imap/VERSION_test.rb: that Imap::VERSION is a string and that it is three numbers separated by dots. Modelled on moby's, less the example comparing against the changelog, which was unreachable here while the file was misspelt.
134
- 3. The test loads the library rather than VERSION.rb, which is the whole of its value: run against v0.4.1 it fails with "uninitialized constant Imap::VERSION". Nine libraries were in that state and not one of them carried this test.
135
- 4. ~ Imap::VERSION: /0.4.1/0.4.2/
138
+ 2. + test/Imap/VERSION_test.rb: that Imap::VERSION is a string and that it is three numbers separated by dots. Less the example comparing against the changelog, which was unreachable here while the file was misspelt.
139
+ 3. ~ Imap::VERSION: /0.4.1/0.4.2/
136
140
 
137
141
 
138
142
  ## 20260822
data/README.md CHANGED
@@ -1,11 +1,15 @@
1
1
  # imap
2
2
 
3
- A Ruby wrapper around Net::IMAP with an elegant DSL for searching, reading, and managing email.
3
+ A Ruby wrapper around Net::IMAP with a hash-based search interface and messages which answer questions rather than handing back structs.
4
4
 
5
5
  ## Features
6
6
 
7
- - Clean, hash-based search interface
8
- - Intuitive message accessors
7
+ - Hash-based search criteria, including OR, NOT and repeated keys
8
+ - Message accessors for dates, flags, size, addresses and attachments
9
+ - RFC 2047 decoding, which Net::IMAP does not do
10
+ - Attachment filenames read out of the BODYSTRUCTURE, which IMAP cannot search upon
11
+ - One fetch for a whole set of messages rather than one per attribute
12
+ - BODY.PEEK throughout, so that reading a message does not mark it read
9
13
  - No Rails dependency - works anywhere
10
14
  - Zero external dependencies beyond net-imap
11
15
 
@@ -29,38 +33,140 @@ Or install it yourself as:
29
33
  $ gem install imap
30
34
  ```
31
35
 
36
+ The gem is published under both `imap` and `imap.rb`. They are the same code; install one.
37
+
32
38
  ## Usage
39
+
40
+ ### Connecting
41
+
33
42
  ```ruby
34
43
  require 'imap'
35
44
 
36
- # Connect and authenticate
37
45
  imap_client = Imap.setup(
38
- server: 'imap.thoran.com',
39
- username: 'code@thoran.com',
46
+ server: 'imap.example.com',
47
+ username: 'someone@example.com',
40
48
  password: 'bigsecret',
41
49
  mailbox: 'INBOX' # optional/default
42
50
  )
51
+ ```
43
52
 
53
+ `Imap.setup` raises `Imap::LoginFailed` where the server rejects the password, or where only one of the username and the password is given. `Imap#login` answers true or false for a caller which would rather handle it itself.
54
+
55
+ `Imap#mailboxes` lists every mailbox which can be selected:
56
+
57
+ ```ruby
58
+ imap_client.mailboxes # => ['INBOX', 'INBOX.Archive', ...]
59
+ imap_client.mailbox = 'INBOX.Archive'
60
+ ```
61
+
62
+ ### Searching
63
+
64
+ Criteria are a hash, keyed by the IMAP search keys in lower case:
65
+
66
+ ```ruby
44
67
  messages = imap_client.search(
45
68
  from: 'noreply@example.com',
46
69
  subject: 'Payday Loans',
47
- since: '18-DEC-2025',
70
+ since: '18-Dec-2025',
48
71
  seen: false
49
72
  )
73
+ ```
74
+
75
+ `or:` takes a list of criteria hashes. IMAP's OR takes two keys, so three or more nest for you:
76
+
77
+ ```ruby
78
+ imap_client.search(or: [{from: 'a@x'}, {to: 'b@y'}, {cc: 'c@z'}])
79
+ ```
80
+
81
+ `not:` negates each key it carries:
82
+
83
+ ```ruby
84
+ imap_client.search(not: {subject: 'Payday'})
85
+ ```
86
+
87
+ `all_of:` is how one key carries several terms, a hash holding it only once:
88
+
89
+ ```ruby
90
+ imap_client.search(all_of: [{text: 'invoice'}, {text: 'overdue'}])
91
+ ```
92
+
93
+ `header:` takes the field and the value:
94
+
95
+ ```ruby
96
+ imap_client.search(header: ['List-Id', 'ruby-talk'])
97
+ ```
98
+
99
+ An unrecognised key raises `Imap::Search::UnknownSearchKey` rather than widening the search silently.
50
100
 
51
- # Access message details
101
+ Where the search keys are built elsewhere, `Imap::Message.for` does the fetch on its own:
102
+
103
+ ```ruby
104
+ Imap::Message.for(imap_client, imap_client.imap.search(['ALL']))
105
+ ```
106
+
107
+ ### Messages
108
+
109
+ A search fetches UID, FLAGS, INTERNALDATE, RFC822.SIZE, ENVELOPE and BODYSTRUCTURE for the whole set in one command, so none of these costs a round trip:
110
+
111
+ ```ruby
52
112
  messages.each do |message|
53
- puts message.subject
54
- puts message.from
55
- puts message.to
56
- puts message.body
57
- puts message.urls # Extracted URLs from body
113
+ message.uid
114
+ message.flags # => [:Seen]
115
+ message.seen?
116
+ message.size # bytes
117
+ message.received_at # Time, from INTERNALDATE
118
+ message.sent_at # Time, from the Date header
119
+ message.subject # encoded words decoded
120
+ message.from # => 'Café <billing@example.com>'
121
+ message.from_address # => 'billing@example.com'
122
+ message.from_domain # => 'example.com'
123
+ message.to # => ['user@example.com']
124
+ message.cc
125
+ message.attachment?
126
+ message.attachment_filenames # => ['résumé.pdf']
58
127
  end
128
+ ```
59
129
 
60
- # Mark messages as read
61
- messages.first.mark_as_read
130
+ The body is fetched only when it is asked for:
131
+
132
+ ```ruby
133
+ message.body # BODY[TEXT], undecoded
134
+ message.source # the whole message, headers and all
135
+ message.urls # the URLs found in the body
136
+ message.mark_as_read
137
+ ```
138
+
139
+ `#body` is the raw text part. Choosing a part out of a multipart message and undoing its transfer encoding is MIME work rather than IMAP work, so hand `#source` to the `mail` gem where that is wanted:
140
+
141
+ ```ruby
142
+ mail = Mail.read_from_string(message.source)
143
+ ```
62
144
 
63
- # Clean up
145
+ ### Decoding
146
+
147
+ `Imap::Message.decode` reads RFC 2047 encoded words, which headers carry wherever a subject or a name is not ASCII:
148
+
149
+ ```ruby
150
+ Imap::Message.decode('=?UTF-8?B?UsOpc3Vtw6k=?=') # => 'Résumé'
151
+ ```
152
+
153
+ ### Extending
154
+
155
+ `Imap::Message.search` and `.for` build with `new`, so a subclass is handed back its own kind:
156
+
157
+ ```ruby
158
+ class Message < Imap::Message
159
+ def body
160
+ @body ||= Mail.read_from_string(source).text_part.decoded
161
+ end
162
+ end
163
+
164
+ Message.for(imap_client, message_ids).first.class # => Message
165
+ ```
166
+
167
+ ### Finishing
168
+
169
+ ```ruby
64
170
  imap_client.bye
65
171
  ```
66
172
 
data/imap.rb.gemspec CHANGED
@@ -32,9 +32,9 @@ Gem::Specification.new do |spec|
32
32
  ]
33
33
 
34
34
  spec.development_dependencies = [
35
- ['minitest', '~> 5.0'],
35
+ 'minitest',
36
36
  'minitest-mock',
37
- ['rake', '~> 13.0']
37
+ 'rake'
38
38
  ]
39
39
 
40
40
  spec.files = [
data/lib/Imap/VERSION.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Imap
2
- VERSION = '0.10.0'
2
+ VERSION = '0.11.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imap.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran
@@ -27,16 +27,16 @@ dependencies:
27
27
  name: minitest
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - "~>"
30
+ - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '5.0'
32
+ version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - "~>"
37
+ - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '5.0'
39
+ version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: minitest-mock
42
42
  requirement: !ruby/object:Gem::Requirement
@@ -55,16 +55,16 @@ dependencies:
55
55
  name: rake
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: '13.0'
60
+ version: '0'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - "~>"
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: '13.0'
67
+ version: '0'
68
68
  description: A Ruby wrapper around Net::IMAP with an elegant DSL for searching, reading,
69
69
  and managing email.
70
70
  email: code@thoran.com