imap-filter 0.0.2
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 +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.semver +5 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +122 -0
- data/LICENSE.txt +20 -0
- data/README.org +321 -0
- data/Rakefile +58 -0
- data/bin/imap-filter +11 -0
- data/examples/default.imap +56 -0
- data/imap-filter.gemspec +110 -0
- data/lib/imap-filter.rb +17 -0
- data/lib/imap-filter/cli.rb +24 -0
- data/lib/imap-filter/dsl.rb +321 -0
- data/lib/imap-filter/functionality.rb +128 -0
- data/lib/imap-filter/imap-filter.rb +108 -0
- data/lib/imap-filter/monkeypatches.rb +37 -0
- data/spec/imap-filter_spec.rb +7 -0
- data/spec/spec_helper.rb +29 -0
- metadata +311 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module ImapFilter
|
3
|
+
module Functionality
|
4
|
+
include Forwardable
|
5
|
+
include ImapFilter::DSL
|
6
|
+
|
7
|
+
FULL ='(UID RFC822.SIZE ENVELOPE BODY.PEEK[TEXT])'
|
8
|
+
BODYTEXT = 'BODY[TEXT]'
|
9
|
+
SUBJECTPEEKLIST = '(UID RFC822.SIZE BODY.PEEK[HEADER.FIELDS (SUBJECT)])'
|
10
|
+
SUBJECTLIST = 'BODY[HEADER.FIELDS (SUBJECT)]'
|
11
|
+
class FunctFilter
|
12
|
+
extend Forwardable
|
13
|
+
|
14
|
+
attr :dfilt, :seq, :acc
|
15
|
+
|
16
|
+
def_delegators :@dfilt, :mbox, :directives, :actions
|
17
|
+
|
18
|
+
def initialize filt
|
19
|
+
@dfilt = filt
|
20
|
+
@seq = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# These strings come from the DSL in the form of
|
24
|
+
# "acct:mbox_path". Reslove and return the actual
|
25
|
+
# account object and mbox path as [account_ob, mbox]
|
26
|
+
def parse_and_resolve_account_mbox_string ambox, default_account = nil
|
27
|
+
a, b = ambox.split ':'
|
28
|
+
a, b = [nil, a] if b.nil?
|
29
|
+
a = nil if a == ''
|
30
|
+
acc = a.nil? ? default_account : _accounts[a.to_sym]
|
31
|
+
mbox = b
|
32
|
+
[acc, mbox]
|
33
|
+
end
|
34
|
+
|
35
|
+
def select_email
|
36
|
+
@acc, box = parse_and_resolve_account_mbox_string mbox
|
37
|
+
acc.imap.select box
|
38
|
+
@seq = acc.imap.search directives
|
39
|
+
end
|
40
|
+
|
41
|
+
def ensure_mailbox account, mailbox
|
42
|
+
begin
|
43
|
+
account.imap.create mailbox
|
44
|
+
rescue Net::IMAP::NoResponseError => e
|
45
|
+
# we ignore this because it -- probably -- means the mailbox already exists.
|
46
|
+
puts " *** ignored mailbox error: #{e}".red unless _options[:verbose] < 1
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_actions
|
51
|
+
actions.each do |action|
|
52
|
+
send *action
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def subject_list
|
57
|
+
unless seq.empty?
|
58
|
+
acc.imap.fetch(seq, SUBJECTPEEKLIST).map do |subject|
|
59
|
+
subject.attr[SUBJECTLIST].to_s.strip.tr("\n\r", '')
|
60
|
+
end
|
61
|
+
else
|
62
|
+
[]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def list *a, **h
|
67
|
+
subject_list.each do |subject|
|
68
|
+
puts subject.attr[subj].to_s.strip.tr("\n\r", '').light_yellow
|
69
|
+
end unless seq.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
def _cross_account_mvcp op, dest_acc, dest_mbox
|
73
|
+
ensure_mailbox dest_acc, dest_mbox
|
74
|
+
begin
|
75
|
+
acc.imap.fetch(seq, FULL).each do |fdat|
|
76
|
+
unless _options[:verbose] < 2
|
77
|
+
print " >>".yellow
|
78
|
+
puts " seq #{fdat.seqno} #{fdat.attr['ENVELOPE']['subject']} -> #{dest_acc.name}:#{dest_mbox}".light_blue
|
79
|
+
end
|
80
|
+
raw = fdat.attr['ENVELOPE'].email_header + fdat.attr[BODYTEXT]
|
81
|
+
dest_acc.imap.append dest_mbox, raw, fdat.attr['FLAGS']
|
82
|
+
end
|
83
|
+
rescue => e
|
84
|
+
puts "ERROR: #{e} -- perhaps you did a move or delete operation before copy?".light_red
|
85
|
+
exit 10
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _mvcp op, destination
|
90
|
+
raise "Illegal operation #{op}" unless [:copy, :move].member? op
|
91
|
+
|
92
|
+
dest_acc, dest_mbox = parse_and_resolve_account_mbox_string destination
|
93
|
+
ensure_mailbox dest_acc, dest_mbox
|
94
|
+
|
95
|
+
if dest_acc == acc # in-account move
|
96
|
+
dest_acc.imap.send op, seq, dest_mbox
|
97
|
+
else # move or copy to different account
|
98
|
+
_cross_account_mvcp op, dest_acc, dest_mbox
|
99
|
+
end unless seq.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
def move destination
|
103
|
+
puts " move from #{acc.name} to #{destination}".light_blue unless _options[:verbose] < 1
|
104
|
+
_mvcp :move, destination unless _options[:dryrun]
|
105
|
+
end
|
106
|
+
|
107
|
+
def copy destination
|
108
|
+
puts " copy from #{acc.name} to #{destination}".light_blue unless _options[:verbose] < 1
|
109
|
+
_mvcp :copy, destination unless _options[:dryrun]
|
110
|
+
end
|
111
|
+
|
112
|
+
def delete
|
113
|
+
puts " delete from #{acc.name}".light_blue unless _options[:verbose] < 1
|
114
|
+
mark :Deleted unless _options[:dryrun]
|
115
|
+
end
|
116
|
+
|
117
|
+
def mark *flags
|
118
|
+
puts " mark #{flags} in #{acc.name}".light_blue unless _options[:verbose] < 1
|
119
|
+
acc.imap.store seq, '+FLAGS.SILENT', flags unless seq.empty? or _options[:dryrun]
|
120
|
+
end
|
121
|
+
|
122
|
+
def unmark *flags
|
123
|
+
puts " unmark #{flags} in #{acc.name}".light_blue unless _options[:verbose] < 1
|
124
|
+
acc.imap.store seq, '-FLAGS.SILENT', flags unless seq.empty? or _options[:dryrun]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'imap-filter'
|
3
|
+
|
4
|
+
include ImapFilter::DSL
|
5
|
+
|
6
|
+
module ImapFilter
|
7
|
+
module Functionality
|
8
|
+
STATUS = {messages: 'MESSAGES', recent: 'RECENT', unseen: 'UNSEEN'}
|
9
|
+
ISTAT = STATUS.map{ |k, v| [v, k] }.to_h
|
10
|
+
|
11
|
+
def self.show_imap_plan
|
12
|
+
puts '====== Accounts'.light_yellow
|
13
|
+
_accounts.each do |name, account|
|
14
|
+
print " #{name}: ".light_green
|
15
|
+
print account.to_s.light_blue
|
16
|
+
puts
|
17
|
+
end
|
18
|
+
puts '====== Filters'.light_yellow
|
19
|
+
_filters.each do |name, filter|
|
20
|
+
print " #{name}: ".light_green
|
21
|
+
print filter.to_s.light_blue
|
22
|
+
puts
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# List all mboxes of given account and their statuses
|
27
|
+
def self.list_mboxes account
|
28
|
+
account.imap.list('', '*')
|
29
|
+
.map { |m| [m['name'], m['attr']] }
|
30
|
+
.map { |mbox, attr|
|
31
|
+
begin
|
32
|
+
[mbox,
|
33
|
+
account.imap.status(mbox, STATUS.values)
|
34
|
+
.map{ |k, v| "#{ISTAT[k]}:#{v}" }
|
35
|
+
.join(' '),
|
36
|
+
attr]
|
37
|
+
rescue
|
38
|
+
nil
|
39
|
+
end }
|
40
|
+
.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.login_imap_accounts test: false
|
44
|
+
puts "====== #{test ? 'Test' : 'Login'} Accounts".light_yellow
|
45
|
+
_accounts.each do |name, account|
|
46
|
+
print " #{name}...".light_white
|
47
|
+
begin
|
48
|
+
account._open_connection
|
49
|
+
puts "SUCCESS, delim #{account.delim}".light_green
|
50
|
+
list_mboxes(account).each do |mbox, stat, attr|
|
51
|
+
print " #{mbox}".light_blue
|
52
|
+
print " #{stat}".light_red
|
53
|
+
puts " #{attr}".light_cyan
|
54
|
+
end unless _options[:verbose] < 2
|
55
|
+
rescue => e
|
56
|
+
puts "FAILED: #{e}".light_red
|
57
|
+
exit unless test
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.list_of_filters_to_run
|
63
|
+
unless _options[:filters].nil?
|
64
|
+
_options[:filters].map{ |f| f.to_sym }
|
65
|
+
else
|
66
|
+
_filters.keys
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# do the selection based on directives
|
71
|
+
# then perform the actions on the set selected.
|
72
|
+
# optimize for copy/moves that are to the same account.
|
73
|
+
def self.run_filter filt
|
74
|
+
f = FunctFilter.new _filters[filt]
|
75
|
+
f.select_email
|
76
|
+
|
77
|
+
unless _options[:verbose] < 1
|
78
|
+
puts "====== Email to be processed by #{filt}".light_yellow
|
79
|
+
f.subject_list.each do |subject|
|
80
|
+
print ' ##'.yellow
|
81
|
+
puts subject.light_blue
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
f.process_actions
|
86
|
+
f.acc.imap.expunge unless _options[:dryrun]
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.execute_filters
|
90
|
+
#login_imap_accounts
|
91
|
+
list_of_filters_to_run.each do |f|
|
92
|
+
print "Running filter: ".light_white
|
93
|
+
puts "#{f}".light_yellow
|
94
|
+
run_filter f
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.run_filters filters
|
99
|
+
show_imap_plan unless _options[:verbose] < 1
|
100
|
+
if _options[:test]
|
101
|
+
login_imap_accounts test: true
|
102
|
+
else
|
103
|
+
login_imap_accounts
|
104
|
+
execute_filters
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Net::IMAP::Envelope
|
2
|
+
CRLF = "\r\n"
|
3
|
+
HEDCNS = [
|
4
|
+
['Date:', ->(s){ s.date } ],
|
5
|
+
['Subject:', ->(s){ s.subject } ],
|
6
|
+
['Date:', ->(s){ s.date } ],
|
7
|
+
['Message-ID:', ->(s){ s.message_id }],
|
8
|
+
['Sender:', ->(s){
|
9
|
+
s.sender.map{ |f|
|
10
|
+
"#{f.name} <#{f.mailbox}@#{f.host}>"
|
11
|
+
}.join ',' unless s.sender.nil? } ],
|
12
|
+
['From:', ->(s){
|
13
|
+
s.from.map{ |f|
|
14
|
+
"#{f.name} <#{f.mailbox}@#{f.host}>"
|
15
|
+
}.join ',' unless s.from.nil? } ],
|
16
|
+
['To:', ->(s){
|
17
|
+
s.to.map{ |f|
|
18
|
+
"#{f.name} <#{f.mailbox}@#{f.host}>"
|
19
|
+
}.join ',' unless s.to.nil? } ],
|
20
|
+
['Cc:', ->(s){
|
21
|
+
s.cc.map{ |f|
|
22
|
+
"#{f.name} <#{f.mailbox}@#{f.host}>"
|
23
|
+
}.join ',' unless s.cc.nil? } ],
|
24
|
+
['Bcc:', ->(s){
|
25
|
+
s.bcc.map{ |f|
|
26
|
+
"#{f.name} <#{f.mailbox}@#{f.host}>"
|
27
|
+
}.join ',' unless s.bcc.nil? } ],
|
28
|
+
['In-Reply-To:', ->(s){ s.in_reply_to }],
|
29
|
+
].to_h
|
30
|
+
|
31
|
+
def email_header
|
32
|
+
HEDCNS.map{ |field, fun| "#{field} #{fun.(self)}" }
|
33
|
+
.join CRLF
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
|
3
|
+
module SimpleCov::Configuration
|
4
|
+
def clean_filters
|
5
|
+
@filters = []
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
SimpleCov.configure do
|
10
|
+
clean_filters
|
11
|
+
load_adapter 'test_frameworks'
|
12
|
+
end
|
13
|
+
|
14
|
+
ENV["COVERAGE"] && SimpleCov.start do
|
15
|
+
add_filter "/.rvm/"
|
16
|
+
end
|
17
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
18
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
19
|
+
|
20
|
+
require 'rspec'
|
21
|
+
require 'imap-filter'
|
22
|
+
|
23
|
+
# Requires supporting files with custom matchers and macros, etc,
|
24
|
+
# in ./support/ and its subdirectories.
|
25
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
26
|
+
|
27
|
+
RSpec.configure do |config|
|
28
|
+
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: imap-filter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fred Mitchell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: semver
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: awesome_print
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: text-table
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: colorize
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rdoc
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: bundler
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '1'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: juwelier
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '2'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '2'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: pry
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: pry-byebug
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '3'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '3'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: pry-doc
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - "~>"
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - "~>"
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: pry-remote
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - "~>"
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - "~>"
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: pry-rescue
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '1'
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - "~>"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '1'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: pry-stack_explorer
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - "~>"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '0'
|
244
|
+
type: :development
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - "~>"
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
description: |2-
|
252
|
+
|
253
|
+
imap-filter is a Ruby implementation of an IMAP filtering application.
|
254
|
+
it can handle multiple IMAP accounts, and create IMAP folders automatically
|
255
|
+
where none exists.
|
256
|
+
|
257
|
+
The imap-filter DSL makes it easy to filter. You can also do "dry-runs"
|
258
|
+
to make sure what happens is what is expected.
|
259
|
+
email: fred.mitchell@gmx.de
|
260
|
+
executables:
|
261
|
+
- imap-filter
|
262
|
+
extensions: []
|
263
|
+
extra_rdoc_files:
|
264
|
+
- LICENSE.txt
|
265
|
+
- README.org
|
266
|
+
files:
|
267
|
+
- ".document"
|
268
|
+
- ".rspec"
|
269
|
+
- ".ruby-version"
|
270
|
+
- ".semver"
|
271
|
+
- Gemfile
|
272
|
+
- Gemfile.lock
|
273
|
+
- LICENSE.txt
|
274
|
+
- README.org
|
275
|
+
- Rakefile
|
276
|
+
- bin/imap-filter
|
277
|
+
- examples/default.imap
|
278
|
+
- imap-filter.gemspec
|
279
|
+
- lib/imap-filter.rb
|
280
|
+
- lib/imap-filter/cli.rb
|
281
|
+
- lib/imap-filter/dsl.rb
|
282
|
+
- lib/imap-filter/functionality.rb
|
283
|
+
- lib/imap-filter/imap-filter.rb
|
284
|
+
- lib/imap-filter/monkeypatches.rb
|
285
|
+
- spec/imap-filter_spec.rb
|
286
|
+
- spec/spec_helper.rb
|
287
|
+
homepage: http://github.com/flajann2/imap-filter
|
288
|
+
licenses:
|
289
|
+
- MIT
|
290
|
+
metadata: {}
|
291
|
+
post_install_message:
|
292
|
+
rdoc_options: []
|
293
|
+
require_paths:
|
294
|
+
- lib
|
295
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ">="
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: '2.2'
|
300
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
301
|
+
requirements:
|
302
|
+
- - ">="
|
303
|
+
- !ruby/object:Gem::Version
|
304
|
+
version: '0'
|
305
|
+
requirements: []
|
306
|
+
rubyforge_project:
|
307
|
+
rubygems_version: 2.5.1
|
308
|
+
signing_key:
|
309
|
+
specification_version: 4
|
310
|
+
summary: IMAP Scriptable filter for one or multiple Email accounts.
|
311
|
+
test_files: []
|