mail_room 0.5.2 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 836563b572db61eacd01d2363273d998863e9831
4
- data.tar.gz: de0cab71b636b3c7ffe0f08cd021896e403940c3
3
+ metadata.gz: 7e839c7e9c2857c75d399aca74fe627438432c17
4
+ data.tar.gz: 97d5cbe394fbd50ee36814785ce03af51381c1ae
5
5
  SHA512:
6
- metadata.gz: 9648c21785544fab432cedeca09c6c28ffd7d993f7ff90c30c1bb2d893e00517687f233118ae945be43fe1c0123ce7f0b2a0addf78c7b5fb22876fae81718df9
7
- data.tar.gz: 503a0ac11cf7e0dddb4299c608ba5d87a5820419afb08ed8a65aeed6e04c6e56a54133f61239f193c63a8f11384fe91540b16ad7dac2a81cbbad4044e794ef1d
6
+ metadata.gz: 5dfcca4fe8a7323d5207b232a48351bb78cd4df53f8301aa719c198186d08ceb09ca3ce7dd3178af2d80f513f330a52488ba9bad5a6aa079aa9a0b19f649e002
7
+ data.tar.gz: e2ec188a14291548bc1891459e3ce18066109daa8566d584714d26fc2be3bb3fc17a54b17e1925c5758d785d1daa4e8292735a7db17cba04f045c6801b035a02
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## mail_room 0.6.0 ##
2
+
3
+ * Add redis Arbitration to reduce multiple deliveries of the same message when running multiple MailRoom instances on the same inbox
4
+
5
+ *Douwe Maan <@DouweM>*
6
+
1
7
  ## mail_room 0.5.2 ##
2
8
 
3
9
  * Fix Sidekiq delivery method for non-UTF8 email
data/README.md CHANGED
@@ -203,6 +203,34 @@ If you're seeing the error `Please log in via your web browser: https://support.
203
203
 
204
204
  I suggest running with either upstart or init.d. Check out this wiki page for some example scripts for both: https://github.com/tpitale/mail_room/wiki/Init-Scripts-for-Running-mail_room
205
205
 
206
+ ## Arbitration ##
207
+
208
+ When running multiple instances of MailRoom against a single mailbox, to try to prevent delivery of the same message multiple times, we can configure Arbitration using Redis.
209
+
210
+ ```yaml
211
+ :mailboxes:
212
+ -
213
+ :email: "user1@gmail.com"
214
+ :password: "password"
215
+ :name: "inbox"
216
+ :delivery_method: postback
217
+ :delivery_options:
218
+ :delivery_url: "http://localhost:3000/inbox"
219
+ :delivery_token: "abcdefg"
220
+
221
+ :arbitration_method: redis
222
+ :arbitration_options:
223
+ # The Redis server to connect with. Defaults to redis://localhost:6379.
224
+ :redis_url: redis://redis.example.com:6379
225
+ # The Redis namespace to house the Redis keys under. Optional.
226
+ :namespace: mail_room
227
+
228
+ ```
229
+
230
+ **Note:** This will likely never be a _perfect_ system for preventing multiple deliveries of the same message, so I would advise checking the unique `message_id` if you are running in this situation.
231
+
232
+ **Note:** There are other scenarios for preventing duplication of messages at scale that _may_ be more appropriate in your particular setup. One such example is using multiple inboxes in reply-by-email situations. Another is to use labels and configure a different `SEARCH` command for each instance of MailRoom.
233
+
206
234
  ## Contributing ##
207
235
 
208
236
  1. Fork it
data/lib/mail_room.rb CHANGED
@@ -2,16 +2,7 @@ require 'net/imap'
2
2
  require 'optparse'
3
3
  require 'yaml'
4
4
 
5
- # The MailRoom namespace
6
5
  module MailRoom
7
- # The MailRoom Delivery namespace holds any defined delivery methods
8
- # including:
9
- #
10
- # * postback (default)
11
- # * letter_opener
12
- # * logger
13
- # * noop
14
- module Delivery; end
15
6
  end
16
7
 
17
8
  require "mail_room/version"
@@ -0,0 +1,16 @@
1
+ module MailRoom
2
+ module Arbitration
3
+ def [](name)
4
+ require_relative("./arbitration/#{name}")
5
+
6
+ case name
7
+ when "redis"
8
+ Arbitration::Redis
9
+ else
10
+ Arbitration::Noop
11
+ end
12
+ end
13
+
14
+ module_function :[]
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module MailRoom
2
+ module Arbitration
3
+ class Noop
4
+ Options = Class.new do
5
+ def initialize(*)
6
+ super()
7
+ end
8
+ end
9
+
10
+ def initialize(*)
11
+ end
12
+
13
+ def deliver?(*)
14
+ true
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,60 @@
1
+ require "redis"
2
+
3
+ module MailRoom
4
+ module Arbitration
5
+ class Redis
6
+ Options = Struct.new(:redis_url, :namespace) do
7
+ def initialize(mailbox)
8
+ redis_url = mailbox.arbitration_options[:redis_url] || "redis://localhost:6379"
9
+ namespace = mailbox.arbitration_options[:namespace]
10
+
11
+ super(redis_url, namespace)
12
+ end
13
+ end
14
+
15
+ # Expire after 10 minutes so Redis doesn't get filled up with outdated data.
16
+ EXPIRATION = 600
17
+
18
+ attr_accessor :options
19
+
20
+ def initialize(options)
21
+ @options = options
22
+ end
23
+
24
+ def deliver?(uid)
25
+ key = "delivered:#{uid}"
26
+
27
+ incr = nil
28
+ redis.multi do |client|
29
+ # At this point, `incr` is a future, which will get its value after
30
+ # the MULTI command returns.
31
+ incr = client.incr(key)
32
+
33
+ client.expire(key, EXPIRATION)
34
+ end
35
+
36
+ # If INCR returns 1, that means the key didn't exist before, which means
37
+ # we are the first mail_room to try to deliver this message, so we get to.
38
+ # If we get any other value, another mail_room already (tried to) deliver
39
+ # the message, so we don't have to anymore.
40
+ incr.value == 1
41
+ end
42
+
43
+ private
44
+
45
+ def redis
46
+ @redis ||= begin
47
+ redis = ::Redis.new(url: options.redis_url)
48
+
49
+ namespace = options.namespace
50
+ if namespace
51
+ require 'redis/namespace'
52
+ ::Redis::Namespace.new(namespace, redis: redis)
53
+ else
54
+ redis
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,24 @@
1
+ module MailRoom
2
+ module Delivery
3
+ def [](name)
4
+ require_relative("./delivery/#{name}")
5
+
6
+ case name
7
+ when "postback"
8
+ Delivery::Postback
9
+ when "logger"
10
+ Delivery::Logger
11
+ when "letter_opener"
12
+ Delivery::LetterOpener
13
+ when "sidekiq"
14
+ Delivery::Sidekiq
15
+ when "que"
16
+ Delivery::Que
17
+ else
18
+ Delivery::Noop
19
+ end
20
+ end
21
+
22
+ module_function :[]
23
+ end
24
+ end
@@ -1,3 +1,6 @@
1
+ require "mail_room/delivery"
2
+ require "mail_room/arbitration"
3
+
1
4
  module MailRoom
2
5
  # Mailbox Configuration fields
3
6
  MAILBOX_FIELDS = [
@@ -15,7 +18,9 @@ module MailRoom
15
18
  :delivery_url, # for postback
16
19
  :delivery_token, # for postback
17
20
  :location, # for letter_opener
18
- :delivery_options
21
+ :delivery_options,
22
+ :arbitration_method,
23
+ :arbitration_options
19
24
  ]
20
25
 
21
26
  # Holds configuration for each of the email accounts we wish to monitor
@@ -30,45 +35,52 @@ module MailRoom
30
35
  :ssl => true,
31
36
  :start_tls => false,
32
37
  :delete_after_delivery => false,
33
- :delivery_options => {}
38
+ :delivery_options => {},
39
+ :arbitration_method => 'noop',
40
+ :arbitration_options => {}
34
41
  }
35
42
 
36
43
  # Store the configuration and require the appropriate delivery method
37
44
  # @param attributes [Hash] configuration options
38
45
  def initialize(attributes={})
39
46
  super(*DEFAULTS.merge(attributes).values_at(*members))
40
-
41
- require_relative("./delivery/#{(delivery_method)}")
42
47
  end
43
48
 
44
- # move to a mailbox deliverer class?
45
49
  def delivery_klass
46
- case delivery_method
47
- when "noop"
48
- Delivery::Noop
49
- when "logger"
50
- Delivery::Logger
51
- when "letter_opener"
52
- Delivery::LetterOpener
53
- when "sidekiq"
54
- Delivery::Sidekiq
55
- when "que"
56
- Delivery::Que
57
- else
58
- Delivery::Postback
59
- end
50
+ Delivery[delivery_method]
51
+ end
52
+
53
+ def arbitration_klass
54
+ Arbitration[arbitration_method]
55
+ end
56
+
57
+ def delivery
58
+ @delivery ||= delivery_klass.new(parsed_delivery_options)
59
+ end
60
+
61
+ def arbitrator
62
+ @arbitrator ||= arbitration_klass.new(parsed_arbitration_options)
63
+ end
64
+
65
+ def deliver?(uid)
66
+ arbitrator.deliver?(uid)
60
67
  end
61
68
 
62
69
  # deliver the imap email message
63
70
  # @param message [Net::IMAP::FetchData]
64
71
  def deliver(message)
65
- message = message.attr['RFC822']
66
- return true unless message
67
-
68
- delivery_klass.new(parsed_delivery_options).deliver(message)
72
+ body = message.attr['RFC822']
73
+ return true unless body
74
+
75
+ delivery.deliver(body)
69
76
  end
70
77
 
71
78
  private
79
+
80
+ def parsed_arbitration_options
81
+ arbitration_klass::Options.new(self)
82
+ end
83
+
72
84
  def parsed_delivery_options
73
85
  delivery_klass::Options.new(self)
74
86
  end
@@ -14,14 +14,12 @@ module MailRoom
14
14
  def process
15
15
  # return if idling? || !running?
16
16
 
17
- new_messages.each do |msg|
18
- # puts msg.attr['RFC822']
19
-
17
+ new_messages.each do |message|
20
18
  # loop over delivery methods and deliver each
21
- delivered = @mailbox.deliver(msg)
19
+ delivered = @mailbox.deliver(message)
22
20
 
23
21
  if delivered && @mailbox.delete_after_delivery
24
- @imap.store(msg.seqno, "+FLAGS", [Net::IMAP::DELETED])
22
+ @imap.store(message.seqno, "+FLAGS", [Net::IMAP::DELETED])
25
23
  end
26
24
  end
27
25
 
@@ -45,17 +43,17 @@ module MailRoom
45
43
  # search for all new (unseen) message ids
46
44
  # @return [Array<Integer>] message ids
47
45
  def new_message_ids
48
- @imap.search(@mailbox.search_command)
46
+ @imap.uid_search(@mailbox.search_command).select { |uid| @mailbox.deliver?(uid) }
49
47
  end
50
48
 
51
49
  # @private
52
50
  # fetch the email for all given ids in RFC822 format
53
51
  # @param ids [Array<Integer>] list of message ids
54
52
  # @return [Array<Net::IMAP::FetchData>] the net/imap messages for the given ids
55
- def messages_for_ids(ids)
56
- return [] if ids.empty?
53
+ def messages_for_ids(uids)
54
+ return [] if uids.empty?
57
55
 
58
- @imap.fetch(ids, "RFC822")
56
+ @imap.uid_fetch(uids, "RFC822")
59
57
  end
60
58
  end
61
59
  end
@@ -1,4 +1,4 @@
1
1
  module MailRoom
2
2
  # Current version of MailRoom gem
3
- VERSION = "0.5.2"
3
+ VERSION = "0.6.0"
4
4
  end
data/mail_room.gemspec CHANGED
@@ -22,12 +22,13 @@ Gem::Specification.new do |gem|
22
22
  gem.add_development_dependency "mocha"
23
23
  gem.add_development_dependency "bourne"
24
24
  gem.add_development_dependency "simplecov"
25
+ gem.add_development_dependency "fakeredis"
25
26
 
26
27
  # for testing delivery methods
27
28
  gem.add_development_dependency "faraday"
28
29
  gem.add_development_dependency "mail"
29
30
  gem.add_development_dependency "letter_opener"
30
- gem.add_development_dependency "redis"
31
+ gem.add_development_dependency "redis-namespace"
31
32
  gem.add_development_dependency "pg"
32
33
  gem.add_development_dependency "charlock_holmes"
33
34
  end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+ require 'mail_room/arbitration/redis'
3
+
4
+ describe MailRoom::Arbitration::Redis do
5
+ let(:mailbox) {
6
+ MailRoom::Mailbox.new(
7
+ arbitration_options: {
8
+ namespace: "mail_room"
9
+ }
10
+ )
11
+ }
12
+ let(:options) { described_class::Options.new(mailbox) }
13
+ subject { described_class.new(options) }
14
+
15
+ # Private, but we don't care.
16
+ let(:redis) { subject.send(:redis) }
17
+
18
+ describe '#deliver?' do
19
+ context "when called the first time" do
20
+ it "returns true" do
21
+ expect(subject.deliver?(123)).to be_truthy
22
+ end
23
+
24
+ it "increments the delivered flag" do
25
+ subject.deliver?(123)
26
+
27
+ expect(redis.get("delivered:123")).to eq("1")
28
+ end
29
+
30
+ it "sets an expiration on the delivered flag" do
31
+ subject.deliver?(123)
32
+
33
+ expect(redis.ttl("delivered:123")).to be > 0
34
+ end
35
+ end
36
+
37
+ context "when called the second time" do
38
+ before do
39
+ subject.deliver?(123)
40
+ end
41
+
42
+ it "returns false" do
43
+ expect(subject.deliver?(123)).to be_falsey
44
+ end
45
+
46
+ it "increments the delivered flag" do
47
+ subject.deliver?(123)
48
+
49
+ expect(redis.get("delivered:123")).to eq("2")
50
+ end
51
+ end
52
+
53
+ context "when called for another uid" do
54
+ before do
55
+ subject.deliver?(123)
56
+ end
57
+
58
+ it "returns true" do
59
+ expect(subject.deliver?(234)).to be_truthy
60
+ end
61
+ end
62
+ end
63
+ end
@@ -6,31 +6,52 @@ describe MailRoom::MailboxHandler do
6
6
  let(:mailbox) {MailRoom::Mailbox.new}
7
7
 
8
8
  it 'fetches and delivers all new messages from ids' do
9
- imap.stubs(:search).returns([1,2])
10
- imap.stubs(:fetch).returns(['message1', 'message2'])
9
+ imap.stubs(:uid_search).returns([1,2])
10
+ message1 = stub(:attr => {'RFC822' => 'message1'})
11
+ message2 = stub(:attr => {'RFC822' => 'message2'})
12
+ imap.stubs(:uid_fetch).returns([message1, message2])
11
13
  mailbox.stubs(:deliver)
12
14
 
13
15
  handler = MailRoom::MailboxHandler.new(mailbox, imap)
14
16
  handler.process
15
17
 
16
- imap.should have_received(:search).with('UNSEEN')
17
- imap.should have_received(:fetch).with([1,2], 'RFC822')
18
- mailbox.should have_received(:deliver).with('message1')
19
- mailbox.should have_received(:deliver).with('message2')
18
+ imap.should have_received(:uid_search).with('UNSEEN')
19
+ imap.should have_received(:uid_fetch).with([1,2], 'RFC822')
20
+ mailbox.should have_received(:deliver).with(message1)
21
+ mailbox.should have_received(:deliver).with(message2)
22
+ end
23
+
24
+ it "fetches and delivers all new messages from ids that haven't been processed yet" do
25
+ imap.stubs(:uid_search).returns([1,2])
26
+ message1 = stub(:attr => {'RFC822' => 'message1'})
27
+ message2 = stub(:attr => {'RFC822' => 'message2'})
28
+ imap.stubs(:uid_fetch).returns([message2])
29
+ mailbox.stubs(:deliver)
30
+ mailbox.stubs(:deliver?).with(1).returns(false)
31
+ mailbox.stubs(:deliver?).with(2).returns(true)
32
+
33
+ handler = MailRoom::MailboxHandler.new(mailbox, imap)
34
+ handler.process
35
+
36
+ imap.should have_received(:uid_search).with('UNSEEN')
37
+ imap.should have_received(:uid_fetch).with([2], 'RFC822')
38
+
39
+ mailbox.should have_received(:deliver).with(message1).never
40
+ mailbox.should have_received(:deliver).with(message2)
20
41
  end
21
42
 
22
43
  it 'returns no messages if there are no ids' do
23
- imap.stubs(:search).returns([])
24
- imap.stubs(:fetch)
44
+ imap.stubs(:uid_search).returns([])
45
+ imap.stubs(:uid_fetch)
25
46
  mailbox.search_command = 'NEW'
26
47
  mailbox.stubs(:deliver)
27
48
 
28
49
  handler = MailRoom::MailboxHandler.new(mailbox, imap)
29
50
  handler.process
30
51
 
31
- imap.should have_received(:search).with('NEW')
32
- imap.should have_received(:fetch).never
52
+ imap.should have_received(:uid_search).with('NEW')
53
+ imap.should have_received(:uid_fetch).never
33
54
  mailbox.should have_received(:deliver).never
34
55
  end
35
56
  end
36
- end
57
+ end
@@ -2,11 +2,39 @@ require 'spec_helper'
2
2
 
3
3
  describe MailRoom::Mailbox do
4
4
  describe "#deliver" do
5
+ context "with arbitration_method of noop" do
6
+ it 'arbitrates with a Noop instance' do
7
+ mailbox = MailRoom::Mailbox.new({:arbitration_method => 'noop'})
8
+ noop = stub(:deliver?)
9
+ MailRoom::Arbitration['noop'].stubs(:new => noop)
10
+
11
+ uid = 123
12
+
13
+ mailbox.deliver?(uid)
14
+
15
+ noop.should have_received(:deliver?).with(uid)
16
+ end
17
+ end
18
+
19
+ context "with arbitration_method of redis" do
20
+ it 'arbitrates with a Redis instance' do
21
+ mailbox = MailRoom::Mailbox.new({:arbitration_method => 'redis'})
22
+ redis = stub(:deliver?)
23
+ MailRoom::Arbitration['redis'].stubs(:new => redis)
24
+
25
+ uid = 123
26
+
27
+ mailbox.deliver?(uid)
28
+
29
+ redis.should have_received(:deliver?).with(uid)
30
+ end
31
+ end
32
+
5
33
  context "with delivery_method of noop" do
6
34
  it 'delivers with a Noop instance' do
7
35
  mailbox = MailRoom::Mailbox.new({:delivery_method => 'noop'})
8
36
  noop = stub(:deliver)
9
- MailRoom::Delivery::Noop.stubs(:new => noop)
37
+ MailRoom::Delivery['noop'].stubs(:new => noop)
10
38
 
11
39
  mailbox.deliver(stub(:attr => {'RFC822' => 'a message'}))
12
40
 
@@ -18,7 +46,7 @@ describe MailRoom::Mailbox do
18
46
  it 'delivers with a Logger instance' do
19
47
  mailbox = MailRoom::Mailbox.new({:delivery_method => 'logger'})
20
48
  logger = stub(:deliver)
21
- MailRoom::Delivery::Logger.stubs(:new => logger)
49
+ MailRoom::Delivery['logger'].stubs(:new => logger)
22
50
 
23
51
  mailbox.deliver(stub(:attr => {'RFC822' => 'a message'}))
24
52
 
@@ -30,7 +58,7 @@ describe MailRoom::Mailbox do
30
58
  it 'delivers with a Postback instance' do
31
59
  mailbox = MailRoom::Mailbox.new({:delivery_method => 'postback'})
32
60
  postback = stub(:deliver)
33
- MailRoom::Delivery::Postback.stubs(:new => postback)
61
+ MailRoom::Delivery['postback'].stubs(:new => postback)
34
62
 
35
63
  mailbox.deliver(stub(:attr => {'RFC822' => 'a message'}))
36
64
 
@@ -42,7 +70,7 @@ describe MailRoom::Mailbox do
42
70
  it 'delivers with a LetterOpener instance' do
43
71
  mailbox = MailRoom::Mailbox.new({:delivery_method => 'letter_opener'})
44
72
  letter_opener = stub(:deliver)
45
- MailRoom::Delivery::LetterOpener.stubs(:new => letter_opener)
73
+ MailRoom::Delivery['letter_opener'].stubs(:new => letter_opener)
46
74
 
47
75
  mailbox.deliver(stub(:attr => {'RFC822' => 'a message'}))
48
76
 
@@ -54,7 +82,7 @@ describe MailRoom::Mailbox do
54
82
  it "doesn't deliver the message" do
55
83
  mailbox = MailRoom::Mailbox.new({:delivery_method => 'noop'})
56
84
  noop = stub(:deliver)
57
- MailRoom::Delivery::Noop.stubs(:new => noop)
85
+ MailRoom::Delivery['noop'].stubs(:new => noop)
58
86
 
59
87
  mailbox.deliver(stub(:attr => {'FLAGS' => [:Seen, :Recent]}))
60
88
 
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ require 'bundler/setup'
6
6
  require 'rspec'
7
7
  require 'mocha/api'
8
8
  require 'bourne'
9
+ require 'fakeredis/rspec'
9
10
 
10
11
  require File.expand_path('../../lib/mail_room', __FILE__)
11
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail_room
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Pitale
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-24 00:00:00.000000000 Z
11
+ date: 2015-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakeredis
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: faraday
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -123,7 +137,7 @@ dependencies:
123
137
  - !ruby/object:Gem::Version
124
138
  version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
- name: redis
140
+ name: redis-namespace
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
143
  - - ">="
@@ -183,9 +197,13 @@ files:
183
197
  - Rakefile
184
198
  - bin/mail_room
185
199
  - lib/mail_room.rb
200
+ - lib/mail_room/arbitration.rb
201
+ - lib/mail_room/arbitration/noop.rb
202
+ - lib/mail_room/arbitration/redis.rb
186
203
  - lib/mail_room/cli.rb
187
204
  - lib/mail_room/configuration.rb
188
205
  - lib/mail_room/coordinator.rb
206
+ - lib/mail_room/delivery.rb
189
207
  - lib/mail_room/delivery/letter_opener.rb
190
208
  - lib/mail_room/delivery/logger.rb
191
209
  - lib/mail_room/delivery/noop.rb
@@ -198,6 +216,7 @@ files:
198
216
  - lib/mail_room/version.rb
199
217
  - mail_room.gemspec
200
218
  - spec/fixtures/test_config.yml
219
+ - spec/lib/arbitration/redis_spec.rb
201
220
  - spec/lib/cli_spec.rb
202
221
  - spec/lib/configuration_spec.rb
203
222
  - spec/lib/coordinator_spec.rb
@@ -235,6 +254,7 @@ summary: mail_room will proxy email (gmail) from IMAP to a callback URL, logger,
235
254
  letter_opener
236
255
  test_files:
237
256
  - spec/fixtures/test_config.yml
257
+ - spec/lib/arbitration/redis_spec.rb
238
258
  - spec/lib/cli_spec.rb
239
259
  - spec/lib/configuration_spec.rb
240
260
  - spec/lib/coordinator_spec.rb