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
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
require 'semver'
|
14
|
+
|
15
|
+
def s_version
|
16
|
+
SemVer.find.format "%M.%m.%p%s"
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'juwelier'
|
20
|
+
Juwelier::Tasks.new do |gem|
|
21
|
+
# gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
|
22
|
+
gem.name = "imap-filter"
|
23
|
+
gem.homepage = "http://github.com/flajann2/imap-filter"
|
24
|
+
gem.license = "MIT"
|
25
|
+
gem.summary = %Q{IMAP Scriptable filter for one or multiple Email accounts.}
|
26
|
+
gem.description = %Q{
|
27
|
+
imap-filter is a Ruby implementation of an IMAP filtering application.
|
28
|
+
it can handle multiple IMAP accounts, and create IMAP folders automatically
|
29
|
+
where none exists.
|
30
|
+
|
31
|
+
The imap-filter DSL makes it easy to filter. You can also do "dry-runs"
|
32
|
+
to make sure what happens is what is expected.}
|
33
|
+
|
34
|
+
gem.email = "fred.mitchell@gmx.de"
|
35
|
+
gem.authors = ["Fred Mitchell"]
|
36
|
+
gem.version = s_version
|
37
|
+
gem.required_ruby_version = '>= 2.2'
|
38
|
+
|
39
|
+
# dependencies defined in Gemfile
|
40
|
+
end
|
41
|
+
Juwelier::RubygemsDotOrgTasks.new
|
42
|
+
|
43
|
+
require 'rspec/core'
|
44
|
+
require 'rspec/core/rake_task'
|
45
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
46
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Code coverage detail"
|
50
|
+
task :simplecov do
|
51
|
+
ENV['COVERAGE'] = "true"
|
52
|
+
Rake::Task['spec'].execute
|
53
|
+
end
|
54
|
+
|
55
|
+
task :default => :spec
|
56
|
+
|
57
|
+
require 'yard'
|
58
|
+
YARD::Rake::YardocTask.new
|
data/bin/imap-filter
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# My Email accounts
|
2
|
+
account :gmx do
|
3
|
+
login ENV['GMX_EMAIL'], ENV['GMX_PASS']
|
4
|
+
serv "imap.gmx.net"
|
5
|
+
ssl true
|
6
|
+
auth :login
|
7
|
+
port 993
|
8
|
+
end
|
9
|
+
|
10
|
+
account :yahoo do
|
11
|
+
login ENV['YAHOO_EMAIL'], ENV['YAHOO_PASS']
|
12
|
+
serv 'imap.mail.yahoo.com'
|
13
|
+
auth :login
|
14
|
+
end
|
15
|
+
|
16
|
+
account :google do
|
17
|
+
login ENV['GOOGLE_EMAIL'], ENV['GOOGLE_PASS']
|
18
|
+
serv "imap.gmail.com"
|
19
|
+
auth :plain
|
20
|
+
end
|
21
|
+
|
22
|
+
filter :slashdot, 'gmx:INBOX', from: 'slashdot' do
|
23
|
+
mark :seen
|
24
|
+
cp 'google:INBOX'
|
25
|
+
mv 'gmx:Slashdot'
|
26
|
+
end
|
27
|
+
|
28
|
+
filter :github, 'gmx:INBOX' do
|
29
|
+
search do
|
30
|
+
from 'github.com'
|
31
|
+
unseen
|
32
|
+
end
|
33
|
+
|
34
|
+
cp 'google:news/Github'
|
35
|
+
mv 'gmx:Github'
|
36
|
+
end
|
37
|
+
|
38
|
+
filter :gitter, 'gmx:INBOX', from: 'gitter' do
|
39
|
+
mv 'gmx:Gitter'
|
40
|
+
end
|
41
|
+
|
42
|
+
filter :xing, 'gmx:INBOX', from: 'xing.com' do
|
43
|
+
mv 'gmx:XING'
|
44
|
+
unmark :seen
|
45
|
+
end
|
46
|
+
|
47
|
+
filter :neat, 'yahoo:NEAT', :unseen do
|
48
|
+
cp 'gmx:Lists/NEAT'
|
49
|
+
mark :seen
|
50
|
+
end
|
51
|
+
|
52
|
+
filter :spam, 'gmx:INBOX', from: ['news.brgmedia.com', 'travel.hoteltravel-email.com'] do
|
53
|
+
delete
|
54
|
+
end
|
55
|
+
|
56
|
+
activate :all
|
data/imap-filter.gemspec
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Generated by juwelier
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: imap-filter 0.0.2 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "imap-filter"
|
9
|
+
s.version = "0.0.2"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Fred Mitchell"]
|
14
|
+
s.date = "2016-09-25"
|
15
|
+
s.description = "\n imap-filter is a Ruby implementation of an IMAP filtering application.\n it can handle multiple IMAP accounts, and create IMAP folders automatically\n where none exists.\n\n The imap-filter DSL makes it easy to filter. You can also do \"dry-runs\"\n to make sure what happens is what is expected."
|
16
|
+
s.email = "fred.mitchell@gmx.de"
|
17
|
+
s.executables = ["imap-filter"]
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE.txt",
|
20
|
+
"README.org"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".rspec",
|
25
|
+
".ruby-version",
|
26
|
+
".semver",
|
27
|
+
"Gemfile",
|
28
|
+
"Gemfile.lock",
|
29
|
+
"LICENSE.txt",
|
30
|
+
"README.org",
|
31
|
+
"Rakefile",
|
32
|
+
"bin/imap-filter",
|
33
|
+
"examples/default.imap",
|
34
|
+
"imap-filter.gemspec",
|
35
|
+
"lib/imap-filter.rb",
|
36
|
+
"lib/imap-filter/cli.rb",
|
37
|
+
"lib/imap-filter/dsl.rb",
|
38
|
+
"lib/imap-filter/functionality.rb",
|
39
|
+
"lib/imap-filter/imap-filter.rb",
|
40
|
+
"lib/imap-filter/monkeypatches.rb",
|
41
|
+
"spec/imap-filter_spec.rb",
|
42
|
+
"spec/spec_helper.rb"
|
43
|
+
]
|
44
|
+
s.homepage = "http://github.com/flajann2/imap-filter"
|
45
|
+
s.licenses = ["MIT"]
|
46
|
+
s.required_ruby_version = Gem::Requirement.new(">= 2.2")
|
47
|
+
s.rubygems_version = "2.5.1"
|
48
|
+
s.summary = "IMAP Scriptable filter for one or multiple Email accounts."
|
49
|
+
|
50
|
+
if s.respond_to? :specification_version then
|
51
|
+
s.specification_version = 4
|
52
|
+
|
53
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
+
s.add_runtime_dependency(%q<semver>, ["~> 1"])
|
55
|
+
s.add_runtime_dependency(%q<awesome_print>, ["~> 1"])
|
56
|
+
s.add_runtime_dependency(%q<text-table>, ["~> 1"])
|
57
|
+
s.add_runtime_dependency(%q<thor>, ["~> 0"])
|
58
|
+
s.add_runtime_dependency(%q<colorize>, ["~> 0"])
|
59
|
+
s.add_development_dependency(%q<rspec>, ["~> 2"])
|
60
|
+
s.add_development_dependency(%q<yard>, ["~> 0"])
|
61
|
+
s.add_development_dependency(%q<rdoc>, ["~> 3"])
|
62
|
+
s.add_development_dependency(%q<bundler>, ["~> 1"])
|
63
|
+
s.add_development_dependency(%q<juwelier>, ["~> 2"])
|
64
|
+
s.add_development_dependency(%q<simplecov>, ["~> 0"])
|
65
|
+
s.add_development_dependency(%q<pry>, ["~> 0"])
|
66
|
+
s.add_development_dependency(%q<pry-byebug>, ["~> 3"])
|
67
|
+
s.add_development_dependency(%q<pry-doc>, ["~> 0"])
|
68
|
+
s.add_development_dependency(%q<pry-remote>, ["~> 0"])
|
69
|
+
s.add_development_dependency(%q<pry-rescue>, ["~> 1"])
|
70
|
+
s.add_development_dependency(%q<pry-stack_explorer>, ["~> 0"])
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<semver>, ["~> 1"])
|
73
|
+
s.add_dependency(%q<awesome_print>, ["~> 1"])
|
74
|
+
s.add_dependency(%q<text-table>, ["~> 1"])
|
75
|
+
s.add_dependency(%q<thor>, ["~> 0"])
|
76
|
+
s.add_dependency(%q<colorize>, ["~> 0"])
|
77
|
+
s.add_dependency(%q<rspec>, ["~> 2"])
|
78
|
+
s.add_dependency(%q<yard>, ["~> 0"])
|
79
|
+
s.add_dependency(%q<rdoc>, ["~> 3"])
|
80
|
+
s.add_dependency(%q<bundler>, ["~> 1"])
|
81
|
+
s.add_dependency(%q<juwelier>, ["~> 2"])
|
82
|
+
s.add_dependency(%q<simplecov>, ["~> 0"])
|
83
|
+
s.add_dependency(%q<pry>, ["~> 0"])
|
84
|
+
s.add_dependency(%q<pry-byebug>, ["~> 3"])
|
85
|
+
s.add_dependency(%q<pry-doc>, ["~> 0"])
|
86
|
+
s.add_dependency(%q<pry-remote>, ["~> 0"])
|
87
|
+
s.add_dependency(%q<pry-rescue>, ["~> 1"])
|
88
|
+
s.add_dependency(%q<pry-stack_explorer>, ["~> 0"])
|
89
|
+
end
|
90
|
+
else
|
91
|
+
s.add_dependency(%q<semver>, ["~> 1"])
|
92
|
+
s.add_dependency(%q<awesome_print>, ["~> 1"])
|
93
|
+
s.add_dependency(%q<text-table>, ["~> 1"])
|
94
|
+
s.add_dependency(%q<thor>, ["~> 0"])
|
95
|
+
s.add_dependency(%q<colorize>, ["~> 0"])
|
96
|
+
s.add_dependency(%q<rspec>, ["~> 2"])
|
97
|
+
s.add_dependency(%q<yard>, ["~> 0"])
|
98
|
+
s.add_dependency(%q<rdoc>, ["~> 3"])
|
99
|
+
s.add_dependency(%q<bundler>, ["~> 1"])
|
100
|
+
s.add_dependency(%q<juwelier>, ["~> 2"])
|
101
|
+
s.add_dependency(%q<simplecov>, ["~> 0"])
|
102
|
+
s.add_dependency(%q<pry>, ["~> 0"])
|
103
|
+
s.add_dependency(%q<pry-byebug>, ["~> 3"])
|
104
|
+
s.add_dependency(%q<pry-doc>, ["~> 0"])
|
105
|
+
s.add_dependency(%q<pry-remote>, ["~> 0"])
|
106
|
+
s.add_dependency(%q<pry-rescue>, ["~> 1"])
|
107
|
+
s.add_dependency(%q<pry-stack_explorer>, ["~> 0"])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
data/lib/imap-filter.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'semver'
|
3
|
+
require 'pp'
|
4
|
+
require 'ap'
|
5
|
+
require 'colorize'
|
6
|
+
require 'awesome_print'
|
7
|
+
require 'net/imap'
|
8
|
+
require 'forwardable'
|
9
|
+
|
10
|
+
module ImapFilter
|
11
|
+
end
|
12
|
+
|
13
|
+
require_relative 'imap-filter/monkeypatches'
|
14
|
+
require_relative 'imap-filter/dsl'
|
15
|
+
require_relative 'imap-filter/functionality'
|
16
|
+
require_relative 'imap-filter/imap-filter'
|
17
|
+
require_relative 'imap-filter/cli'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'imap-filter'
|
3
|
+
|
4
|
+
include ImapFilter::DSL
|
5
|
+
|
6
|
+
module ImapFilter
|
7
|
+
module Cli
|
8
|
+
class Main < Thor
|
9
|
+
class_option :verbose, type: :numeric, banner: '[1|2|3|4]', aliases: '-v', default: 0
|
10
|
+
@@default_script = ENV['IMAPF_IMAP_FILE'] || 'default.imap'
|
11
|
+
|
12
|
+
desc 'filter [script]', "Run the powerplay script. Default #{@@default_script}"
|
13
|
+
option :dryrun, type: :boolean, aliases: '-u', desc: "Dry run, do not actually execute."
|
14
|
+
option :test, type: :boolean, aliases: '-t', desc: "Test IMAP accounts only."
|
15
|
+
option :filters, type: :array, aliases: '-f', banner: %(<FILT1>[ FILT2 FILT3...]),
|
16
|
+
desc: "Run specified filters. The default is to run all of them."
|
17
|
+
def filter(script = @@default_script)
|
18
|
+
_global[:options] = options
|
19
|
+
puts "script %s " % [script] if _options[:verbose] >= 1
|
20
|
+
load script, true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'imap-filter'
|
3
|
+
|
4
|
+
module ImapFilter
|
5
|
+
module DSL
|
6
|
+
@@global_config = {}
|
7
|
+
|
8
|
+
def _global
|
9
|
+
@@global_config
|
10
|
+
end
|
11
|
+
|
12
|
+
def _options
|
13
|
+
DSL::_global[:options]
|
14
|
+
end
|
15
|
+
|
16
|
+
def _accounts
|
17
|
+
DSL::_global[:accounts] ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def _filters
|
21
|
+
DSL::_global[:filters] ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
class Dsl
|
25
|
+
attr :name, :desc
|
26
|
+
|
27
|
+
def initialize(name, desc=nil, &ignore)
|
28
|
+
@name = name
|
29
|
+
@desc = desc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Account < Dsl
|
34
|
+
attr :name, :userid, :pass, :fqdn, :use_ssl, :use_port, :auth_type
|
35
|
+
attr :imap, :delim
|
36
|
+
|
37
|
+
def login userid, password
|
38
|
+
@userid = userid
|
39
|
+
@pass = password
|
40
|
+
@use_ssl = true
|
41
|
+
@use_port = nil
|
42
|
+
@auth_type = 'PLAIN'
|
43
|
+
end
|
44
|
+
|
45
|
+
def serv fqdn
|
46
|
+
@fqdn = fqdn
|
47
|
+
end
|
48
|
+
|
49
|
+
def ssl t
|
50
|
+
@use_ssl = t
|
51
|
+
end
|
52
|
+
|
53
|
+
def port p
|
54
|
+
@use_port = p
|
55
|
+
end
|
56
|
+
|
57
|
+
def auth type
|
58
|
+
@auth_type = type.to_s.upcase
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(name, &block)
|
62
|
+
super
|
63
|
+
@name = name
|
64
|
+
instance_eval( &block )
|
65
|
+
_accounts[name] = self
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
"SERV #{fqdn} USER #{userid} SSL #{use_ssl} PORT #{ use_port ? use_port : '<default>'} AUTH #{auth_type} >DELIM #{delim}"
|
70
|
+
end
|
71
|
+
|
72
|
+
# connects and logs in
|
73
|
+
def _open_connection
|
74
|
+
print "\n *** connect #{fqdn} port '#{use_port}' ssl #{use_ssl}".light_cyan unless _options[:verbose] < 2
|
75
|
+
unless use_port.nil?
|
76
|
+
@imap = Net::IMAP.new(fqdn, port: use_port, ssl: use_ssl)
|
77
|
+
else
|
78
|
+
@imap = Net::IMAP.new(fqdn, ssl: use_ssl)
|
79
|
+
end
|
80
|
+
|
81
|
+
print "\n *** auth #{userid} pass #{pass}...".light_cyan unless _options[:verbose] < 2
|
82
|
+
imap.authenticate(auth_type, userid, pass)
|
83
|
+
@delim = imap.list('', '').first.delim
|
84
|
+
end
|
85
|
+
|
86
|
+
def _close_connection
|
87
|
+
imap.close
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Filter < Dsl
|
92
|
+
attr :mbox, :directives, :actions
|
93
|
+
OPS = [:or, :not, :new]
|
94
|
+
MARKS = {
|
95
|
+
seen: :Seen,
|
96
|
+
read: :Seen,
|
97
|
+
unread: :Unseen,
|
98
|
+
unseen: :Unseen,
|
99
|
+
deleted: :Deleted,
|
100
|
+
flagged: :Flagged
|
101
|
+
}
|
102
|
+
DIRECTIVES = {
|
103
|
+
all: 'ALL',
|
104
|
+
new: 'NEW',
|
105
|
+
recent: 'RECENT',
|
106
|
+
seen: 'SEEN',
|
107
|
+
read: 'SEEN',
|
108
|
+
unseen: 'UNSEEN',
|
109
|
+
unread: 'UNSEEN',
|
110
|
+
answered: 'ANSWERED',
|
111
|
+
unanswered: 'UNANSWERED',
|
112
|
+
deleted: 'DELETED',
|
113
|
+
undeleted: 'UNDELETED',
|
114
|
+
draft: 'DRAFT',
|
115
|
+
undraft: 'UNDRAFT',
|
116
|
+
flagged: 'FLAGGED',
|
117
|
+
unflagged: 'UNFLAGGED',
|
118
|
+
}
|
119
|
+
|
120
|
+
def list *a, **h
|
121
|
+
@actions << [:list, a, h]
|
122
|
+
end
|
123
|
+
|
124
|
+
def move to_mbox
|
125
|
+
@actions << [:move, to_mbox]
|
126
|
+
end
|
127
|
+
alias mv move
|
128
|
+
|
129
|
+
def copy to_mbox
|
130
|
+
@actions << [:copy, to_mbox]
|
131
|
+
end
|
132
|
+
alias cp copy
|
133
|
+
|
134
|
+
def delete
|
135
|
+
@actions << [:delete]
|
136
|
+
end
|
137
|
+
|
138
|
+
def mark *flags, custom: false
|
139
|
+
flags.each do |f|
|
140
|
+
raise "Illegal flag #{f}" unless MARKS.member? f
|
141
|
+
end unless custom
|
142
|
+
@actions << [:mark] + flags.map{ |f| MARKS[f] || f }
|
143
|
+
end
|
144
|
+
alias store mark
|
145
|
+
|
146
|
+
def unmark *flags, custom: false
|
147
|
+
flags.each do |f|
|
148
|
+
raise "Illegal flag #{f}" unless MARKS.member? f
|
149
|
+
end unless custom
|
150
|
+
@actions << [:unmark] + flags.map{ |f| MARKS[f] || f }
|
151
|
+
end
|
152
|
+
alias unstore unmark
|
153
|
+
|
154
|
+
def search &block
|
155
|
+
def before d
|
156
|
+
directives << 'BEFORE' << d
|
157
|
+
end
|
158
|
+
|
159
|
+
def body s
|
160
|
+
directives << 'BODY'<< s
|
161
|
+
end
|
162
|
+
|
163
|
+
def cc s
|
164
|
+
directives << 'CC' << s
|
165
|
+
end
|
166
|
+
|
167
|
+
def bcc s
|
168
|
+
directives << 'BCC' << s
|
169
|
+
end
|
170
|
+
|
171
|
+
def from s
|
172
|
+
directives << 'FROM' << s
|
173
|
+
end
|
174
|
+
|
175
|
+
def op *a
|
176
|
+
a.each { |x|
|
177
|
+
raise "illegal operator #{x}" unless OPS.member? x
|
178
|
+
directives << x.to_s.upcase
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
def on d
|
183
|
+
directives << 'ON' << d
|
184
|
+
end
|
185
|
+
|
186
|
+
def since d
|
187
|
+
directives << 'SINCE' << d
|
188
|
+
end
|
189
|
+
|
190
|
+
def senton d
|
191
|
+
directives << 'SENTON' << d
|
192
|
+
end
|
193
|
+
|
194
|
+
def sentsince d
|
195
|
+
directives << 'SENTSINCE' << d
|
196
|
+
end
|
197
|
+
|
198
|
+
def sentbefore d
|
199
|
+
directives << 'SENTBEFORE' << d
|
200
|
+
end
|
201
|
+
|
202
|
+
def smaller n
|
203
|
+
directives << 'SMALLER' << n
|
204
|
+
end
|
205
|
+
|
206
|
+
def subject s
|
207
|
+
directives << 'SUBJECT' << s
|
208
|
+
end
|
209
|
+
|
210
|
+
def text s
|
211
|
+
directives << 'TEXT' << s
|
212
|
+
end
|
213
|
+
|
214
|
+
def to s
|
215
|
+
directives << 'TO' << s
|
216
|
+
end
|
217
|
+
|
218
|
+
def all
|
219
|
+
directives << 'ALL'
|
220
|
+
end
|
221
|
+
|
222
|
+
def answered
|
223
|
+
directives << 'ANSWERED'
|
224
|
+
end
|
225
|
+
|
226
|
+
def unanswered
|
227
|
+
directives << 'UNANSWERED'
|
228
|
+
end
|
229
|
+
|
230
|
+
def deleted
|
231
|
+
directives << 'DELETED'
|
232
|
+
end
|
233
|
+
|
234
|
+
def undeleted
|
235
|
+
directives << 'UNDELETED'
|
236
|
+
end
|
237
|
+
|
238
|
+
def draft
|
239
|
+
directives << 'DRAFT'
|
240
|
+
end
|
241
|
+
|
242
|
+
def undraft
|
243
|
+
directives << 'UNDRAFT'
|
244
|
+
end
|
245
|
+
|
246
|
+
def flagged
|
247
|
+
directives << 'FLAGGED'
|
248
|
+
end
|
249
|
+
|
250
|
+
def unflagged
|
251
|
+
directives << 'UNFLAGGED'
|
252
|
+
end
|
253
|
+
|
254
|
+
def seen
|
255
|
+
directives << 'SEEN'
|
256
|
+
end
|
257
|
+
alias red seen
|
258
|
+
|
259
|
+
def unseen
|
260
|
+
directives << 'UNSEEN'
|
261
|
+
end
|
262
|
+
alias unread unseen
|
263
|
+
|
264
|
+
def keyword key
|
265
|
+
directives << 'KEYWORD' << key
|
266
|
+
end
|
267
|
+
|
268
|
+
def unkeyword key
|
269
|
+
directives << 'UNKEYWORD' << key
|
270
|
+
end
|
271
|
+
|
272
|
+
instance_eval &block
|
273
|
+
end
|
274
|
+
|
275
|
+
def massage directives
|
276
|
+
if directives.is_a?(Hash)
|
277
|
+
directives.map{ |k, v|
|
278
|
+
unless v.is_a? Array
|
279
|
+
[k.to_s.upcase, v]
|
280
|
+
else
|
281
|
+
['OR',
|
282
|
+
v.map{ |va|
|
283
|
+
[k.to_s.upcase, va]
|
284
|
+
}].flatten
|
285
|
+
end
|
286
|
+
}.flatten
|
287
|
+
elsif directives.is_a?(Symbol)
|
288
|
+
DIRECTIVES[directives]
|
289
|
+
else
|
290
|
+
directives
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# note that directives can be either a hash or a single symbol
|
295
|
+
def initialize(name, mbox, directives=[], &block)
|
296
|
+
super(name)
|
297
|
+
@mbox = mbox
|
298
|
+
@directives = massage directives
|
299
|
+
@actions = []
|
300
|
+
instance_eval &block
|
301
|
+
_filters[name] = self
|
302
|
+
end
|
303
|
+
|
304
|
+
def to_s
|
305
|
+
"MBOX #{mbox} DIRECTIVES #{directives}"
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def account name, &block
|
310
|
+
Account.new name, &block
|
311
|
+
end
|
312
|
+
|
313
|
+
def filter name, mbox, singledir=nil, **directives, &block
|
314
|
+
Filter.new name, mbox, (singledir || directives), &block
|
315
|
+
end
|
316
|
+
|
317
|
+
def activate filters
|
318
|
+
Functionality.run_filters filters
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|