imap_guard 1.0.0 → 2.0.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.
- checksums.yaml +5 -5
- data/.gitlab-ci.yml +16 -0
- data/.rspec +1 -1
- data/.rubocop.yml +46 -0
- data/Gemfile +14 -2
- data/Guardfile +4 -3
- data/LICENSE.txt +1 -1
- data/README.md +14 -17
- data/Rakefile +6 -2
- data/examples/example.rb +15 -13
- data/imap_guard.gemspec +12 -17
- data/lib/imap_guard/guard.rb +42 -42
- data/lib/imap_guard/query.rb +33 -32
- data/lib/imap_guard.rb +2 -0
- data/spec/imap_guard/guard_spec.rb +69 -68
- data/spec/imap_guard/query_spec.rb +26 -27
- data/spec/spec_helper.rb +5 -4
- metadata +20 -136
- data/.ruby-version +0 -1
- data/.travis.yml +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25df25da92ea0dae5ec4d6aaf9484049aa9713cc358ad43e6fce41628e2007a3
|
4
|
+
data.tar.gz: '0028b947283d027fa80184fbcbc211e922539644a452e4ed859c4ea3822ec832'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87d43bcba3020e0d2ec1b4a7e5d589abff5fa842ce83ab3405c2216818cfd43c877003613a4d65cb42abe190ab75d72435ab577efdd1dc914ebc77b87f46d74a
|
7
|
+
data.tar.gz: 4279c2dd1877d4f83508094d0725298d8e08ea1940c0c925c89a4842ffd196465b0cb3186555f73dbf15e50cafbda2b884d8982df0b3162dd1740a608316765a
|
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Official language image. Look for the different tagged releases at:
|
2
|
+
# https://hub.docker.com/r/library/ruby/tags/
|
3
|
+
image: ruby:latest
|
4
|
+
|
5
|
+
before_script:
|
6
|
+
- ruby -v
|
7
|
+
- bundle install -j $(nproc)
|
8
|
+
|
9
|
+
rspec:
|
10
|
+
script: rspec spec
|
11
|
+
|
12
|
+
rubocop:
|
13
|
+
script: rubocop
|
14
|
+
|
15
|
+
yard:
|
16
|
+
script: yard stats --list-undoc
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rake
|
3
|
+
- rubocop-rspec
|
4
|
+
|
5
|
+
AllCops:
|
6
|
+
TargetRubyVersion: 3.0
|
7
|
+
NewCops: enable
|
8
|
+
|
9
|
+
Metrics:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Layout/AccessModifierIndentation:
|
13
|
+
EnforcedStyle: outdent
|
14
|
+
|
15
|
+
Layout/LineLength:
|
16
|
+
Enabled: 100
|
17
|
+
|
18
|
+
Style/StringLiterals:
|
19
|
+
EnforcedStyle: double_quotes
|
20
|
+
|
21
|
+
Style/TrailingCommaInArguments:
|
22
|
+
EnforcedStyleForMultiline: comma
|
23
|
+
|
24
|
+
Style/TrailingCommaInHashLiteral:
|
25
|
+
EnforcedStyleForMultiline: comma
|
26
|
+
|
27
|
+
RSpec/ExampleLength:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
RSpec/ExpectInHook:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
RSpec/ExpectOutput:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
RSpec/MessageSpies:
|
37
|
+
Enabled: false # TODO: enable
|
38
|
+
|
39
|
+
RSpec/MultipleExpectations:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
RSpec/NamedSubject:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
RSpec/NestedGroups:
|
46
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -1,4 +1,16 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
# Specify your gem's runtime dependencies in imap_guard.gemspec
|
4
6
|
gemspec
|
7
|
+
|
8
|
+
# Specify your gem's development dependencies below:
|
9
|
+
gem "bundler", ">= 1.3"
|
10
|
+
gem "rake"
|
11
|
+
gem "rspec"
|
12
|
+
gem "rubocop"
|
13
|
+
gem "rubocop-rake"
|
14
|
+
gem "rubocop-rspec"
|
15
|
+
gem "simplecov"
|
16
|
+
gem "yard"
|
data/Guardfile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# More info at https://github.com/guard/guard#readme
|
2
4
|
|
3
|
-
guard
|
5
|
+
guard "rspec" do
|
4
6
|
watch(%r{^spec/.+_spec\.rb$})
|
5
7
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
6
8
|
watch(%r{^lib/(.+)/(.+)\.rb$}) { |m| "spec/#{m[1]}/#{m[2]}_spec.rb" }
|
7
|
-
watch(
|
9
|
+
watch("spec/spec_helper.rb") { "spec" }
|
8
10
|
watch(%r{^spec/support/.+\.rb$}) { "spec" }
|
9
11
|
end
|
10
|
-
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,11 @@
|
|
1
|
-
# ImapGuard
|
1
|
+
# ImapGuard
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/imap_guard)
|
4
|
+
[](https://gitlab.com/infertux/imap_guard/-/pipelines)
|
5
|
+
[](https://codeclimate.com/github/infertux/imap_guard)
|
6
|
+
[](http://inch-ci.org/github/infertux/imap_guard)
|
4
7
|
|
5
|
-
|
6
|
-
* [Bug Tracker](https://github.com/infertux/imap_guard/issues "Bug Tracker on Github")
|
7
|
-
* [API documentation](http://rubydoc.info/gems/imap_guard/frames "API Documentation on Rubydoc")
|
8
|
-
* [Rubygem](https://rubygems.org/gems/imap_guard "ImapGuard on Rubygems")
|
9
|
-
* [Continuous Integration](https://travis-ci.org/infertux/imap_guard "ImapGuard on Travis-CI")
|
10
|
-
* [Dependencies](https://gemnasium.com/infertux/imap_guard "ImapGuard dependencies on Gemnasium")
|
8
|
+
**A guard for your IMAP mailboxes.**
|
11
9
|
|
12
10
|
ImapGuard connects to your IMAP server and processes your emails.
|
13
11
|
You can finely pick them thanks to advanced search queries and Ruby blocks.
|
@@ -70,7 +68,7 @@ guard.delete base_query.dup.before(7).subject("Logwatch for ") do |mail|
|
|
70
68
|
end
|
71
69
|
```
|
72
70
|
|
73
|
-
|
71
|
+
You can always forge your own raw IMAP search queries (the [RFC](http://tools.ietf.org/html/rfc3501#section-6.4.4) can help in that case):
|
74
72
|
|
75
73
|
```ruby
|
76
74
|
query = 'SEEN SUBJECT "ALERT" FROM "root"'
|
@@ -79,19 +77,19 @@ guard.delete query do |mail|
|
|
79
77
|
end
|
80
78
|
```
|
81
79
|
|
82
|
-
|
80
|
+
There is a `move` method as well:
|
83
81
|
|
84
82
|
```ruby
|
85
|
-
guard.
|
86
|
-
|
83
|
+
guard.move query, 'destination_folder' do |mail|
|
84
|
+
# and it can take a filter block like `delete`
|
85
|
+
end
|
87
86
|
```
|
88
87
|
|
89
|
-
|
88
|
+
Finally, this should be handled automatically but you can explicitly expunge pending emails and close the connection:
|
90
89
|
|
91
90
|
```ruby
|
92
|
-
guard.
|
93
|
-
|
94
|
-
end
|
91
|
+
guard.expunge # effectively delete emails marked as deleted
|
92
|
+
guard.close # expunge then close the connection
|
95
93
|
```
|
96
94
|
|
97
95
|
### Advanced features
|
@@ -134,4 +132,3 @@ MIT
|
|
134
132
|
|
135
133
|
|
136
134
|
[Mail]: https://github.com/mikel/mail
|
137
|
-
|
data/Rakefile
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rspec/core/rake_task"
|
5
|
+
require "rubocop/rake_task"
|
3
6
|
|
4
7
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
5
|
-
t.ruby_opts =
|
8
|
+
t.ruby_opts = "-w"
|
6
9
|
end
|
7
10
|
|
8
|
-
|
11
|
+
RuboCop::RakeTask.new(:rubocop)
|
9
12
|
|
13
|
+
task default: %i[spec rubocop]
|
data/examples/example.rb
CHANGED
@@ -1,43 +1,45 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
# frozen_string_literal: true
|
4
|
+
# rubocop:disable all
|
5
|
+
|
6
|
+
require "imap_guard"
|
4
7
|
|
5
8
|
SETTINGS = {
|
6
|
-
host:
|
9
|
+
host: "imap.googlemail.com",
|
7
10
|
port: 993,
|
8
|
-
username:
|
9
|
-
password:
|
10
|
-
}
|
11
|
+
username: "you@gmail.com",
|
12
|
+
password: "your_pass",
|
13
|
+
}.freeze
|
11
14
|
|
12
|
-
settings = SETTINGS.merge(
|
15
|
+
settings = SETTINGS.merge(read_only: false)
|
13
16
|
base_query = ImapGuard::Query.new.unflagged.unanswered.freeze
|
14
17
|
guard = ImapGuard::Guard.new settings
|
15
18
|
# guard.debug = ->(mail) { print "#{mail.subject}: " }
|
16
19
|
guard.login
|
17
20
|
|
18
|
-
guard.select
|
21
|
+
guard.select "INBOX"
|
19
22
|
|
20
23
|
# Github
|
21
24
|
%w(github.com notifications@travis-ci.org app@gemnasium.com).map do |from|
|
22
25
|
base_query.dup.from(from)
|
23
26
|
end.each do |query|
|
24
|
-
guard.move query,
|
27
|
+
guard.move query, "INBOX.Github"
|
25
28
|
end
|
26
29
|
|
27
30
|
# To Do
|
28
|
-
guard.move base_query.dup.from("me").to("me"),
|
31
|
+
guard.move base_query.dup.from("me").to("me"), "INBOX.TODO"
|
29
32
|
|
30
33
|
# Ops
|
31
|
-
guard.select
|
34
|
+
guard.select "INBOX.Ops"
|
32
35
|
query = base_query.dup.seen
|
33
36
|
guard.delete query.dup.subject("monit alert -- ").before(7)
|
34
37
|
guard.delete query.dup.subject("CRON-APT completed on ").before(3)
|
35
38
|
guard.delete query.dup.subject("Logwatch for ").before(7)
|
36
|
-
guard.select
|
39
|
+
guard.select "INBOX"
|
37
40
|
|
38
41
|
# Uni
|
39
|
-
guard.move base_query.dup.or.from("uni.tld").to("uni.tld"),
|
42
|
+
guard.move base_query.dup.or.from("uni.tld").to("uni.tld"), "INBOX.Uni"
|
40
43
|
|
41
44
|
# Bye!
|
42
45
|
guard.disconnect
|
43
|
-
|
data/imap_guard.gemspec
CHANGED
@@ -1,32 +1,27 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
|
5
6
|
Gem::Specification.new do |spec|
|
6
7
|
spec.name = "imap_guard"
|
7
|
-
spec.version = "
|
8
|
+
spec.version = "2.0.0"
|
8
9
|
spec.authors = ["Cédric Félizard"]
|
9
10
|
spec.email = ["cedric@felizard.fr"]
|
10
|
-
spec.description =
|
11
|
+
spec.description = "A guard for your IMAP server"
|
11
12
|
spec.summary = spec.description
|
12
13
|
spec.homepage = "https://github.com/infertux/imap_guard"
|
13
14
|
spec.license = "MIT"
|
14
15
|
|
15
|
-
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.files = `git ls-files`.split($/) # rubocop:disable Style/SpecialGlobalVars
|
16
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.
|
21
|
-
|
20
|
+
spec.required_ruby_version = ">= 3.0.5"
|
21
|
+
|
22
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
22
23
|
|
23
|
-
spec.
|
24
|
-
spec.
|
25
|
-
spec.
|
26
|
-
spec.add_development_dependency 'rspec'
|
27
|
-
spec.add_development_dependency 'guard-rspec'
|
28
|
-
spec.add_development_dependency 'rb-inotify'
|
29
|
-
spec.add_development_dependency 'cane'
|
30
|
-
spec.add_development_dependency 'yard'
|
31
|
-
spec.add_development_dependency 'redcarpet' # for yardoc
|
24
|
+
spec.add_dependency "mail", ">= 2.7.1"
|
25
|
+
spec.add_dependency "net-imap"
|
26
|
+
spec.add_dependency "term-ansicolor", ">= 1.2.2"
|
32
27
|
end
|
data/lib/imap_guard/guard.rb
CHANGED
@@ -1,30 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
|
6
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/imap"
|
4
|
+
require "ostruct"
|
5
|
+
require "mail"
|
6
|
+
require "term/ansicolor"
|
7
|
+
|
8
|
+
String.include Term::ANSIColor
|
9
|
+
Term::ANSIColor.coloring = $stdout.isatty
|
7
10
|
|
8
11
|
module ImapGuard
|
9
12
|
# Guard allows you to process your mailboxes.
|
10
13
|
class Guard
|
11
14
|
# List of required settings
|
12
|
-
REQUIRED_SETTINGS = [
|
15
|
+
REQUIRED_SETTINGS = %i[host port username password].freeze
|
13
16
|
|
14
17
|
# List of optional settings
|
15
|
-
OPTIONAL_SETTINGS = [
|
18
|
+
OPTIONAL_SETTINGS = %i[read_only verbose].freeze
|
19
|
+
|
20
|
+
Settings = Struct.new("Settings", *(REQUIRED_SETTINGS + OPTIONAL_SETTINGS))
|
16
21
|
|
17
22
|
# @return [Proc, nil] Matched emails are passed to this debug lambda if present
|
18
23
|
attr_accessor :debug
|
19
24
|
|
20
25
|
# @note The settings are frozen
|
21
|
-
# @return [
|
26
|
+
# @return [Struct::Settings] ImapGuard settings
|
22
27
|
attr_reader :settings
|
23
28
|
|
24
29
|
# @return [String, nil] Currently selected mailbox
|
25
30
|
attr_reader :mailbox
|
26
31
|
|
27
|
-
def initialize
|
32
|
+
def initialize(settings)
|
28
33
|
self.settings = settings
|
29
34
|
end
|
30
35
|
|
@@ -39,7 +44,7 @@ module ImapGuard
|
|
39
44
|
|
40
45
|
# Selects a mailbox (folder)
|
41
46
|
# @return [void]
|
42
|
-
def select
|
47
|
+
def select(mailbox)
|
43
48
|
if @settings.read_only
|
44
49
|
@imap.examine(mailbox) # open in read-only
|
45
50
|
else
|
@@ -53,15 +58,15 @@ module ImapGuard
|
|
53
58
|
# @param mailbox Destination mailbox
|
54
59
|
# @param filter Optional filter block
|
55
60
|
# @return [void]
|
56
|
-
def move
|
57
|
-
operation = lambda
|
61
|
+
def move(query, mailbox, &filter)
|
62
|
+
operation = lambda do |message_id|
|
58
63
|
unless @settings.read_only
|
59
64
|
@imap.copy(message_id, mailbox)
|
60
65
|
@imap.store(message_id, "+FLAGS", [Net::IMAP::DELETED])
|
61
66
|
end
|
62
67
|
|
63
68
|
"moved to #{mailbox}".yellow
|
64
|
-
|
69
|
+
end
|
65
70
|
process query, operation, &filter
|
66
71
|
end
|
67
72
|
|
@@ -69,14 +74,12 @@ module ImapGuard
|
|
69
74
|
# @param query IMAP query
|
70
75
|
# @param filter Optional filter block
|
71
76
|
# @return [void]
|
72
|
-
def delete
|
73
|
-
operation = lambda
|
74
|
-
unless @settings.read_only
|
75
|
-
@imap.store(message_id, "+FLAGS", [Net::IMAP::DELETED])
|
76
|
-
end
|
77
|
+
def delete(query, &filter)
|
78
|
+
operation = lambda do |message_id|
|
79
|
+
@imap.store(message_id, "+FLAGS", [Net::IMAP::DELETED]) unless @settings.read_only
|
77
80
|
|
78
|
-
|
79
|
-
|
81
|
+
"deleted".red
|
82
|
+
end
|
80
83
|
process query, operation, &filter
|
81
84
|
end
|
82
85
|
|
@@ -84,16 +87,16 @@ module ImapGuard
|
|
84
87
|
# @param query IMAP query
|
85
88
|
# @param opration Lambda to call on each message
|
86
89
|
# @return [void]
|
87
|
-
def each
|
88
|
-
operation =
|
90
|
+
def each(query)
|
91
|
+
operation = ->(message_id) { yield message_id } # rubocop:disable Style/ExplicitBlockArgument
|
89
92
|
process query, operation
|
90
93
|
end
|
91
94
|
|
92
95
|
# Fetches a message from its UID
|
93
96
|
# @return [Mail]
|
94
97
|
# @note We use "BODY.PEEK[]" to avoid setting the \Seen flag.
|
95
|
-
def fetch_mail
|
96
|
-
msg = @imap.fetch(message_id,
|
98
|
+
def fetch_mail(message_id)
|
99
|
+
msg = @imap.fetch(message_id, "BODY.PEEK[]").first.attr["BODY[]"]
|
97
100
|
Mail.read_from_string msg
|
98
101
|
end
|
99
102
|
|
@@ -125,7 +128,7 @@ module ImapGuard
|
|
125
128
|
|
126
129
|
private
|
127
130
|
|
128
|
-
def process
|
131
|
+
def process(query, operation)
|
129
132
|
message_ids = search query
|
130
133
|
count = message_ids.size
|
131
134
|
|
@@ -133,10 +136,10 @@ module ImapGuard
|
|
133
136
|
print "Processing UID #{message_id} (#{index.succ}/#{count}): "
|
134
137
|
|
135
138
|
result = true
|
136
|
-
if block_given?
|
139
|
+
if block_given? || debug
|
137
140
|
mail = fetch_mail message_id
|
138
141
|
|
139
|
-
debug.call(mail) if debug
|
142
|
+
debug.call(mail) if debug # rubocop:disable Style/SafeNavigation
|
140
143
|
|
141
144
|
if block_given?
|
142
145
|
result = yield(mail)
|
@@ -146,12 +149,11 @@ module ImapGuard
|
|
146
149
|
|
147
150
|
puts result ? operation.call(message_id) : "ignored".green
|
148
151
|
end
|
149
|
-
|
150
152
|
ensure
|
151
153
|
expunge
|
152
154
|
end
|
153
155
|
|
154
|
-
def search
|
156
|
+
def search(query)
|
155
157
|
unless [Array, String].any? { |type| query.is_a? type }
|
156
158
|
raise TypeError, "Query must be either a string holding the entire search string, or a single-dimension array of search keywords and arguments."
|
157
159
|
end
|
@@ -164,27 +166,25 @@ module ImapGuard
|
|
164
166
|
|
165
167
|
def verbose
|
166
168
|
@verbose ||= if @settings.verbose
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end.new
|
175
|
-
end
|
169
|
+
$stdout
|
170
|
+
else
|
171
|
+
# anonymous null object
|
172
|
+
# rubocop:disable all
|
173
|
+
Class.new do def method_missing(*); nil end end.new
|
174
|
+
# rubocop:enable all
|
175
|
+
end
|
176
176
|
end
|
177
177
|
|
178
|
-
def settings=
|
178
|
+
def settings=(settings)
|
179
179
|
missing = REQUIRED_SETTINGS - settings.keys
|
180
180
|
raise ArgumentError, "Missing settings: #{missing}" unless missing.empty?
|
181
181
|
|
182
182
|
unknown = settings.keys - REQUIRED_SETTINGS - OPTIONAL_SETTINGS
|
183
183
|
raise ArgumentError, "Unknown settings: #{unknown}" unless unknown.empty?
|
184
184
|
|
185
|
-
|
185
|
+
struct = Settings.members.map { |member| settings.fetch(member, false) }
|
186
|
+
@settings = Settings.new(*struct).freeze
|
186
187
|
puts "DRY-RUN MODE ENABLED".yellow.bold.negative if @settings.read_only
|
187
188
|
end
|
188
189
|
end
|
189
190
|
end
|
190
|
-
|
data/lib/imap_guard/query.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ImapGuard
|
2
4
|
# Query is a neat DSL to help you generate IMAP search queries.
|
3
5
|
# @note All methods return self so they can be chained.
|
@@ -5,31 +7,31 @@ module ImapGuard
|
|
5
7
|
# Messages that have the +\Seen+ flag set.
|
6
8
|
# @return [self]
|
7
9
|
def seen
|
8
|
-
self <<
|
10
|
+
self << "SEEN"
|
9
11
|
end
|
10
12
|
|
11
13
|
# Messages that do not have the +\Seen+ flag set.
|
12
14
|
# @return [self]
|
13
15
|
def unseen
|
14
|
-
self <<
|
16
|
+
self << "UNSEEN"
|
15
17
|
end
|
16
18
|
|
17
19
|
# Messages that do not have the +\Answered+ flag set.
|
18
20
|
# @return [self]
|
19
21
|
def unanswered
|
20
|
-
self <<
|
22
|
+
self << "UNANSWERED"
|
21
23
|
end
|
22
24
|
|
23
25
|
# Messages that do not have the +\Flagged+ flag set.
|
24
26
|
# @return [self]
|
25
27
|
def unflagged
|
26
|
-
self <<
|
28
|
+
self << "UNFLAGGED"
|
27
29
|
end
|
28
30
|
|
29
31
|
# Messages with the +\Deleted+ flag set.
|
30
32
|
# @return [self]
|
31
33
|
def deleted
|
32
|
-
self <<
|
34
|
+
self << "DELETED"
|
33
35
|
end
|
34
36
|
|
35
37
|
# Messages that match either search key.
|
@@ -41,13 +43,13 @@ module ImapGuard
|
|
41
43
|
# or.unanswered.unflagged #=> ["OR", "UNANSWERED", "UNFLAGGED"]
|
42
44
|
# or(:unanswered, :unflagged) #=> ["OR", "UNANSWERED", "UNFLAGGED"]
|
43
45
|
# @return [self]
|
44
|
-
def or
|
45
|
-
self <<
|
46
|
+
def or(search_key1 = nil, search_key2 = nil)
|
47
|
+
self << "OR"
|
46
48
|
|
47
|
-
if search_key1
|
49
|
+
if search_key1 && search_key2
|
48
50
|
send(search_key1)
|
49
51
|
send(search_key2)
|
50
|
-
elsif search_key1
|
52
|
+
elsif search_key1 || search_key2
|
51
53
|
raise ArgumentError, "You must give either zero or two arguments."
|
52
54
|
end
|
53
55
|
|
@@ -60,8 +62,8 @@ module ImapGuard
|
|
60
62
|
# not.deleted #=> ["NOT", "DELETED"]
|
61
63
|
# not(:deleted) #=> ["NOT", "DELETED"]
|
62
64
|
# @return [self]
|
63
|
-
def not
|
64
|
-
self <<
|
65
|
+
def not(search_key = nil)
|
66
|
+
self << "NOT"
|
65
67
|
send(search_key) if search_key
|
66
68
|
self
|
67
69
|
end
|
@@ -69,29 +71,29 @@ module ImapGuard
|
|
69
71
|
# Messages that contain the specified string in the envelope
|
70
72
|
# structure's SUBJECT field.
|
71
73
|
# @return [self]
|
72
|
-
def subject
|
73
|
-
self <<
|
74
|
+
def subject(string)
|
75
|
+
self << "SUBJECT" << string
|
74
76
|
end
|
75
77
|
|
76
78
|
# Messages that contain the specified string in the envelope
|
77
79
|
# structure's FROM field.
|
78
80
|
# @return [self]
|
79
|
-
def from
|
80
|
-
self <<
|
81
|
+
def from(string)
|
82
|
+
self << "FROM" << string
|
81
83
|
end
|
82
84
|
|
83
85
|
# Messages that contain the specified string in the envelope
|
84
86
|
# structure's TO field.
|
85
87
|
# @return [self]
|
86
|
-
def to
|
87
|
-
self <<
|
88
|
+
def to(string)
|
89
|
+
self << "TO" << string
|
88
90
|
end
|
89
91
|
|
90
92
|
# Messages that contain the specified string in the envelope
|
91
93
|
# structure's CC field.
|
92
94
|
# @return [self]
|
93
|
-
def cc
|
94
|
-
self <<
|
95
|
+
def cc(string)
|
96
|
+
self << "CC" << string
|
95
97
|
end
|
96
98
|
|
97
99
|
# Messages whose internal date (disregarding time and timezone)
|
@@ -101,20 +103,19 @@ module ImapGuard
|
|
101
103
|
# - [Fixnum]: _n_ days before today
|
102
104
|
# - [Date]: uses this date
|
103
105
|
# @return [self]
|
104
|
-
def before
|
105
|
-
case date
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
106
|
+
def before(date)
|
107
|
+
date = case date
|
108
|
+
when String
|
109
|
+
date
|
110
|
+
when Integer
|
111
|
+
(Date.today - date).strftime "%e-%b-%Y"
|
112
|
+
when Date
|
113
|
+
date.strftime "%e-%b-%Y"
|
114
|
+
else
|
115
|
+
raise ArgumentError, "#{date.inspect} is invalid."
|
116
|
+
end
|
115
117
|
|
116
|
-
self <<
|
118
|
+
self << "BEFORE" << date
|
117
119
|
end
|
118
120
|
end
|
119
121
|
end
|
120
|
-
|