gitlab-mail_room 0.0.10 → 0.0.19
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 +4 -4
- data/.gitlab/issue_templates/Release.md +1 -0
- data/.gitlab-ci.yml +11 -21
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +501 -0
- data/.ruby-version +1 -1
- data/.travis.yml +9 -3
- data/CHANGELOG.md +4 -0
- data/CONTRIBUTING.md +40 -0
- data/README.md +99 -9
- data/Rakefile +1 -1
- data/lib/mail_room/arbitration/redis.rb +1 -1
- data/lib/mail_room/connection.rb +6 -1
- data/lib/mail_room/delivery/letter_opener.rb +1 -1
- data/lib/mail_room/delivery/postback.rb +36 -4
- data/lib/mail_room/delivery/sidekiq.rb +4 -3
- data/lib/mail_room/jwt.rb +39 -0
- data/lib/mail_room/mailbox.rb +56 -17
- data/lib/mail_room/mailbox_watcher.rb +7 -1
- data/lib/mail_room/microsoft_graph/connection.rb +232 -0
- data/lib/mail_room/microsoft_graph.rb +7 -0
- data/lib/mail_room/version.rb +1 -1
- data/mail_room.gemspec +8 -1
- data/spec/fixtures/jwt_secret +1 -0
- data/spec/lib/arbitration/redis_spec.rb +6 -5
- data/spec/lib/cli_spec.rb +3 -3
- data/spec/lib/configuration_spec.rb +1 -1
- data/spec/lib/delivery/letter_opener_spec.rb +2 -2
- data/spec/lib/delivery/logger_spec.rb +1 -1
- data/spec/lib/delivery/postback_spec.rb +62 -14
- data/spec/lib/delivery/sidekiq_spec.rb +34 -11
- data/spec/lib/jwt_spec.rb +80 -0
- data/spec/lib/mailbox_spec.rb +65 -17
- data/spec/lib/mailbox_watcher_spec.rb +54 -38
- data/spec/lib/microsoft_graph/connection_spec.rb +221 -0
- data/spec/spec_helper.rb +13 -3
- metadata +87 -5
data/spec/lib/mailbox_spec.rb
CHANGED
@@ -3,12 +3,23 @@ require 'spec_helper'
|
|
3
3
|
describe MailRoom::Mailbox do
|
4
4
|
let(:sample_message) { MailRoom::Message.new(uid: 123, body: 'a message') }
|
5
5
|
|
6
|
+
context 'with IMAP configuration' do
|
7
|
+
subject { build_mailbox }
|
8
|
+
|
9
|
+
describe '#imap?' do
|
10
|
+
it 'configured as an IMAP inbox' do
|
11
|
+
expect(subject.imap?).to be true
|
12
|
+
expect(subject.microsoft_graph?).to be false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
6
17
|
describe "#deliver" do
|
7
18
|
context "with arbitration_method of noop" do
|
8
19
|
it 'arbitrates with a Noop instance' do
|
9
|
-
mailbox = build_mailbox({:
|
20
|
+
mailbox = build_mailbox({arbitration_method: 'noop'})
|
10
21
|
noop = stub(:deliver?)
|
11
|
-
MailRoom::Arbitration['noop'].stubs(:
|
22
|
+
MailRoom::Arbitration['noop'].stubs(new: noop)
|
12
23
|
|
13
24
|
uid = 123
|
14
25
|
|
@@ -20,9 +31,9 @@ describe MailRoom::Mailbox do
|
|
20
31
|
|
21
32
|
context "with arbitration_method of redis" do
|
22
33
|
it 'arbitrates with a Redis instance' do
|
23
|
-
mailbox = build_mailbox({:
|
34
|
+
mailbox = build_mailbox({arbitration_method: 'redis'})
|
24
35
|
redis = stub(:deliver?)
|
25
|
-
MailRoom::Arbitration['redis'].stubs(:
|
36
|
+
MailRoom::Arbitration['redis'].stubs(new: redis)
|
26
37
|
uid = 123
|
27
38
|
redis.expects(:deliver?).with(uid)
|
28
39
|
|
@@ -32,9 +43,9 @@ describe MailRoom::Mailbox do
|
|
32
43
|
|
33
44
|
context "with delivery_method of noop" do
|
34
45
|
it 'delivers with a Noop instance' do
|
35
|
-
mailbox = build_mailbox({:
|
46
|
+
mailbox = build_mailbox({delivery_method: 'noop'})
|
36
47
|
noop = stub(:deliver)
|
37
|
-
MailRoom::Delivery['noop'].stubs(:
|
48
|
+
MailRoom::Delivery['noop'].stubs(new: noop)
|
38
49
|
|
39
50
|
noop.expects(:deliver).with(sample_message.body)
|
40
51
|
|
@@ -44,9 +55,9 @@ describe MailRoom::Mailbox do
|
|
44
55
|
|
45
56
|
context "with delivery_method of logger" do
|
46
57
|
it 'delivers with a Logger instance' do
|
47
|
-
mailbox = build_mailbox({:
|
58
|
+
mailbox = build_mailbox({delivery_method: 'logger'})
|
48
59
|
logger = stub(:deliver)
|
49
|
-
MailRoom::Delivery['logger'].stubs(:
|
60
|
+
MailRoom::Delivery['logger'].stubs(new: logger)
|
50
61
|
|
51
62
|
logger.expects(:deliver).with(sample_message.body)
|
52
63
|
|
@@ -56,9 +67,9 @@ describe MailRoom::Mailbox do
|
|
56
67
|
|
57
68
|
context "with delivery_method of postback" do
|
58
69
|
it 'delivers with a Postback instance' do
|
59
|
-
mailbox = build_mailbox({:
|
70
|
+
mailbox = build_mailbox({delivery_method: 'postback'})
|
60
71
|
postback = stub(:deliver)
|
61
|
-
MailRoom::Delivery['postback'].stubs(:
|
72
|
+
MailRoom::Delivery['postback'].stubs(new: postback)
|
62
73
|
|
63
74
|
postback.expects(:deliver).with(sample_message.body)
|
64
75
|
|
@@ -68,9 +79,9 @@ describe MailRoom::Mailbox do
|
|
68
79
|
|
69
80
|
context "with delivery_method of letter_opener" do
|
70
81
|
it 'delivers with a LetterOpener instance' do
|
71
|
-
mailbox = build_mailbox({:
|
82
|
+
mailbox = build_mailbox({delivery_method: 'letter_opener'})
|
72
83
|
letter_opener = stub(:deliver)
|
73
|
-
MailRoom::Delivery['letter_opener'].stubs(:
|
84
|
+
MailRoom::Delivery['letter_opener'].stubs(new: letter_opener)
|
74
85
|
|
75
86
|
letter_opener.expects(:deliver).with(sample_message.body)
|
76
87
|
|
@@ -82,7 +93,7 @@ describe MailRoom::Mailbox do
|
|
82
93
|
it "doesn't deliver the message" do
|
83
94
|
mailbox = build_mailbox({ name: "magic mailbox", delivery_method: 'noop' })
|
84
95
|
noop = stub(:deliver)
|
85
|
-
MailRoom::Delivery['noop'].stubs(:
|
96
|
+
MailRoom::Delivery['noop'].stubs(new: noop)
|
86
97
|
noop.expects(:deliver).never
|
87
98
|
|
88
99
|
mailbox.deliver(MailRoom::Message.new(uid: 1234, body: nil))
|
@@ -91,9 +102,9 @@ describe MailRoom::Mailbox do
|
|
91
102
|
|
92
103
|
context "with ssl options hash" do
|
93
104
|
it 'replaces verify mode with constant' do
|
94
|
-
mailbox = build_mailbox({:
|
105
|
+
mailbox = build_mailbox({ssl: {verify_mode: :none}})
|
95
106
|
|
96
|
-
expect(mailbox.ssl_options).to eq({:
|
107
|
+
expect(mailbox.ssl_options).to eq({verify_mode: OpenSSL::SSL::VERIFY_NONE})
|
97
108
|
end
|
98
109
|
end
|
99
110
|
|
@@ -121,8 +132,45 @@ describe MailRoom::Mailbox do
|
|
121
132
|
describe "#validate!" do
|
122
133
|
context "with missing configuration" do
|
123
134
|
it 'raises an error' do
|
124
|
-
expect { build_mailbox({:
|
125
|
-
expect { build_mailbox({:
|
135
|
+
expect { build_mailbox({name: nil}) }.to raise_error(MailRoom::ConfigurationError)
|
136
|
+
expect { build_mailbox({host: nil}) }.to raise_error(MailRoom::ConfigurationError)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context "with Microsoft Graph configuration" do
|
141
|
+
let(:options) do
|
142
|
+
{
|
143
|
+
arbitration_method: 'redis',
|
144
|
+
}.merge(REQUIRED_MICROSOFT_GRAPH_DEFAULTS)
|
145
|
+
end
|
146
|
+
|
147
|
+
subject { build_mailbox(options) }
|
148
|
+
|
149
|
+
def delete_inbox_option(key)
|
150
|
+
options[:inbox_options] = options[:inbox_options].dup.delete(key)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'allows password omission' do
|
154
|
+
expect { subject }.not_to raise_error
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'configured as a Microsoft Graph inbox' do
|
158
|
+
expect(subject.imap?).to be false
|
159
|
+
expect(subject.microsoft_graph?).to be true
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'raises an error when the inbox options are not present' do
|
163
|
+
options.delete(:inbox_options)
|
164
|
+
|
165
|
+
expect { subject }.to raise_error(MailRoom::ConfigurationError)
|
166
|
+
end
|
167
|
+
|
168
|
+
%i[tenant_id client_id client_secret].each do |item|
|
169
|
+
it "raises an error when the #{item} is not present" do
|
170
|
+
delete_inbox_option(item)
|
171
|
+
|
172
|
+
expect { subject }.to raise_error(MailRoom::ConfigurationError)
|
173
|
+
end
|
126
174
|
end
|
127
175
|
end
|
128
176
|
end
|
@@ -1,61 +1,77 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe MailRoom::MailboxWatcher do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
context 'with IMAP configured' do
|
5
|
+
let(:mailbox) {build_mailbox}
|
6
|
+
|
7
|
+
describe '#running?' do
|
8
|
+
it 'is false by default' do
|
9
|
+
watcher = MailRoom::MailboxWatcher.new(mailbox)
|
10
|
+
expect(watcher.running?).to eq(false)
|
11
|
+
end
|
10
12
|
end
|
11
|
-
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
describe '#run' do
|
15
|
+
let(:imap) {stub(login: true, select: true)}
|
16
|
+
let(:watcher) {MailRoom::MailboxWatcher.new(mailbox)}
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
before :each do
|
19
|
+
Net::IMAP.stubs(:new).returns(imap) # prevent connection
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
it 'loops over wait while running' do
|
23
|
+
connection = MailRoom::IMAP::Connection.new(mailbox)
|
23
24
|
|
24
|
-
|
25
|
+
MailRoom::IMAP::Connection.stubs(:new).returns(connection)
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
watcher.expects(:running?).twice.returns(true, false)
|
28
|
+
connection.expects(:wait).once
|
29
|
+
connection.expects(:on_new_message).once
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
watcher.run
|
32
|
+
watcher.watching_thread.join # wait for finishing run
|
33
|
+
end
|
32
34
|
end
|
33
|
-
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
describe '#quit' do
|
37
|
+
let(:imap) {stub(login: true, select: true)}
|
38
|
+
let(:watcher) {MailRoom::MailboxWatcher.new(mailbox)}
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
before :each do
|
41
|
+
Net::IMAP.stubs(:new).returns(imap) # prevent connection
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'closes and waits for the connection' do
|
45
|
+
connection = MailRoom::IMAP::Connection.new(mailbox)
|
46
|
+
connection.stubs(:wait)
|
47
|
+
connection.stubs(:quit)
|
42
48
|
|
43
|
-
|
44
|
-
connection = MailRoom::IMAP::Connection.new(mailbox)
|
45
|
-
connection.stubs(:wait)
|
46
|
-
connection.stubs(:quit)
|
49
|
+
MailRoom::IMAP::Connection.stubs(:new).returns(connection)
|
47
50
|
|
48
|
-
|
51
|
+
watcher.run
|
52
|
+
|
53
|
+
expect(watcher.running?).to eq(true)
|
54
|
+
|
55
|
+
connection.expects(:quit)
|
56
|
+
|
57
|
+
watcher.quit
|
58
|
+
|
59
|
+
expect(watcher.running?).to eq(false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
49
63
|
|
50
|
-
|
64
|
+
context 'with Microsoft Graph configured' do
|
65
|
+
let(:mailbox) { build_mailbox(REQUIRED_MICROSOFT_GRAPH_DEFAULTS) }
|
51
66
|
|
52
|
-
|
67
|
+
subject { described_class.new(mailbox) }
|
53
68
|
|
54
|
-
|
69
|
+
it 'initializes a Microsoft Graph connection' do
|
70
|
+
connection = stub(on_new_message: nil)
|
55
71
|
|
56
|
-
|
72
|
+
MailRoom::MicrosoftGraph::Connection.stubs(:new).returns(connection)
|
57
73
|
|
58
|
-
expect(
|
74
|
+
expect(subject.send(:connection)).to eq(connection)
|
59
75
|
end
|
60
76
|
end
|
61
77
|
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
require 'spec_helper'
|
5
|
+
require 'json'
|
6
|
+
require 'webmock/rspec'
|
7
|
+
|
8
|
+
describe MailRoom::MicrosoftGraph::Connection do
|
9
|
+
let(:tenant_id) { options[:inbox_options][:tenant_id] }
|
10
|
+
let(:options) do
|
11
|
+
{
|
12
|
+
delete_after_delivery: true,
|
13
|
+
expunge_deleted: true
|
14
|
+
}.merge(REQUIRED_MICROSOFT_GRAPH_DEFAULTS)
|
15
|
+
end
|
16
|
+
let(:mailbox) { build_mailbox(options) }
|
17
|
+
let(:base_url) { 'https://graph.microsoft.com/v1.0/users/user@example.com/mailFolders/inbox/messages' }
|
18
|
+
let(:message_base_url) { 'https://graph.microsoft.com/v1.0/users/user@example.com/messages' }
|
19
|
+
|
20
|
+
let(:connection) { described_class.new(mailbox) }
|
21
|
+
let(:uid) { 1 }
|
22
|
+
let(:access_token) { SecureRandom.hex }
|
23
|
+
let(:refresh_token) { SecureRandom.hex }
|
24
|
+
let(:expires_in) { Time.now + 3600 }
|
25
|
+
let(:unread_messages_body) { '' }
|
26
|
+
let(:status) { 200 }
|
27
|
+
let!(:stub_token) do
|
28
|
+
stub_request(:post, "https://login.microsoftonline.com/#{tenant_id}/oauth2/v2.0/token").to_return(
|
29
|
+
body: { 'access_token' => access_token, 'refresh_token' => refresh_token, 'expires_in' => expires_in }.to_json,
|
30
|
+
headers: { 'Content-Type' => 'application/json' }
|
31
|
+
)
|
32
|
+
end
|
33
|
+
let!(:stub_unread_messages_request) do
|
34
|
+
stub_request(:get, "#{base_url}?$filter=isRead%20eq%20false").to_return(
|
35
|
+
status: status,
|
36
|
+
body: unread_messages_body.to_json,
|
37
|
+
headers: { 'Content-Type' => 'application/json' }
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
before do
|
42
|
+
WebMock.enable!
|
43
|
+
end
|
44
|
+
|
45
|
+
context '#quit' do
|
46
|
+
it 'returns false' do
|
47
|
+
expect(connection.stopped?).to be_falsey
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns true' do
|
51
|
+
connection.quit
|
52
|
+
|
53
|
+
expect(connection.stopped?).to be_truthy
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not attempt to process the mailbox' do
|
57
|
+
connection.quit
|
58
|
+
|
59
|
+
connection.expects(:process_mailbox).times(0)
|
60
|
+
connection.wait
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context '#wait' do
|
65
|
+
before do
|
66
|
+
connection.stubs(:do_sleep)
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'poll interval' do
|
70
|
+
it 'defaults to 60 seconds' do
|
71
|
+
expect(connection.send(:poll_interval)).to eq(60)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'calls do_sleep 60 times' do
|
75
|
+
connection.expects(:do_sleep).with(1).times(60)
|
76
|
+
|
77
|
+
connection.wait
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'interval set to 10' do
|
81
|
+
let(:options) do
|
82
|
+
{
|
83
|
+
inbox_method: :microsoft_graph,
|
84
|
+
inbox_options: {
|
85
|
+
tenant_id: '98776',
|
86
|
+
client_id: '12345',
|
87
|
+
client_secret: 'MY-SECRET',
|
88
|
+
poll_interval: '10'
|
89
|
+
}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'sets the poll interval to 10' do
|
94
|
+
expect(connection.send(:poll_interval)).to eq(10)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'calls do_sleep 10 times' do
|
98
|
+
connection.expects(:do_sleep).with(1).times(10)
|
99
|
+
|
100
|
+
connection.wait
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with a single message' do
|
106
|
+
let(:message_id) { SecureRandom.hex }
|
107
|
+
let(:unread_messages_body) { { value: ['id' => message_id] } }
|
108
|
+
let(:message_url) { "#{message_base_url}/#{message_id}" }
|
109
|
+
let(:message_body) { 'hello world' }
|
110
|
+
|
111
|
+
it 'requests message ID' do
|
112
|
+
stub_get = stub_request(:get, "#{message_url}/$value").to_return(
|
113
|
+
status: 200,
|
114
|
+
body: message_body
|
115
|
+
)
|
116
|
+
stub_patch = stub_request(:patch, message_url).with(body: { "isRead": true }.to_json)
|
117
|
+
stub_delete = stub_request(:delete, message_url)
|
118
|
+
message_count = 0
|
119
|
+
|
120
|
+
connection.on_new_message do |message|
|
121
|
+
message_count += 1
|
122
|
+
expect(message.uid).to eq(message_id)
|
123
|
+
expect(message.body).to eq(message_body)
|
124
|
+
end
|
125
|
+
|
126
|
+
connection.wait
|
127
|
+
|
128
|
+
assert_requested(stub_token)
|
129
|
+
assert_requested(stub_unread_messages_request)
|
130
|
+
assert_requested(stub_get)
|
131
|
+
assert_requested(stub_patch)
|
132
|
+
assert_requested(stub_delete)
|
133
|
+
expect(message_count).to eq(1)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context 'with multiple pages of messages' do
|
138
|
+
let(:message_ids) { [SecureRandom.hex, SecureRandom.hex] }
|
139
|
+
let(:next_page_url) { 'https://graph.microsoft.com/v1.0/nextPage' }
|
140
|
+
let(:unread_messages_body) { { value: ['id' => message_ids.first], '@odata.nextLink' => next_page_url } }
|
141
|
+
let(:message_body) { 'hello world' }
|
142
|
+
|
143
|
+
it 'requests message ID' do
|
144
|
+
stub_request(:get, next_page_url).to_return(
|
145
|
+
status: 200,
|
146
|
+
body: { value: ['id' => message_ids[1]] }.to_json
|
147
|
+
)
|
148
|
+
|
149
|
+
stubs = []
|
150
|
+
message_ids.each do |message_id|
|
151
|
+
rfc822_msg_url = "#{message_base_url}/#{message_id}/$value"
|
152
|
+
stubs << stub_request(:get, rfc822_msg_url).to_return(
|
153
|
+
status: 200,
|
154
|
+
body: message_body
|
155
|
+
)
|
156
|
+
|
157
|
+
msg_url = "#{message_base_url}/#{message_id}"
|
158
|
+
stubs << stub_request(:patch, msg_url).with(body: { "isRead": true }.to_json)
|
159
|
+
stubs << stub_request(:delete, msg_url)
|
160
|
+
end
|
161
|
+
|
162
|
+
message_count = 0
|
163
|
+
|
164
|
+
connection.on_new_message do |message|
|
165
|
+
expect(message.uid).to eq(message_ids[message_count])
|
166
|
+
expect(message.body).to eq(message_body)
|
167
|
+
message_count += 1
|
168
|
+
end
|
169
|
+
|
170
|
+
connection.wait
|
171
|
+
|
172
|
+
stubs.each { |stub| assert_requested(stub) }
|
173
|
+
expect(message_count).to eq(2)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
shared_examples 'request backoff' do
|
178
|
+
it 'backs off' do
|
179
|
+
connection.expects(:backoff)
|
180
|
+
|
181
|
+
connection.on_new_message {}
|
182
|
+
connection.wait
|
183
|
+
|
184
|
+
expect(connection.throttled_count).to eq(1)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'too many requests' do
|
189
|
+
let(:status) { 429 }
|
190
|
+
|
191
|
+
it_behaves_like 'request backoff'
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'too much bandwidth' do
|
195
|
+
let(:status) { 509 }
|
196
|
+
|
197
|
+
it_behaves_like 'request backoff'
|
198
|
+
end
|
199
|
+
|
200
|
+
context 'invalid JSON response' do
|
201
|
+
let(:body) { 'this is something' }
|
202
|
+
|
203
|
+
it 'ignores the message and logs a warning' do
|
204
|
+
mailbox.logger.expects(:warn)
|
205
|
+
|
206
|
+
connection.on_new_message {}
|
207
|
+
connection.wait
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
context '500 error' do
|
212
|
+
let(:status) { 500 }
|
213
|
+
|
214
|
+
it 'terminates due to error' do
|
215
|
+
connection.on_new_message {}
|
216
|
+
|
217
|
+
expect { connection.wait }.to raise_error(OAuth2::Error)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -22,11 +22,21 @@ RSpec.configure do |config|
|
|
22
22
|
end
|
23
23
|
|
24
24
|
REQUIRED_MAILBOX_DEFAULTS = {
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
25
|
+
name: "inbox",
|
26
|
+
email: "user@example.com",
|
27
|
+
password: "password123"
|
28
28
|
}
|
29
29
|
|
30
|
+
REQUIRED_MICROSOFT_GRAPH_DEFAULTS = {
|
31
|
+
password: nil,
|
32
|
+
inbox_method: :microsoft_graph,
|
33
|
+
inbox_options: {
|
34
|
+
tenant_id: '98776',
|
35
|
+
client_id: '12345',
|
36
|
+
client_secret: 'MY-SECRET',
|
37
|
+
}.freeze
|
38
|
+
}.freeze
|
39
|
+
|
30
40
|
def build_mailbox(options = {})
|
31
41
|
MailRoom::Mailbox.new(REQUIRED_MAILBOX_DEFAULTS.merge(options))
|
32
42
|
end
|