tuktuk 0.6.5 → 0.7.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 +4 -4
- data/lib/tuktuk/tuktuk.rb +14 -8
- data/lib/tuktuk/version.rb +2 -2
- data/spec/deliver_spec.rb +139 -13
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 645a6229301a14c9ea9de30d17f6fed26fefbc9f28d8217ca3bc62c092029e59
|
4
|
+
data.tar.gz: 2fa5cd367e612f7a5214d48c670afd07a69b297437db0444fc85f6da750be588
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e496e4ab7b6eed91ad413acf28a36d63bd325a0f3638f41d004fe8b02caa27b4256a7c4c85bb1c4e9c3ad1b2308e1bed3c12d58f2a00687f99ea7b651c8121e9
|
7
|
+
data.tar.gz: cdcfd31010bceb164b591699c96b5e9bc010bbfaec53bf3d6f23c2bfee4b1141f34a0ab4ca3b6b70fb7ac2ee8130c6f510069b6216208f07e368488d08344d68
|
data/lib/tuktuk/tuktuk.rb
CHANGED
@@ -30,16 +30,19 @@ module Tuktuk
|
|
30
30
|
|
31
31
|
def deliver(message, opts = {})
|
32
32
|
# raise 'Please pass a valid message object.' unless message[:to]
|
33
|
+
bcc = opts.delete(:bcc) || []
|
34
|
+
bcc = [bcc] if bcc.is_a?(String)
|
35
|
+
|
33
36
|
self.options = opts if opts.any?
|
34
37
|
mail = Package.build(message)
|
35
|
-
response = lookup_and_deliver(mail)
|
38
|
+
response = lookup_and_deliver(mail, bcc)
|
36
39
|
return response, mail
|
37
40
|
end
|
38
41
|
|
39
42
|
# same as deliver but raises error. used by ActionMailer
|
40
|
-
def deliver!(mail)
|
43
|
+
def deliver!(mail, opts = {})
|
41
44
|
@logger = Rails.logger if defined?(Rails) and !config[:log_to]
|
42
|
-
resp, email = deliver(mail)
|
45
|
+
resp, email = deliver(mail, opts)
|
43
46
|
if resp.is_a?(Exception)
|
44
47
|
raise resp
|
45
48
|
else
|
@@ -89,7 +92,9 @@ module Tuktuk
|
|
89
92
|
hash = {}
|
90
93
|
array.each_with_index do |message, i|
|
91
94
|
mail = Package.build(message, i)
|
92
|
-
|
95
|
+
if mail.destinations.count != 1
|
96
|
+
raise ArgumentError, "Invalid destination count: #{mail.destinations.count}"
|
97
|
+
end
|
93
98
|
|
94
99
|
if to = mail.destinations.first and domain = get_domain(to)
|
95
100
|
domain = domain.downcase
|
@@ -109,7 +114,7 @@ module Tuktuk
|
|
109
114
|
servers.any? && servers
|
110
115
|
end
|
111
116
|
|
112
|
-
def lookup_and_deliver(mail,
|
117
|
+
def lookup_and_deliver(mail, bcc = [])
|
113
118
|
if mail.destinations.empty?
|
114
119
|
raise "No destinations found! You need to pass a :to field."
|
115
120
|
end
|
@@ -127,9 +132,10 @@ module Tuktuk
|
|
127
132
|
last_error = nil
|
128
133
|
servers.each do |server|
|
129
134
|
begin
|
130
|
-
response = send_now(mail, server, to)
|
135
|
+
response = send_now(mail, server, to, bcc)
|
131
136
|
break
|
132
137
|
rescue Exception => e # explicitly rescue Exception so we catch Timeout:Error's too
|
138
|
+
logger.error "Error: #{e}"
|
133
139
|
last_error = e
|
134
140
|
end
|
135
141
|
end
|
@@ -210,14 +216,14 @@ module Tuktuk
|
|
210
216
|
responses
|
211
217
|
end
|
212
218
|
|
213
|
-
def send_now(mail, server, to)
|
219
|
+
def send_now(mail, server, to, bcc = [])
|
214
220
|
logger.info "#{to} - Delivering email at #{server}..."
|
215
221
|
from = get_from(mail)
|
216
222
|
|
217
223
|
response = nil
|
218
224
|
socket = init_connection(server)
|
219
225
|
socket.start(get_helo_domain(from), nil, nil, nil) do |smtp|
|
220
|
-
response = smtp.send_message(get_raw_mail(mail), from, to)
|
226
|
+
response = smtp.send_message(get_raw_mail(mail), from, to, *bcc)
|
221
227
|
logger.info "#{to} - [SENT] #{response.message.strip}"
|
222
228
|
end
|
223
229
|
|
data/lib/tuktuk/version.rb
CHANGED
data/spec/deliver_spec.rb
CHANGED
@@ -1,8 +1,142 @@
|
|
1
1
|
require './lib/tuktuk/tuktuk'
|
2
2
|
require 'rspec/mocks'
|
3
3
|
|
4
|
+
def email(attrs = {})
|
5
|
+
{ :to => "user#{rand(1000)}@domain.com",
|
6
|
+
:from => 'me@company.com',
|
7
|
+
:subject => 'Test email',
|
8
|
+
:body => 'Hello world.'
|
9
|
+
}.merge(attrs)
|
10
|
+
end
|
11
|
+
|
4
12
|
describe 'deliver' do
|
5
13
|
|
14
|
+
before(:each) do
|
15
|
+
@mock_smtp = double('Net::SMTP', enable_starttls_auto: true, :read_timeout= => true, :open_timeout= => true)
|
16
|
+
@mock_conn = double('SMTP Connection')
|
17
|
+
@mock_smtp.stub(:start).and_yield(@mock_conn)
|
18
|
+
@mock_resp = double('SMTP::Response', message: '250 OK')
|
19
|
+
|
20
|
+
Net::SMTP.stub(:new).and_return(@mock_smtp)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'single recipient' do
|
24
|
+
|
25
|
+
describe 'when destination is valid (has MX servers)' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
@servers = ['mx1.domain.com', 'mx2.domain.com', 'mx3.domain.com']
|
29
|
+
Tuktuk.stub(:smtp_servers_for_domain).and_return(@servers)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'sends message' do
|
33
|
+
msg = email
|
34
|
+
expect(@mock_conn).to receive(:send_message).with(String, msg[:from], msg[:to]).and_return(@mock_resp)
|
35
|
+
Tuktuk.deliver(msg)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'and bcc is given' do
|
39
|
+
|
40
|
+
let(:bcc_email) { 'bcc@test.com' }
|
41
|
+
|
42
|
+
it 'includes it in destination list' do
|
43
|
+
msg = email
|
44
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to], bcc_email).and_return(@mock_resp)
|
45
|
+
Tuktuk.deliver(msg, bcc: [bcc_email])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'also works if not passed as array' do
|
49
|
+
msg = email
|
50
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to], bcc_email).and_return(@mock_resp)
|
51
|
+
Tuktuk.deliver(msg, bcc: bcc_email)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'multiple recipients (string list)' do
|
61
|
+
|
62
|
+
describe 'when destination is valid (has MX servers)' do
|
63
|
+
|
64
|
+
before do
|
65
|
+
@servers = ['mx1.domain.com', 'mx2.domain.com', 'mx3.domain.com']
|
66
|
+
Tuktuk.stub(:smtp_servers_for_domain).and_return(@servers)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'sends message' do
|
70
|
+
msg = email(to: 'some@one.com, another@one.com')
|
71
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').first).and_return(@mock_resp)
|
72
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').last).and_return(@mock_resp)
|
73
|
+
Tuktuk.deliver(msg)
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'and bcc is given' do
|
77
|
+
|
78
|
+
let(:bcc_email) { 'bcc@test.com' }
|
79
|
+
|
80
|
+
it 'includes it in destination list' do
|
81
|
+
msg = email(to: 'some@one.com, another@one.com')
|
82
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').first, bcc_email).and_return(@mock_resp)
|
83
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').last, bcc_email).and_return(@mock_resp)
|
84
|
+
Tuktuk.deliver(msg, bcc: [bcc_email])
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'also works if not passed as array' do
|
88
|
+
msg = email(to: 'some@one.com, another@one.com')
|
89
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').first, bcc_email).and_return(@mock_resp)
|
90
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].split(', ').last, bcc_email).and_return(@mock_resp)
|
91
|
+
Tuktuk.deliver(msg, bcc: bcc_email)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
describe 'multiple recipients (array)' do
|
101
|
+
|
102
|
+
describe 'when destination is valid (has MX servers)' do
|
103
|
+
|
104
|
+
before do
|
105
|
+
@servers = ['mx1.domain.com', 'mx2.domain.com', 'mx3.domain.com']
|
106
|
+
Tuktuk.stub(:smtp_servers_for_domain).and_return(@servers)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'sends message' do
|
110
|
+
msg = email(to: ['some@one.com', 'another@one.com'])
|
111
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].first).and_return(@mock_resp)
|
112
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].last).and_return(@mock_resp)
|
113
|
+
Tuktuk.deliver(msg)
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'and bcc is given' do
|
117
|
+
|
118
|
+
let(:bcc_email) { 'bcc@test.com' }
|
119
|
+
|
120
|
+
it 'includes it in destination list' do
|
121
|
+
msg = email(to: ['some@one.com', 'another@one.com'])
|
122
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].first, bcc_email).and_return(@mock_resp)
|
123
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].last, bcc_email).and_return(@mock_resp)
|
124
|
+
Tuktuk.deliver(msg, bcc: [bcc_email])
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'also works if not passed as array' do
|
128
|
+
msg = email(to: ['some@one.com', 'another@one.com'])
|
129
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].first, bcc_email).and_return(@mock_resp)
|
130
|
+
expect(@mock_conn).to receive(:send_message).with(instance_of(String), msg[:from], msg[:to].last, bcc_email).and_return(@mock_resp)
|
131
|
+
Tuktuk.deliver(msg, bcc: bcc_email)
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
6
140
|
end
|
7
141
|
|
8
142
|
describe 'deliver many' do
|
@@ -17,7 +151,7 @@ describe 'deliver many' do
|
|
17
151
|
it 'raises' do
|
18
152
|
lambda do
|
19
153
|
Tuktuk.deliver_many []
|
20
|
-
end.should raise_error
|
154
|
+
end.should raise_error(ArgumentError)
|
21
155
|
end
|
22
156
|
|
23
157
|
end
|
@@ -26,8 +160,8 @@ describe 'deliver many' do
|
|
26
160
|
|
27
161
|
it 'raises' do
|
28
162
|
lambda do
|
29
|
-
Tuktuk.deliver_many [ email, email(:to => 'one@user.com, two@user.com')]
|
30
|
-
end.should raise_error
|
163
|
+
Tuktuk.deliver_many [ email, email(:to => 'one@user.com, two@user.com') ]
|
164
|
+
end.should raise_error(ArgumentError)
|
31
165
|
end
|
32
166
|
|
33
167
|
end
|
@@ -89,7 +223,7 @@ describe 'deliver many' do
|
|
89
223
|
end
|
90
224
|
|
91
225
|
it 'starts by delivering to first one' do
|
92
|
-
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', [1]).and_return([[1,'ok']])
|
226
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', [1]).and_return([[1, 'ok']])
|
93
227
|
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', [1])
|
94
228
|
end
|
95
229
|
|
@@ -178,7 +312,7 @@ describe 'deliver many' do
|
|
178
312
|
describe 'and other servers are down' do
|
179
313
|
|
180
314
|
before do
|
181
|
-
# TODO: for some reason the :init_connection on line
|
315
|
+
# TODO: for some reason the :init_connection on line 138 is affecting this
|
182
316
|
# this test should pass when running on its own
|
183
317
|
# Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_return(@mock_smtp)
|
184
318
|
# Tuktuk.should_receive(:init_connection).once.with('mx2.domain.com').and_raise('Unable to connect.')
|
@@ -204,12 +338,4 @@ describe 'deliver many' do
|
|
204
338
|
|
205
339
|
end
|
206
340
|
|
207
|
-
def email(attrs = {})
|
208
|
-
{ :to => "user#{rand(1000)}@domain.com",
|
209
|
-
:from => 'me@company.com',
|
210
|
-
:subject => 'Test email',
|
211
|
-
:body => 'Hello world.'
|
212
|
-
}.merge(attrs)
|
213
|
-
end
|
214
|
-
|
215
341
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tuktuk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|