mailhandler 1.0.36 → 1.0.37
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/Gemfile +2 -2
- data/Rakefile +2 -2
- data/lib/mailhandler.rb +13 -37
- data/lib/mailhandler/errors.rb +1 -5
- data/lib/mailhandler/receiver.rb +4 -22
- data/lib/mailhandler/receiving/base.rb +16 -45
- data/lib/mailhandler/receiving/filelist/base.rb +25 -49
- data/lib/mailhandler/receiving/filelist/filter/base.rb +10 -52
- data/lib/mailhandler/receiving/filelist/filter/email.rb +4 -44
- data/lib/mailhandler/receiving/folder.rb +16 -54
- data/lib/mailhandler/receiving/imap.rb +34 -78
- data/lib/mailhandler/receiving/mail.rb +5 -19
- data/lib/mailhandler/receiving/notification/console.rb +2 -18
- data/lib/mailhandler/receiving/notification/email.rb +5 -28
- data/lib/mailhandler/receiving/notification/email/content.rb +9 -20
- data/lib/mailhandler/receiving/notification/email/states.rb +1 -36
- data/lib/mailhandler/receiving/observer.rb +5 -16
- data/lib/mailhandler/sender.rb +2 -14
- data/lib/mailhandler/sending/api.rb +1 -7
- data/lib/mailhandler/sending/api_batch.rb +1 -13
- data/lib/mailhandler/sending/base.rb +1 -13
- data/lib/mailhandler/sending/smtp.rb +20 -22
- data/lib/mailhandler/version.rb +2 -2
- data/mailhandler.gemspec +14 -17
- data/readme.md +33 -8
- data/spec/spec_helper.rb +1 -5
- data/spec/unit/mailhandler/receiver_spec.rb +8 -30
- data/spec/unit/mailhandler/receiving/base_spec.rb +4 -14
- data/spec/unit/mailhandler/receiving/folder_spec.rb +61 -155
- data/spec/unit/mailhandler/receiving/imap_spec.rb +18 -42
- data/spec/unit/mailhandler/receiving/notification/console_spec.rb +6 -16
- data/spec/unit/mailhandler/receiving/notification/email/content_spec.rb +10 -44
- data/spec/unit/mailhandler/receiving/notification/email_spec.rb +9 -15
- data/spec/unit/mailhandler/sender_spec.rb +12 -23
- data/spec/unit/mailhandler/sending/sender_api_batch_spec.rb +7 -19
- data/spec/unit/mailhandler/sending/sender_api_spec.rb +4 -14
- data/spec/unit/mailhandler/sending/sender_smtp_spec.rb +24 -6
- data/spec/unit/mailhandler_spec.rb +33 -25
- metadata +2 -2
@@ -3,11 +3,8 @@ require 'postmark'
|
|
3
3
|
require_relative 'base.rb'
|
4
4
|
|
5
5
|
module MailHandler
|
6
|
-
|
7
6
|
module Sending
|
8
|
-
|
9
7
|
class PostmarkAPISender < Sender
|
10
|
-
|
11
8
|
attr_accessor :host,
|
12
9
|
:api_token,
|
13
10
|
:use_ssl,
|
@@ -43,10 +40,7 @@ module MailHandler
|
|
43
40
|
|
44
41
|
protected
|
45
42
|
|
46
|
-
DEFAULT_HOST = 'api.postmarkapp.com'
|
47
|
-
|
43
|
+
DEFAULT_HOST = 'api.postmarkapp.com'.freeze
|
48
44
|
end
|
49
|
-
|
50
45
|
end
|
51
|
-
|
52
46
|
end
|
@@ -2,35 +2,23 @@ require_relative 'api.rb'
|
|
2
2
|
require_relative '../errors'
|
3
3
|
|
4
4
|
module MailHandler
|
5
|
-
|
6
5
|
module Sending
|
7
|
-
|
8
6
|
class PostmarkBatchAPISender < PostmarkAPISender
|
9
|
-
|
10
7
|
def initialize(api_token = nil)
|
11
|
-
|
12
8
|
super(api_token)
|
13
|
-
|
14
9
|
end
|
15
10
|
|
16
11
|
def send(emails)
|
17
|
-
|
18
12
|
verify_email(emails)
|
19
13
|
init_client
|
20
14
|
client.deliver_messages(emails)
|
21
|
-
|
22
15
|
end
|
23
16
|
|
24
17
|
protected
|
25
18
|
|
26
19
|
def verify_email(emails)
|
27
|
-
|
28
|
-
raise MailHandler::TypeError, "Invalid type error, only Array of Mail::Message object types for sending allowed" unless emails.is_a?(Array) && emails.all? { |e| e.is_a? allowed_email_type }
|
29
|
-
|
20
|
+
raise MailHandler::TypeError, 'Invalid type error, only Array of Mail::Message object types for sending allowed' unless emails.is_a?(Array) && emails.all? { |e| e.is_a? allowed_email_type }
|
30
21
|
end
|
31
|
-
|
32
22
|
end
|
33
|
-
|
34
23
|
end
|
35
|
-
|
36
24
|
end
|
@@ -1,37 +1,25 @@
|
|
1
1
|
require_relative '../errors'
|
2
2
|
|
3
3
|
module MailHandler
|
4
|
-
|
5
4
|
module Sending
|
6
|
-
|
7
5
|
class Sender
|
8
|
-
|
9
6
|
attr_reader :type
|
10
7
|
|
11
|
-
def send(
|
12
|
-
|
8
|
+
def send(_email)
|
13
9
|
raise MailHandler::InterfaceError, 'Send interface not implemented.'
|
14
|
-
|
15
10
|
end
|
16
11
|
|
17
12
|
protected
|
18
13
|
|
19
14
|
def verify_email(email)
|
20
|
-
|
21
15
|
raise MailHandler::TypeError, "Invalid type error, only #{allowed_email_type} object type for sending allowed." unless email.is_a? allowed_email_type
|
22
|
-
|
23
16
|
end
|
24
17
|
|
25
18
|
private
|
26
19
|
|
27
20
|
def allowed_email_type
|
28
|
-
|
29
21
|
Mail::Message
|
30
|
-
|
31
22
|
end
|
32
|
-
|
33
23
|
end
|
34
|
-
|
35
24
|
end
|
36
|
-
|
37
25
|
end
|
@@ -1,14 +1,11 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
require 'net/imap'
|
3
3
|
require_relative 'base'
|
4
4
|
|
5
5
|
module MailHandler
|
6
|
-
|
7
6
|
module Sending
|
8
|
-
|
9
7
|
# class which describes methods to send and receive emails
|
10
8
|
class SMTPSender < Sender
|
11
|
-
|
12
9
|
attr_accessor :address,
|
13
10
|
:port,
|
14
11
|
:domain,
|
@@ -17,45 +14,46 @@ module MailHandler
|
|
17
14
|
:authentication,
|
18
15
|
:use_ssl
|
19
16
|
|
20
|
-
|
17
|
+
attr_accessor :open_timeout,
|
18
|
+
:read_timeout,
|
19
|
+
:save_response
|
21
20
|
|
21
|
+
def initialize
|
22
22
|
@type = :smtp
|
23
23
|
@authentication = 'plain'
|
24
24
|
@use_ssl = false
|
25
|
+
@save_response = false
|
25
26
|
|
27
|
+
@open_timeout = 60
|
28
|
+
@read_timeout = 60
|
26
29
|
end
|
27
30
|
|
28
31
|
def send(email)
|
29
|
-
|
30
32
|
verify_email(email)
|
31
33
|
email = configure_sending(email)
|
32
|
-
email.deliver
|
33
|
-
|
34
|
+
save_response ? email.deliver! : email.deliver
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
37
38
|
|
38
39
|
def configure_sending(email)
|
39
|
-
|
40
40
|
options = {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
41
|
+
address: address,
|
42
|
+
port: port,
|
43
|
+
domain: domain,
|
44
|
+
user_name: username,
|
45
|
+
password: password,
|
46
|
+
authentication: @authentication,
|
47
|
+
enable_starttls_auto: @use_ssl,
|
48
|
+
|
49
|
+
return_response: save_response,
|
50
|
+
open_timeout: open_timeout,
|
51
|
+
read_timeout: read_timeout
|
50
52
|
}
|
51
53
|
|
52
54
|
email.delivery_method :smtp, options
|
53
55
|
email
|
54
|
-
|
55
56
|
end
|
56
|
-
|
57
57
|
end
|
58
|
-
|
59
58
|
end
|
60
|
-
|
61
59
|
end
|
data/lib/mailhandler/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module MailHandler
|
2
|
-
VERSION = '1.0.
|
3
|
-
end
|
2
|
+
VERSION = '1.0.37'.freeze
|
3
|
+
end
|
data/mailhandler.gemspec
CHANGED
@@ -1,37 +1,34 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('
|
1
|
+
|
2
|
+
lib = File.expand_path('lib', __dir__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'mailhandler/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
|
-
|
8
7
|
s.name = 'mailhandler'
|
9
8
|
s.version = MailHandler::VERSION
|
10
9
|
s.platform = Gem::Platform::RUBY
|
11
10
|
s.license = 'MIT'
|
12
11
|
|
13
|
-
s.authors = [
|
14
|
-
s.email = [
|
12
|
+
s.authors = ['Igor Balos']
|
13
|
+
s.email = ['ibalosh@gmail.com', 'igor@wildbit.com']
|
15
14
|
|
16
|
-
s.summary =
|
17
|
-
s.description =
|
15
|
+
s.summary = 'Postmark email receiving and sending handler.'
|
16
|
+
s.description = 'Use this gem to send emails through SMTP and Postmark API. Check if email arrived by imap or folder check.'
|
18
17
|
|
19
|
-
|
20
|
-
s.files = `git ls-files`.split($/)
|
18
|
+
s.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
21
19
|
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
22
20
|
s.homepage = 'https://github.com/wildbit/mailhandler'
|
23
|
-
s.require_paths = [
|
21
|
+
s.require_paths = ['lib']
|
24
22
|
|
25
|
-
s.post_install_message =
|
23
|
+
s.post_install_message = '
|
26
24
|
==================
|
27
25
|
Thanks for installing the mailhandler gem.
|
28
26
|
Review the README.md for implementation details and examples.
|
29
27
|
==================
|
30
|
-
|
31
|
-
|
32
|
-
s.required_rubygems_version = ">= 1.9.3"
|
28
|
+
'
|
33
29
|
|
34
|
-
s.
|
35
|
-
s.add_dependency "postmark", '>= 1.7.0'
|
30
|
+
s.required_rubygems_version = '>= 1.9.3'
|
36
31
|
|
37
|
-
|
32
|
+
s.add_dependency 'mail'
|
33
|
+
s.add_dependency 'postmark', '>= 1.7.0'
|
34
|
+
end
|
data/readme.md
CHANGED
@@ -33,23 +33,36 @@ In order to search for email, all you need to do is setup inbox folder and archi
|
|
33
33
|
Folders can be the same if you don't plan to archive found emails. Retrieving emails from a folder would look like following:
|
34
34
|
|
35
35
|
``` ruby
|
36
|
+
|
37
|
+
inbox_folder = '/folder/mailbox/inbox'
|
38
|
+
archive_folder = '/folder/mailbox/archive/'
|
39
|
+
|
36
40
|
email_receiver = MailHandler.receiver(:folder) do |checker|
|
37
|
-
checker.inbox_folder =
|
38
|
-
checker.archive_folder =
|
41
|
+
checker.inbox_folder = inbox_folder
|
42
|
+
checker.archive_folder = archive_folder
|
39
43
|
end
|
40
44
|
```
|
41
45
|
|
42
46
|
## Configure imap mailbox email to check
|
43
47
|
|
44
|
-
If you plan to search for emails in your remote inbox which
|
48
|
+
If you plan to search for emails in your remote inbox which supports IMAP, you can use Mailhandler by providing IMAP settings.
|
49
|
+
We recommend to keep credentials for your IMAP settings safe, and read them from config file or environment variables.
|
50
|
+
Do NOT keep credentials in your repositories.
|
45
51
|
|
46
52
|
``` ruby
|
53
|
+
|
54
|
+
address = 'imap.example.com'
|
55
|
+
port = 993
|
56
|
+
username = 'john'
|
57
|
+
password = 'xxxxxxxxxxxxxx'
|
58
|
+
use_ssl = true
|
59
|
+
|
47
60
|
email_receiver = MailHandler.receiver(:imap) do |checker|
|
48
|
-
checker.address =
|
49
|
-
checker.port =
|
50
|
-
checker.username =
|
51
|
-
checker.password =
|
52
|
-
checker.use_ssl =
|
61
|
+
checker.address = address
|
62
|
+
checker.port = port
|
63
|
+
checker.username = username
|
64
|
+
checker.password = password
|
65
|
+
checker.use_ssl = use_ssl
|
53
66
|
end
|
54
67
|
```
|
55
68
|
|
@@ -124,6 +137,8 @@ There are three ways you can send email, which we will describe below. To send e
|
|
124
137
|
To send email with Postmark, you need to choose type of sending, api token options.
|
125
138
|
|
126
139
|
``` ruby
|
140
|
+
api_token = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
|
141
|
+
|
127
142
|
email_sender = MailHandler.sender(type) do |dispatcher|
|
128
143
|
dispatcher.api_token = api_token
|
129
144
|
end
|
@@ -135,8 +150,18 @@ end
|
|
135
150
|
### Sending email by SMTP
|
136
151
|
|
137
152
|
To send email with SMTP you need to configure standard SMTP settings.
|
153
|
+
We recommend to keep credentials for your SMTP settings safe, and read them from config file or environment variables.
|
154
|
+
Do NOT keep credentials in your repositories.
|
138
155
|
|
139
156
|
``` ruby
|
157
|
+
|
158
|
+
address = 'imap.example.com'
|
159
|
+
domain = 'example.com'
|
160
|
+
port = 587
|
161
|
+
username = 'john'
|
162
|
+
password = 'xxxxxxxxxxxxxx'
|
163
|
+
use_ssl = true
|
164
|
+
|
140
165
|
email_sender = MailHandler.sender(:smtp) do |dispatcher|
|
141
166
|
dispatcher.address = address
|
142
167
|
dispatcher.port = port
|
data/spec/spec_helper.rb
CHANGED
@@ -8,15 +8,11 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
8
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
9
|
|
10
10
|
def data_folder
|
11
|
-
|
12
11
|
File.join(File.dirname(__FILE__), '/', 'data')
|
13
|
-
|
14
12
|
end
|
15
13
|
|
16
14
|
RSpec.configure do |c|
|
17
|
-
|
18
15
|
# Use the specified formatter, options are: # :documentation, :progress, :html, :textmate
|
19
16
|
c.formatter = :documentation
|
20
17
|
c.color = true
|
21
|
-
|
22
|
-
end
|
18
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe MailHandler::Receiver do
|
4
|
-
|
5
4
|
context 'valid receiver' do
|
6
|
-
|
7
|
-
let(:default_search_option) { {:by_subject => 'test'} }
|
5
|
+
let(:default_search_option) { { by_subject: 'test' } }
|
8
6
|
let(:receiving_duration) { 5 }
|
9
7
|
let(:found_email) { Mail.new { subject 'test email' } }
|
10
|
-
let(:checker)
|
8
|
+
let(:checker) do
|
11
9
|
checker = double('Checker')
|
12
10
|
|
13
11
|
allow(checker).to receive(:find) { sleep receiving_duration; true }
|
@@ -17,43 +15,33 @@ describe MailHandler::Receiver do
|
|
17
15
|
allow(checker).to receive(:start) { nil }
|
18
16
|
allow(checker).to receive(:stop) { nil }
|
19
17
|
checker
|
20
|
-
|
21
|
-
}
|
18
|
+
end
|
22
19
|
subject(:receiver) { MailHandler::Receiver.new(checker) }
|
23
20
|
|
24
21
|
context 'att readers' do
|
25
|
-
|
26
22
|
it { is_expected.to respond_to(:checker) }
|
27
23
|
it { is_expected.to respond_to(:search) }
|
28
24
|
it { is_expected.to respond_to(:max_search_duration) }
|
29
|
-
|
30
25
|
end
|
31
26
|
|
32
27
|
context 'att writters' do
|
33
|
-
|
34
28
|
it { is_expected.to respond_to(:checker=) }
|
35
29
|
it { is_expected.to respond_to(:search=) }
|
36
30
|
it { is_expected.to respond_to(:max_search_duration=) }
|
37
|
-
|
38
31
|
end
|
39
32
|
|
40
33
|
it 'create' do
|
41
|
-
|
42
34
|
is_expected.to be_kind_of MailHandler::Receiver
|
43
|
-
|
44
35
|
end
|
45
36
|
|
46
37
|
it '.find_email' do
|
47
|
-
|
48
38
|
expect(receiver.find_email(default_search_option)).to be true
|
49
|
-
|
50
39
|
end
|
51
40
|
|
52
41
|
it '.search' do
|
53
|
-
|
54
42
|
receiver.find_email(default_search_option)
|
55
43
|
|
56
|
-
aggregate_failures
|
44
|
+
aggregate_failures 'search details' do
|
57
45
|
expect(receiver.search.options).to eq default_search_option
|
58
46
|
expect(receiver.search.started_at).to be_within(1).of(Time.now - receiving_duration)
|
59
47
|
expect(receiver.search.finished_at).to be_within(1).of(Time.now)
|
@@ -62,12 +50,10 @@ describe MailHandler::Receiver do
|
|
62
50
|
expect(receiver.search.emails).to eq [found_email]
|
63
51
|
expect(receiver.search.email).to eq found_email
|
64
52
|
end
|
65
|
-
|
66
53
|
end
|
67
54
|
|
68
55
|
context '.search' do
|
69
|
-
|
70
|
-
let(:checker) {
|
56
|
+
let(:checker) do
|
71
57
|
checker = double('Checker')
|
72
58
|
|
73
59
|
allow(checker).to receive(:find) { sleep 1; false }
|
@@ -77,24 +63,16 @@ describe MailHandler::Receiver do
|
|
77
63
|
allow(checker).to receive(:start) { nil }
|
78
64
|
allow(checker).to receive(:stop) { nil }
|
79
65
|
checker
|
66
|
+
end
|
80
67
|
|
81
|
-
|
82
|
-
|
83
|
-
[1,3,5].each do |duration|
|
84
|
-
|
68
|
+
[1, 3, 5].each do |duration|
|
85
69
|
it "max duration - #{duration} seconds" do
|
86
|
-
|
87
70
|
receiver.max_search_duration = duration
|
88
71
|
receiver.find_email(default_search_option)
|
89
72
|
|
90
73
|
expect(receiver.search.duration).to be_within(1).of(duration)
|
91
|
-
|
92
74
|
end
|
93
|
-
|
94
75
|
end
|
95
|
-
|
96
76
|
end
|
97
|
-
|
98
77
|
end
|
99
|
-
|
100
|
-
end
|
78
|
+
end
|
@@ -1,35 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe MailHandler::Receiving::Checker do
|
4
|
-
|
5
4
|
subject { MailHandler::Receiving::Checker.new }
|
6
5
|
|
7
6
|
it '.create' do
|
8
|
-
|
9
7
|
is_expected.to be_kind_of MailHandler::Receiving::Checker
|
10
|
-
|
11
8
|
end
|
12
9
|
|
13
10
|
it 'init details' do
|
14
|
-
|
15
|
-
|
16
|
-
expect(subject.search_options).to eq({:count => 50, :archive => false})
|
11
|
+
aggregate_failures 'receiving details' do
|
12
|
+
expect(subject.search_options).to eq(count: 50, archive: false)
|
17
13
|
expect(subject.found_emails).to eq []
|
18
14
|
expect(subject.search_result).to be false
|
19
15
|
end
|
20
|
-
|
21
16
|
end
|
22
17
|
|
23
18
|
it '.find' do
|
24
|
-
|
25
|
-
expect { subject.find(:by_subject => 'test') }.to raise_error(MailHandler::InterfaceError, 'Find interface not implemented.')
|
26
|
-
|
19
|
+
expect { subject.find(by_subject: 'test') }.to raise_error(MailHandler::InterfaceError, 'Find interface not implemented.')
|
27
20
|
end
|
28
21
|
|
29
22
|
it '.search_result' do
|
30
|
-
|
31
23
|
expect(subject.search_result).to be false
|
32
|
-
|
33
24
|
end
|
34
|
-
|
35
|
-
end
|
25
|
+
end
|