mail_room 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/CHANGELOG.md +8 -0
- data/CODE_OF_CONDUCT.md +6 -4
- data/README.md +8 -1
- data/lib/mail_room/backports/imap.rb +33 -0
- data/lib/mail_room/mailbox.rb +41 -0
- data/lib/mail_room/mailbox_watcher.rb +4 -16
- data/lib/mail_room/version.rb +1 -1
- data/lib/mail_room.rb +1 -0
- data/spec/lib/mailbox_spec.rb +8 -0
- data/spec/lib/mailbox_watcher_spec.rb +4 -6
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9feac02c627c54d87da87bc73e1aec3587f43ff3
|
4
|
+
data.tar.gz: 55c2cd20c9e7b7036094c4d46c2efc93567f3e77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29476b7c9e48f064087b59cc869ad6fab364044ca5a8fbf0f8fdb2dadb6a0222cdb07c473f4d82f0b75ccf895c063b56599bb1fd1acfa906309844f85bca3fb8
|
7
|
+
data.tar.gz: 030b4c91c26c545d2103d2d6f7147606bfafa7998c3b31251356b8da4241614260210863c9ef8ce04423ec91f95a381cf23fcdc648fc397368d2d33e5e6039f1
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## mail_room 0.7.0 ##
|
2
|
+
|
3
|
+
* Backports idle timeout from ruby 2.3.0
|
4
|
+
* Sets default to 29 minutes to prevent IMAP disconnects
|
5
|
+
* Validates that the timeout does not exceed 29 minutes
|
6
|
+
|
7
|
+
*Tony Pitale <@tpitale>*
|
8
|
+
|
1
9
|
## mail_room 0.6.1 ##
|
2
10
|
|
3
11
|
* ERB parsing of configuration yml file to enable using ENV variables
|
data/CODE_OF_CONDUCT.md
CHANGED
@@ -11,12 +11,14 @@ Examples of unacceptable behavior by participants include:
|
|
11
11
|
* Trolling or insulting/derogatory comments
|
12
12
|
* Public or private harassment
|
13
13
|
* Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
14
|
-
* Other unethical or unprofessional conduct
|
14
|
+
* Other unethical or unprofessional conduct
|
15
15
|
|
16
|
-
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct
|
16
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
17
|
+
|
18
|
+
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
17
19
|
|
18
20
|
This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
19
21
|
|
20
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
|
22
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [INSERT EMAIL ADDRESS]. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
21
23
|
|
22
|
-
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.
|
24
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.3.0, available at [http://contributor-covenant.org/version/1/3/0/](http://contributor-covenant.org/version/1/3/0/)
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ mail_room is a configuration based process that will idle on IMAP connections an
|
|
7
7
|
* Log the message or open with LetterOpener (Logger or LetterOpener)
|
8
8
|
|
9
9
|
[![Build Status](https://travis-ci.org/tpitale/mail_room.png?branch=master)](https://travis-ci.org/tpitale/mail_room)
|
10
|
-
[![Code Climate](https://codeclimate.com/github/tpitale/mail_room.
|
10
|
+
[![Code Climate](https://codeclimate.com/github/tpitale/mail_room/badges/gpa.svg)](https://codeclimate.com/github/tpitale/mail_room)
|
11
11
|
|
12
12
|
## Installation ##
|
13
13
|
|
@@ -189,6 +189,11 @@ disabled, you can get the raw string of the email using `request.body.read`.
|
|
189
189
|
I would recommend having the `mail` gem bundled and parse the email using
|
190
190
|
`Mail.read_from_string(request.body.read)`.
|
191
191
|
|
192
|
+
## idle_timeout ##
|
193
|
+
|
194
|
+
By default, the IDLE command will wait for 29 minutes (in order to keep the server connection happy).
|
195
|
+
If you'd prefer not to wait that long, you can pass `imap_timeout` in seconds for your mailbox configuration.
|
196
|
+
|
192
197
|
## Search Command ##
|
193
198
|
|
194
199
|
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.
|
@@ -197,6 +202,8 @@ This setting allows configuration of the IMAP search command sent to the server.
|
|
197
202
|
|
198
203
|
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).
|
199
204
|
|
205
|
+
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.
|
206
|
+
|
200
207
|
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.
|
201
208
|
|
202
209
|
## Running in Production ##
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module MailRoom
|
2
|
+
class IMAP < Net::IMAP
|
3
|
+
# Backported 2.3.0 version of net/imap idle command to support timeout
|
4
|
+
def idle(timeout = nil, &response_handler)
|
5
|
+
raise LocalJumpError, "no block given" unless response_handler
|
6
|
+
|
7
|
+
response = nil
|
8
|
+
|
9
|
+
synchronize do
|
10
|
+
tag = Thread.current[:net_imap_tag] = generate_tag
|
11
|
+
put_string("#{tag} IDLE#{CRLF}")
|
12
|
+
|
13
|
+
begin
|
14
|
+
add_response_handler(response_handler)
|
15
|
+
@idle_done_cond = new_cond
|
16
|
+
@idle_done_cond.wait(timeout)
|
17
|
+
@idle_done_cond = nil
|
18
|
+
if @receiver_thread_terminating
|
19
|
+
raise Net::IMAP::Error, "connection closed"
|
20
|
+
end
|
21
|
+
ensure
|
22
|
+
unless @receiver_thread_terminating
|
23
|
+
remove_response_handler(response_handler)
|
24
|
+
put_string("DONE#{CRLF}")
|
25
|
+
response = get_tagged_response(tag, "IDLE")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
return response
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/mail_room/mailbox.rb
CHANGED
@@ -10,6 +10,7 @@ module MailRoom
|
|
10
10
|
:port,
|
11
11
|
:ssl,
|
12
12
|
:start_tls,
|
13
|
+
:idle_timeout,
|
13
14
|
:search_command,
|
14
15
|
:name,
|
15
16
|
:delete_after_delivery,
|
@@ -23,9 +24,17 @@ module MailRoom
|
|
23
24
|
:arbitration_options
|
24
25
|
]
|
25
26
|
|
27
|
+
IdleTimeoutTooLarge = Class.new(RuntimeError)
|
28
|
+
|
26
29
|
# Holds configuration for each of the email accounts we wish to monitor
|
27
30
|
# and deliver email to when new emails arrive over imap
|
28
31
|
Mailbox = Struct.new(*MAILBOX_FIELDS) do
|
32
|
+
# Keep it to 29 minutes or less
|
33
|
+
# The IMAP serve will close the connection after 30 minutes of inactivity
|
34
|
+
# (which sending IDLE and then nothing technically is), so we re-idle every
|
35
|
+
# 29 minutes, as suggested by the spec: https://tools.ietf.org/html/rfc2177
|
36
|
+
IMAP_IDLE_TIMEOUT = 29 * 60 # 29 minutes in in seconds
|
37
|
+
|
29
38
|
# Default attributes for the mailbox configuration
|
30
39
|
DEFAULTS = {
|
31
40
|
:search_command => 'UNSEEN',
|
@@ -34,6 +43,7 @@ module MailRoom
|
|
34
43
|
:port => 993,
|
35
44
|
:ssl => true,
|
36
45
|
:start_tls => false,
|
46
|
+
:idle_timeout => IMAP_IDLE_TIMEOUT,
|
37
47
|
:delete_after_delivery => false,
|
38
48
|
:delivery_options => {},
|
39
49
|
:arbitration_method => 'noop',
|
@@ -44,6 +54,8 @@ module MailRoom
|
|
44
54
|
# @param attributes [Hash] configuration options
|
45
55
|
def initialize(attributes={})
|
46
56
|
super(*DEFAULTS.merge(attributes).values_at(*members))
|
57
|
+
|
58
|
+
validate!
|
47
59
|
end
|
48
60
|
|
49
61
|
def delivery_klass
|
@@ -75,6 +87,17 @@ module MailRoom
|
|
75
87
|
delivery.deliver(body)
|
76
88
|
end
|
77
89
|
|
90
|
+
# true, false, or ssl options hash
|
91
|
+
def ssl_options
|
92
|
+
replace_verify_mode(ssl)
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate!
|
96
|
+
if self[:idle_timeout] > IMAP_IDLE_TIMEOUT
|
97
|
+
raise IdleTimeoutTooLarge.new("Please use an idle timeout smaller than #{29*60} to prevent IMAP server disconnects")
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
78
101
|
private
|
79
102
|
|
80
103
|
def parsed_arbitration_options
|
@@ -84,5 +107,23 @@ module MailRoom
|
|
84
107
|
def parsed_delivery_options
|
85
108
|
delivery_klass::Options.new(self)
|
86
109
|
end
|
110
|
+
|
111
|
+
def replace_verify_mode(options)
|
112
|
+
return options unless options.is_a?(Hash)
|
113
|
+
return options unless options.has_key?(:verify_mode)
|
114
|
+
|
115
|
+
options[:verify_mode] = case options[:verify_mode]
|
116
|
+
when :none, 'none'
|
117
|
+
OpenSSL::SSL::VERIFY_NONE
|
118
|
+
when :peer, 'peer'
|
119
|
+
OpenSSL::SSL::VERIFY_PEER
|
120
|
+
when :client_once, 'client_once'
|
121
|
+
OpenSSL::SSL::VERIFY_CLIENT_ONCE
|
122
|
+
when :fail_if_no_peer_cert, 'fail_if_no_peer_cert'
|
123
|
+
OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
124
|
+
end
|
125
|
+
|
126
|
+
options
|
127
|
+
end
|
87
128
|
end
|
88
129
|
end
|
@@ -4,7 +4,7 @@ module MailRoom
|
|
4
4
|
# Watch a Mailbox
|
5
5
|
# @author Tony Pitale
|
6
6
|
class MailboxWatcher
|
7
|
-
attr_accessor :idling_thread
|
7
|
+
attr_accessor :idling_thread
|
8
8
|
|
9
9
|
# Watch a new mailbox
|
10
10
|
# @param mailbox [MailRoom::Mailbox] the mailbox to watch
|
@@ -17,7 +17,7 @@ module MailRoom
|
|
17
17
|
|
18
18
|
# build a net/imap connection to google imap
|
19
19
|
def imap
|
20
|
-
@imap ||=
|
20
|
+
@imap ||= MailRoom::IMAP.new(@mailbox.host, :port => @mailbox.port, :ssl => @mailbox.ssl_options)
|
21
21
|
end
|
22
22
|
|
23
23
|
# build a handler to process mailbox messages
|
@@ -100,20 +100,8 @@ module MailRoom
|
|
100
100
|
|
101
101
|
@idling = true
|
102
102
|
|
103
|
-
|
104
|
-
# The IMAP server will close the connection after 30 minutes of inactivity
|
105
|
-
# (which sending IDLE and then nothing technically is), so we re-idle every
|
106
|
-
# 29 minutes, as suggested by the spec: https://tools.ietf.org/html/rfc2177
|
107
|
-
sleep 29 * 60
|
108
|
-
|
109
|
-
imap.idle_done if idling?
|
110
|
-
end
|
111
|
-
timeout_thread.abort_on_exception = true
|
112
|
-
|
113
|
-
imap.idle(&idle_handler)
|
103
|
+
imap.idle(@mailbox.idle_timeout, &idle_handler)
|
114
104
|
ensure
|
115
|
-
timeout_thread.kill if timeout_thread
|
116
|
-
self.timeout_thread = nil
|
117
105
|
@idling = false
|
118
106
|
end
|
119
107
|
|
@@ -139,7 +127,7 @@ module MailRoom
|
|
139
127
|
self.idling_thread = Thread.start do
|
140
128
|
while(running?) do
|
141
129
|
begin
|
142
|
-
# block until we stop idling
|
130
|
+
# block for idle_timeout until we stop idling
|
143
131
|
idle
|
144
132
|
|
145
133
|
# when new messages are ready
|
data/lib/mail_room/version.rb
CHANGED
data/lib/mail_room.rb
CHANGED
data/spec/lib/mailbox_spec.rb
CHANGED
@@ -89,5 +89,13 @@ describe MailRoom::Mailbox do
|
|
89
89
|
noop.should have_received(:deliver).never
|
90
90
|
end
|
91
91
|
end
|
92
|
+
|
93
|
+
context "with ssl options hash" do
|
94
|
+
it 'replaces verify mode with constant' do
|
95
|
+
mailbox = MailRoom::Mailbox.new({:ssl => {:verify_mode => :none}})
|
96
|
+
|
97
|
+
expect(mailbox.ssl_options).to eq({:verify_mode => OpenSSL::SSL::VERIFY_NONE})
|
98
|
+
end
|
99
|
+
end
|
92
100
|
end
|
93
101
|
end
|
@@ -25,14 +25,12 @@ describe MailRoom::MailboxWatcher do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#imap' do
|
28
|
-
let(:mailbox) {MailRoom::Mailbox.new}
|
29
|
-
|
30
28
|
it 'builds a new Net::IMAP object' do
|
31
|
-
|
29
|
+
MailRoom::IMAP.stubs(:new).returns('imap')
|
32
30
|
|
33
31
|
MailRoom::MailboxWatcher.new(mailbox).imap.should eq('imap')
|
34
32
|
|
35
|
-
|
33
|
+
MailRoom::IMAP.should have_received(:new).with('imap.gmail.com', :port => 993, :ssl => true)
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
@@ -40,7 +38,7 @@ describe MailRoom::MailboxWatcher do
|
|
40
38
|
let(:imap) {stub(:login => true, :select => true)}
|
41
39
|
|
42
40
|
let(:mailbox) {
|
43
|
-
MailRoom::Mailbox.new(:email => 'user1@gmail.com', :password => 'password', :name => 'inbox'
|
41
|
+
MailRoom::Mailbox.new(:email => 'user1@gmail.com', :password => 'password', :name => 'inbox')
|
44
42
|
}
|
45
43
|
|
46
44
|
let(:watcher) {
|
@@ -74,7 +72,7 @@ describe MailRoom::MailboxWatcher do
|
|
74
72
|
|
75
73
|
describe '#idle' do
|
76
74
|
let(:imap) {stub}
|
77
|
-
let(:watcher) {MailRoom::MailboxWatcher.new(
|
75
|
+
let(:watcher) {MailRoom::MailboxWatcher.new(mailbox)}
|
78
76
|
|
79
77
|
before :each do
|
80
78
|
watcher.stubs(:imap).returns(imap)
|
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.
|
4
|
+
version: 0.7.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:
|
11
|
+
date: 2016-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -200,6 +200,7 @@ files:
|
|
200
200
|
- lib/mail_room/arbitration.rb
|
201
201
|
- lib/mail_room/arbitration/noop.rb
|
202
202
|
- lib/mail_room/arbitration/redis.rb
|
203
|
+
- lib/mail_room/backports/imap.rb
|
203
204
|
- lib/mail_room/cli.rb
|
204
205
|
- lib/mail_room/configuration.rb
|
205
206
|
- lib/mail_room/coordinator.rb
|