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/README.md
CHANGED
@@ -20,7 +20,14 @@ The fork is useful as we can post quick fixes to our own fork and release fixes
|
|
20
20
|
|
21
21
|
## README
|
22
22
|
|
23
|
-
mail_room is a configuration based process that will
|
23
|
+
mail_room is a configuration based process that will listen for incoming
|
24
|
+
e-mail and execute a delivery method when a new message is
|
25
|
+
received. mail_room supports the following methods for receiving e-mail:
|
26
|
+
|
27
|
+
* IMAP
|
28
|
+
* [Microsoft Graph API](https://docs.microsoft.com/en-us/graph/api/resources/mail-api-overview?view=graph-rest-1.0)
|
29
|
+
|
30
|
+
Examples of delivery methods include:
|
24
31
|
|
25
32
|
* POST to a delivery URL (Postback)
|
26
33
|
* Queue a job to Sidekiq or Que for later processing (Sidekiq or Que)
|
@@ -117,6 +124,31 @@ You will also need to install `faraday` or `letter_opener` if you use the `postb
|
|
117
124
|
:host: 127.0.0.1
|
118
125
|
:port: 26379
|
119
126
|
:worker: EmailReceiverWorker
|
127
|
+
-
|
128
|
+
:email: "user7@outlook365.com"
|
129
|
+
:password: "password"
|
130
|
+
:name: "inbox"
|
131
|
+
:inbox_method: microsoft_graph
|
132
|
+
:inbox_options:
|
133
|
+
:tenant_id: 12345
|
134
|
+
:client_id: ABCDE
|
135
|
+
:client_secret: YOUR-SECRET-HERE
|
136
|
+
:poll_interval: 60
|
137
|
+
:delivery_method: sidekiq
|
138
|
+
:delivery_options:
|
139
|
+
:redis_url: redis://localhost:6379
|
140
|
+
:worker: EmailReceiverWorker
|
141
|
+
-
|
142
|
+
:email: "user8@gmail.com"
|
143
|
+
:password: "password"
|
144
|
+
:name: "inbox"
|
145
|
+
:delivery_method: postback
|
146
|
+
:delivery_options:
|
147
|
+
:delivery_url: "http://localhost:3000/inbox"
|
148
|
+
:jwt_auth_header: "Mailroom-Api-Request"
|
149
|
+
:jwt_issuer: "mailroom"
|
150
|
+
:jwt_algorithm: "HS256"
|
151
|
+
:jwt_secret_path: "/etc/secrets/mailroom/.mailroom_secret"
|
120
152
|
```
|
121
153
|
|
122
154
|
**Note:** If using `delete_after_delivery`, you also probably want to use
|
@@ -134,6 +166,72 @@ the server is running. Otherwise, it returns a 500 status code.
|
|
134
166
|
|
135
167
|
This feature is not included in upstream `mail_room` and is specific to GitLab.
|
136
168
|
|
169
|
+
## inbox_method
|
170
|
+
|
171
|
+
By default, IMAP mode is assumed for reading a mailbox.
|
172
|
+
|
173
|
+
### IMAP Server Configuration ##
|
174
|
+
|
175
|
+
You can set per-mailbox configuration for the IMAP server's `host` (default: 'imap.gmail.com'), `port` (default: 993), `ssl` (default: true), and `start_tls` (default: false).
|
176
|
+
|
177
|
+
If you want to set additional options for IMAP SSL you can pass a YAML hash to match [SSLContext#set_params](http://docs.ruby-lang.org/en/2.2.0/OpenSSL/SSL/SSLContext.html#method-i-set_params). If you set `verify_mode` to `:none` it'll replace with the appropriate constant.
|
178
|
+
|
179
|
+
If you're seeing the error `Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)`, you need to configure your Gmail account to allow less secure apps to access it: https://support.google.com/accounts/answer/6010255.
|
180
|
+
|
181
|
+
### Microsoft Graph configuration
|
182
|
+
|
183
|
+
To use the Microsoft Graph API instead of IMAP to read e-mail, you will
|
184
|
+
need to create an application in the Azure Active Directory. See the
|
185
|
+
[Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details:
|
186
|
+
|
187
|
+
1. Sign in to the [Azure portal](https://portal.azure.com).
|
188
|
+
1. Search for and select `Azure Active Directory`.
|
189
|
+
1. Under `Manage`, select `App registrations` > `New registration`.
|
190
|
+
1. Enter a `Name` for your application, such as `MailRoom`. Users of your app might see this name, and you can change it later.
|
191
|
+
1. If `Supported account types` is listed, select the appropriate option.
|
192
|
+
1. Leave `Redirect URI` blank. This is not needed.
|
193
|
+
1. Select `Register`.
|
194
|
+
1. Under `Manage`, select `Certificates & secrets`.
|
195
|
+
1. Under `Client secrets`, select `New client secret`, and enter a name.
|
196
|
+
1. Under `Expires`, select `Never`, unless you plan on updating the credentials every time it expires.
|
197
|
+
1. Select `Add`. Record the secret value in a safe location for use in a later step.
|
198
|
+
1. Under `Manage`, select `API Permissions` > `Add a permission`. Select `Microsoft Graph`.
|
199
|
+
1. Select `Application permissions`.
|
200
|
+
1. Under the `Mail` node, select `Mail.ReadWrite`, and then select Add permissions.
|
201
|
+
1. If `User.Read` is listed in the permission list, you can delete this.
|
202
|
+
1. Click `Grant admin consent` for these permissions.
|
203
|
+
|
204
|
+
#### Restrict mailbox access
|
205
|
+
|
206
|
+
Note that for MailRoom to work as a service account, this application
|
207
|
+
must have the `Mail.ReadWrite` to read/write mail in *all*
|
208
|
+
mailboxes. However, while this appears to be security risk,
|
209
|
+
we can configure an application access policy to limit the
|
210
|
+
mailbox access for this account. [Follow these instructions](https://docs.microsoft.com/en-us/graph/auth-limit-mailbox-access)
|
211
|
+
to setup PowerShell and configure this policy.
|
212
|
+
|
213
|
+
#### MailRoom config for Microsoft Graph
|
214
|
+
|
215
|
+
In the MailRoom configuration, set `inbox_method` to `microsoft_graph`.
|
216
|
+
You will also need:
|
217
|
+
|
218
|
+
* The client and tenant ID from the `Overview` section in the Azure app page
|
219
|
+
* The client secret created earlier
|
220
|
+
|
221
|
+
Fill in `inbox_options` with these values:
|
222
|
+
|
223
|
+
```yaml
|
224
|
+
:inbox_method: microsoft_graph
|
225
|
+
:inbox_options:
|
226
|
+
:tenant_id: 12345
|
227
|
+
:client_id: ABCDE
|
228
|
+
:client_secret: YOUR-SECRET-HERE
|
229
|
+
:poll_interval: 60
|
230
|
+
```
|
231
|
+
|
232
|
+
By default, MailRoom will poll for new messages every 60 seconds. `poll_interval` configures the number of
|
233
|
+
seconds to poll. Setting the value to 0 or under will default to 60 seconds.
|
234
|
+
|
137
235
|
## delivery_method ##
|
138
236
|
|
139
237
|
### postback ###
|
@@ -284,14 +382,6 @@ If you'd prefer not to wait that long, you can pass `idle_timeout` in seconds fo
|
|
284
382
|
|
285
383
|
This setting allows configuration of the IMAP search command sent to the server. This still defaults 'UNSEEN'. You may find that 'NEW' works better for you.
|
286
384
|
|
287
|
-
## IMAP Server Configuration ##
|
288
|
-
|
289
|
-
You can set per-mailbox configuration for the IMAP server's `host` (default: 'imap.gmail.com'), `port` (default: 993), `ssl` (default: true), and `start_tls` (default: false).
|
290
|
-
|
291
|
-
If you want to set additional options for IMAP SSL you can pass a YAML hash to match [SSLContext#set_params](http://docs.ruby-lang.org/en/2.2.0/OpenSSL/SSL/SSLContext.html#method-i-set_params). If you set `verify_mode` to `:none` it'll replace with the appropriate constant.
|
292
|
-
|
293
|
-
If you're seeing the error `Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)`, you need to configure your Gmail account to allow less secure apps to access it: https://support.google.com/accounts/answer/6010255.
|
294
|
-
|
295
385
|
## Running in Production ##
|
296
386
|
|
297
387
|
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
|
data/Rakefile
CHANGED
@@ -31,7 +31,7 @@ module MailRoom
|
|
31
31
|
# Any subsequent failure in the instance which gets the lock will be dealt
|
32
32
|
# with by the expiration, at which time another instance can pick up the
|
33
33
|
# message and try again.
|
34
|
-
client.set(key, 1,
|
34
|
+
client.set(key, 1, nx: true, ex: expiration)
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
data/lib/mail_room/connection.rb
CHANGED
@@ -6,18 +6,23 @@ module MailRoom
|
|
6
6
|
|
7
7
|
def initialize(mailbox)
|
8
8
|
@mailbox = mailbox
|
9
|
+
@stopped = false
|
9
10
|
end
|
10
11
|
|
11
12
|
def on_new_message(&block)
|
12
13
|
@new_message_handler = block
|
13
14
|
end
|
14
15
|
|
16
|
+
def stopped?
|
17
|
+
@stopped
|
18
|
+
end
|
19
|
+
|
15
20
|
def wait
|
16
21
|
raise NotImplementedError
|
17
22
|
end
|
18
23
|
|
19
24
|
def quit
|
20
|
-
|
25
|
+
@stopped = true
|
21
26
|
end
|
22
27
|
end
|
23
28
|
end
|
@@ -24,7 +24,7 @@ module MailRoom
|
|
24
24
|
# Trigger `LetterOpener` to deliver our message
|
25
25
|
# @param message [String] the email message as a string, RFC822 format
|
26
26
|
def deliver(message)
|
27
|
-
method = ::LetterOpener::DeliveryMethod.new(:
|
27
|
+
method = ::LetterOpener::DeliveryMethod.new(location: @delivery_options.location)
|
28
28
|
method.deliver!(Mail.read_from_string(message))
|
29
29
|
|
30
30
|
true
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'faraday'
|
2
|
+
require "mail_room/jwt"
|
2
3
|
|
3
4
|
module MailRoom
|
4
5
|
module Delivery
|
5
6
|
# Postback Delivery method
|
6
7
|
# @author Tony Pitale
|
7
8
|
class Postback
|
8
|
-
Options = Struct.new(:url, :token, :username, :password, :logger, :content_type) do
|
9
|
+
Options = Struct.new(:url, :token, :username, :password, :logger, :content_type, :jwt) do
|
9
10
|
def initialize(mailbox)
|
10
11
|
url =
|
11
12
|
mailbox.delivery_url ||
|
@@ -17,6 +18,8 @@ module MailRoom
|
|
17
18
|
mailbox.delivery_options[:delivery_token] ||
|
18
19
|
mailbox.delivery_options[:token]
|
19
20
|
|
21
|
+
jwt = initialize_jwt(mailbox.delivery_options)
|
22
|
+
|
20
23
|
username = mailbox.delivery_options[:username]
|
21
24
|
password = mailbox.delivery_options[:password]
|
22
25
|
|
@@ -24,16 +27,31 @@ module MailRoom
|
|
24
27
|
|
25
28
|
content_type = mailbox.delivery_options[:content_type]
|
26
29
|
|
27
|
-
super(url, token, username, password, logger, content_type)
|
30
|
+
super(url, token, username, password, logger, content_type, jwt)
|
28
31
|
end
|
29
32
|
|
30
33
|
def token_auth?
|
31
34
|
!self[:token].nil?
|
32
35
|
end
|
33
36
|
|
37
|
+
def jwt_auth?
|
38
|
+
self[:jwt].valid?
|
39
|
+
end
|
40
|
+
|
34
41
|
def basic_auth?
|
35
42
|
!self[:username].nil? && !self[:password].nil?
|
36
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def initialize_jwt(delivery_options)
|
48
|
+
::MailRoom::JWT.new(
|
49
|
+
header: delivery_options[:jwt_auth_header],
|
50
|
+
secret_path: delivery_options[:jwt_secret_path],
|
51
|
+
algorithm: delivery_options[:jwt_algorithm],
|
52
|
+
issuer: delivery_options[:jwt_issuer]
|
53
|
+
)
|
54
|
+
end
|
37
55
|
end
|
38
56
|
|
39
57
|
# Build a new delivery, hold the delivery options
|
@@ -60,13 +78,27 @@ module MailRoom
|
|
60
78
|
connection.post do |request|
|
61
79
|
request.url @delivery_options.url
|
62
80
|
request.body = message
|
63
|
-
|
64
|
-
request
|
81
|
+
config_request_content_type(request)
|
82
|
+
config_request_jwt_auth(request)
|
65
83
|
end
|
66
84
|
|
67
85
|
@delivery_options.logger.info({ delivery_method: 'Postback', action: 'message pushed', url: @delivery_options.url })
|
68
86
|
true
|
69
87
|
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def config_request_content_type(request)
|
92
|
+
return if @delivery_options.content_type.nil?
|
93
|
+
|
94
|
+
request.headers['Content-Type'] = @delivery_options.content_type
|
95
|
+
end
|
96
|
+
|
97
|
+
def config_request_jwt_auth(request)
|
98
|
+
return unless @delivery_options.jwt_auth?
|
99
|
+
|
100
|
+
request.headers[@delivery_options.jwt.header] = @delivery_options.jwt.token
|
101
|
+
end
|
70
102
|
end
|
71
103
|
end
|
72
104
|
end
|
@@ -8,16 +8,17 @@ module MailRoom
|
|
8
8
|
# Sidekiq Delivery method
|
9
9
|
# @author Douwe Maan
|
10
10
|
class Sidekiq
|
11
|
-
Options = Struct.new(:redis_url, :namespace, :sentinels, :queue, :worker, :logger) do
|
11
|
+
Options = Struct.new(:redis_url, :namespace, :sentinels, :queue, :worker, :logger, :redis_db) do
|
12
12
|
def initialize(mailbox)
|
13
13
|
redis_url = mailbox.delivery_options[:redis_url] || "redis://localhost:6379"
|
14
|
+
redis_db = mailbox.delivery_options[:redis_db] || 0
|
14
15
|
namespace = mailbox.delivery_options[:namespace]
|
15
16
|
sentinels = mailbox.delivery_options[:sentinels]
|
16
17
|
queue = mailbox.delivery_options[:queue] || "default"
|
17
18
|
worker = mailbox.delivery_options[:worker]
|
18
19
|
logger = mailbox.logger
|
19
20
|
|
20
|
-
super(redis_url, namespace, sentinels, queue, worker, logger)
|
21
|
+
super(redis_url, namespace, sentinels, queue, worker, logger, redis_db)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
@@ -45,7 +46,7 @@ module MailRoom
|
|
45
46
|
def client
|
46
47
|
@client ||= begin
|
47
48
|
sentinels = options.sentinels
|
48
|
-
redis_options = { url: options.redis_url }
|
49
|
+
redis_options = { url: options.redis_url, db: options.redis_db }
|
49
50
|
redis_options[:sentinels] = sentinels if sentinels
|
50
51
|
|
51
52
|
redis = ::Redis.new(redis_options)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'securerandom'
|
5
|
+
require 'jwt'
|
6
|
+
require 'base64'
|
7
|
+
|
8
|
+
module MailRoom
|
9
|
+
# Responsible for validating and generating JWT token
|
10
|
+
class JWT
|
11
|
+
DEFAULT_ISSUER = 'mailroom'
|
12
|
+
DEFAULT_ALGORITHM = 'HS256'
|
13
|
+
|
14
|
+
attr_reader :header, :secret_path, :issuer, :algorithm
|
15
|
+
|
16
|
+
def initialize(header:, secret_path:, issuer:, algorithm:)
|
17
|
+
@header = header
|
18
|
+
@secret_path = secret_path
|
19
|
+
@issuer = issuer || DEFAULT_ISSUER
|
20
|
+
@algorithm = algorithm || DEFAULT_ALGORITHM
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid?
|
24
|
+
[@header, @secret_path, @issuer, @algorithm].none?(&:nil?)
|
25
|
+
end
|
26
|
+
|
27
|
+
def token
|
28
|
+
return nil unless valid?
|
29
|
+
|
30
|
+
secret = Base64.strict_decode64(File.read(@secret_path).chomp)
|
31
|
+
payload = {
|
32
|
+
nonce: SecureRandom.hex(12),
|
33
|
+
iat: Time.now.to_i, # https://github.com/jwt/ruby-jwt#issued-at-claim
|
34
|
+
iss: @issuer
|
35
|
+
}
|
36
|
+
::JWT.encode payload, secret, @algorithm
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/mail_room/mailbox.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require "mail_room/delivery"
|
2
2
|
require "mail_room/arbitration"
|
3
3
|
require "mail_room/imap"
|
4
|
+
require "mail_room/microsoft_graph"
|
4
5
|
|
5
6
|
module MailRoom
|
6
7
|
# Mailbox Configuration fields
|
7
8
|
MAILBOX_FIELDS = [
|
8
9
|
:email,
|
10
|
+
:inbox_method,
|
11
|
+
:inbox_options,
|
9
12
|
:password,
|
10
13
|
:host,
|
11
14
|
:port,
|
@@ -42,24 +45,26 @@ module MailRoom
|
|
42
45
|
# 29 minutes, as suggested by the spec: https://tools.ietf.org/html/rfc2177
|
43
46
|
IMAP_IDLE_TIMEOUT = 29 * 60 # 29 minutes in in seconds
|
44
47
|
|
45
|
-
|
48
|
+
IMAP_CONFIGURATION = [:name, :email, :password, :host, :port].freeze
|
49
|
+
MICROSOFT_GRAPH_CONFIGURATION = [:name, :email].freeze
|
50
|
+
MICROSOFT_GRAPH_INBOX_OPTIONS = [:tenant_id, :client_id, :client_secret].freeze
|
46
51
|
|
47
52
|
# Default attributes for the mailbox configuration
|
48
53
|
DEFAULTS = {
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
59
|
-
:
|
60
|
-
:
|
61
|
-
:
|
62
|
-
:
|
54
|
+
search_command: 'UNSEEN',
|
55
|
+
delivery_method: 'postback',
|
56
|
+
host: 'imap.gmail.com',
|
57
|
+
port: 993,
|
58
|
+
ssl: true,
|
59
|
+
start_tls: false,
|
60
|
+
limit_max_unread: 0,
|
61
|
+
idle_timeout: IMAP_IDLE_TIMEOUT,
|
62
|
+
delete_after_delivery: false,
|
63
|
+
expunge_deleted: false,
|
64
|
+
delivery_options: {},
|
65
|
+
arbitration_method: 'noop',
|
66
|
+
arbitration_options: {},
|
67
|
+
logger: {}
|
63
68
|
}
|
64
69
|
|
65
70
|
# Store the configuration and require the appropriate delivery method
|
@@ -122,14 +127,32 @@ module MailRoom
|
|
122
127
|
{ email: self.email, name: self.name }
|
123
128
|
end
|
124
129
|
|
130
|
+
def imap?
|
131
|
+
!microsoft_graph?
|
132
|
+
end
|
133
|
+
|
134
|
+
def microsoft_graph?
|
135
|
+
self[:inbox_method].to_s == 'microsoft_graph'
|
136
|
+
end
|
137
|
+
|
125
138
|
def validate!
|
139
|
+
if microsoft_graph?
|
140
|
+
validate_microsoft_graph!
|
141
|
+
else
|
142
|
+
validate_imap!
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def validate_imap!
|
126
149
|
if self[:idle_timeout] > IMAP_IDLE_TIMEOUT
|
127
150
|
raise IdleTimeoutTooLarge,
|
128
151
|
"Please use an idle timeout smaller than #{29*60} to prevent " \
|
129
152
|
"IMAP server disconnects"
|
130
153
|
end
|
131
154
|
|
132
|
-
|
155
|
+
IMAP_CONFIGURATION.each do |k|
|
133
156
|
if self[k].nil?
|
134
157
|
raise ConfigurationError,
|
135
158
|
"Field :#{k} is required in Mailbox: #{inspect}"
|
@@ -137,7 +160,23 @@ module MailRoom
|
|
137
160
|
end
|
138
161
|
end
|
139
162
|
|
140
|
-
|
163
|
+
def validate_microsoft_graph!
|
164
|
+
raise ConfigurationError, "Missing inbox_options in Mailbox: #{inspect}" unless self.inbox_options.is_a?(Hash)
|
165
|
+
|
166
|
+
MICROSOFT_GRAPH_CONFIGURATION.each do |k|
|
167
|
+
if self[k].nil?
|
168
|
+
raise ConfigurationError,
|
169
|
+
"Field :#{k} is required in Mailbox: #{inspect}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
MICROSOFT_GRAPH_INBOX_OPTIONS.each do |k|
|
174
|
+
if self[:inbox_options][k].nil?
|
175
|
+
raise ConfigurationError,
|
176
|
+
"inbox_options field :#{k} is required in Mailbox: #{inspect}"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
141
180
|
|
142
181
|
def parsed_arbitration_options
|
143
182
|
arbitration_klass::Options.new(self)
|
@@ -62,8 +62,14 @@ module MailRoom
|
|
62
62
|
end
|
63
63
|
|
64
64
|
private
|
65
|
+
|
65
66
|
def connection
|
66
|
-
@connection ||=
|
67
|
+
@connection ||=
|
68
|
+
if @mailbox.microsoft_graph?
|
69
|
+
::MailRoom::MicrosoftGraph::Connection.new(@mailbox)
|
70
|
+
else
|
71
|
+
::MailRoom::IMAP::Connection.new(@mailbox)
|
72
|
+
end
|
67
73
|
end
|
68
74
|
end
|
69
75
|
end
|