tuktuk 0.5.3 → 0.5.4
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.
- data/README.md +15 -11
- data/lib/tuktuk/bounce.rb +8 -8
- data/lib/tuktuk/package.rb +5 -4
- data/lib/tuktuk/tuktuk.rb +4 -3
- data/lib/tuktuk/version.rb +1 -1
- data/spec/deliver_spec.rb +208 -206
- metadata +94 -75
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -16,9 +16,9 @@ Delivering mail
|
|
16
16
|
require 'tuktuk'
|
17
17
|
|
18
18
|
message = {
|
19
|
-
:from
|
20
|
-
:to
|
21
|
-
:body
|
19
|
+
:from => 'you@username.com',
|
20
|
+
:to => 'user@yoursite.com',
|
21
|
+
:body => 'Hello there',
|
22
22
|
:subject => 'Hiya'
|
23
23
|
}
|
24
24
|
|
@@ -74,8 +74,8 @@ require 'tuktuk'
|
|
74
74
|
|
75
75
|
Tuktuk.options = {
|
76
76
|
:dkim => {
|
77
|
-
:domain
|
78
|
-
:selector
|
77
|
+
:domain => 'yoursite.com',
|
78
|
+
:selector => 'mailer',
|
79
79
|
:private_key => IO.read('ssl/yoursite.com.key')
|
80
80
|
}
|
81
81
|
}
|
@@ -85,13 +85,13 @@ message = { ... }
|
|
85
85
|
response, email = Tuktuk.deliver(message)
|
86
86
|
```
|
87
87
|
|
88
|
-
For DKIM to work, you need to set up
|
88
|
+
For DKIM to work, you need to set up some TXT records in your domain's DNS. You can use [this tool](http://www.socketlabs.com/domainkey-dkim-generation-wizard/) to generate the key. You should also create [SPF records](http://www.spfwizard.net/) if you haven't.
|
89
89
|
|
90
90
|
All available options, with their defaults:
|
91
91
|
|
92
92
|
``` ruby
|
93
93
|
Tuktuk.options = {
|
94
|
-
:log_to => nil, # e.g. log/mailer.log
|
94
|
+
:log_to => nil, # e.g. log/mailer.log or STDOUT
|
95
95
|
:helo_domain => nil, # your server's domain goes here
|
96
96
|
:max_workers => 0, # controls number of threads for delivering_many emails (read below)
|
97
97
|
:open_timeout => 20, # max seconds to wait for opening a connection
|
@@ -130,13 +130,17 @@ config.action_mailer.delivery_method = :tuktuk
|
|
130
130
|
config.action_mailer.tuktuk_settings = {
|
131
131
|
:log_to => 'log/mailer.log', # when not set, Tuktuk will use Rails.logger
|
132
132
|
:dkim => {
|
133
|
-
:domain
|
134
|
-
:selector
|
133
|
+
:domain => 'yoursite.com',
|
134
|
+
:selector => 'mailer',
|
135
135
|
:private_key => IO.read('ssl/yoursite.com.key')
|
136
136
|
}
|
137
137
|
}
|
138
138
|
```
|
139
139
|
|
140
|
-
|
140
|
+
# Contributions
|
141
141
|
|
142
|
-
|
142
|
+
You're more than welcome. Send a pull request, including tests, and make sure you don't break anything. That's it.
|
143
|
+
|
144
|
+
# Copyright
|
145
|
+
|
146
|
+
(c) Fork Limited. MIT license.
|
data/lib/tuktuk/bounce.rb
CHANGED
@@ -3,8 +3,8 @@ module Tuktuk
|
|
3
3
|
class Bounce < RuntimeError
|
4
4
|
|
5
5
|
HARD_BOUNCE_CODES = [
|
6
|
-
|
7
|
-
|
6
|
+
501, # Bad address syntax (eg. "i.user.@hotmail.com")
|
7
|
+
504, # mailbox is disabled
|
8
8
|
511, # sorry, no mailbox here by that name (#5.1.1 - chkuser)
|
9
9
|
540, # recipient's email account has been suspended.
|
10
10
|
550, # Requested action not taken: mailbox unavailable
|
@@ -18,19 +18,19 @@ class Bounce < RuntimeError
|
|
18
18
|
if e.is_a?(Net::SMTPFatalError) and code = e.to_s[0..2] and HARD_BOUNCE_CODES.include? code.to_i
|
19
19
|
HardBounce.new(e)
|
20
20
|
else
|
21
|
-
SoftBounce.new(e) # either soft mailbox bounce or server bounce
|
21
|
+
SoftBounce.new(e) # either soft mailbox bounce, timeout or server bounce
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def code
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
if str = to_s[0..2] and str.gsub(/[^0-9]/, '') != ''
|
27
|
+
str.to_i
|
28
|
+
end
|
29
|
+
end
|
30
30
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class HardBounce < Bounce; end
|
34
34
|
class SoftBounce < Bounce; end
|
35
35
|
|
36
|
-
end
|
36
|
+
end
|
data/lib/tuktuk/package.rb
CHANGED
@@ -20,10 +20,11 @@ module Package
|
|
20
20
|
mail = message[:html_body] ? mixed(message) : plain(message)
|
21
21
|
mail.charset = 'UTF-8'
|
22
22
|
|
23
|
-
mail['In-Reply-To']
|
24
|
-
mail['List-
|
25
|
-
mail['List-
|
26
|
-
mail['
|
23
|
+
mail['In-Reply-To'] = message[:in_reply_to] if message[:in_reply_to]
|
24
|
+
mail['List-Unsubscribe'] = message[:list_unsubscribe] if message[:list_unsubscribe]
|
25
|
+
mail['List-Archive'] = message[:list_archive] if message[:list_archive]
|
26
|
+
mail['List-Id'] = message[:list_id] if message[:list_id]
|
27
|
+
mail['X-Mailer'] = "Tuktuk SMTP v#{Tuktuk::VERSION}"
|
27
28
|
|
28
29
|
if message[:return_path]
|
29
30
|
mail['Return-Path'] = message[:return_path]
|
data/lib/tuktuk/tuktuk.rb
CHANGED
@@ -14,7 +14,7 @@ DEFAULTS = {
|
|
14
14
|
:read_timeout => 20,
|
15
15
|
:open_timeout => 20,
|
16
16
|
:verify_ssl => true,
|
17
|
-
:debug => false,
|
17
|
+
:debug => false,
|
18
18
|
:log_to => nil # $stdout,
|
19
19
|
}
|
20
20
|
|
@@ -42,7 +42,7 @@ module Tuktuk
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def deliver_many(messages, opts = {})
|
45
|
-
raise
|
45
|
+
raise ArgumentError, "Not an array of messages: #{messages.inspect}" unless messages.any?
|
46
46
|
self.options = opts if opts.any?
|
47
47
|
messages_by_domain = reorder_by_domain(messages)
|
48
48
|
lookup_and_deliver_many(messages_by_domain)
|
@@ -121,7 +121,7 @@ module Tuktuk
|
|
121
121
|
begin
|
122
122
|
response = send_now(mail, server, to)
|
123
123
|
break
|
124
|
-
rescue => e
|
124
|
+
rescue Exception => e # explicitly rescue Exception so we catch Timeout:Error's too
|
125
125
|
last_error = e
|
126
126
|
end
|
127
127
|
end
|
@@ -262,6 +262,7 @@ module Tuktuk
|
|
262
262
|
logger.warn "Debug option enabled. Connecting to localhost!"
|
263
263
|
server = 'localhost'
|
264
264
|
end
|
265
|
+
|
265
266
|
smtp = Net::SMTP.new(server, nil)
|
266
267
|
smtp.enable_starttls_auto(context)
|
267
268
|
smtp.read_timeout = config[:read_timeout] if config[:read_timeout]
|
data/lib/tuktuk/version.rb
CHANGED
data/spec/deliver_spec.rb
CHANGED
@@ -2,212 +2,214 @@ require './lib/tuktuk/tuktuk'
|
|
2
2
|
require 'rspec/mocks'
|
3
3
|
|
4
4
|
describe 'deliver' do
|
5
|
-
|
5
|
+
|
6
6
|
end
|
7
7
|
|
8
8
|
describe 'deliver many' do
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@mock_smtp = double('Net::SMTP')
|
12
|
+
Net::SMTP.stub(:new).and_return(@mock_smtp)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'when no emails are passed' do
|
16
|
+
|
17
|
+
it 'raises' do
|
18
|
+
lambda do
|
19
|
+
Tuktuk.deliver_many []
|
20
|
+
end.should raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'when one email contains multiple addresses' do
|
26
|
+
|
27
|
+
it 'raises' do
|
28
|
+
lambda do
|
29
|
+
Tuktuk.deliver_many [ email, email(:to => 'one@user.com, two@user.com')]
|
30
|
+
end.should raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'when emails are valid' do
|
36
|
+
|
37
|
+
it 'groups them by domain' do
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'and max_workers is 0' do
|
42
|
+
|
43
|
+
it 'does not start any threads' do
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'and max_workers is >0' do
|
50
|
+
|
51
|
+
it 'does not spawn any more threads than the max allowed' do
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe 'and max workers is auto' do
|
58
|
+
|
59
|
+
it 'spawns a new thread for each domain' do
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'when delivering to domain' do
|
66
|
+
|
67
|
+
before do
|
68
|
+
@mock_smtp.stub(:start).and_yield('foo')
|
69
|
+
@emails = [email, email, email]
|
70
|
+
|
71
|
+
@success = double('Net::SMTP::Response')
|
72
|
+
@soft_email_bounce = Tuktuk::SoftBounce.new('503 Sender already specified')
|
73
|
+
@hard_email_bounce = Tuktuk::HardBounce.new('505 Mailbox not found')
|
74
|
+
@soft_server_bounce = Tuktuk::SoftBounce.new('Be back in a sec')
|
75
|
+
@hard_server_bounce = Tuktuk::HardBounce.new('No MX records found.')
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'when domain exists' do
|
79
|
+
|
80
|
+
before do
|
81
|
+
@domain = 'domain.com'
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'and has valid MX servers' do
|
85
|
+
|
86
|
+
before do
|
87
|
+
@servers = ['mx1.domain.com', 'mx2.domain.com', 'mx3.domain.com']
|
88
|
+
Tuktuk.stub(:smtp_servers_for_domain).and_return(@servers)
|
89
|
+
end
|
90
|
+
|
91
|
+
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']])
|
93
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', [1])
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'and first server processes all our mail' do
|
97
|
+
|
98
|
+
describe 'and all mail goes through' do
|
99
|
+
|
100
|
+
before do
|
101
|
+
@responses = []
|
102
|
+
@emails.each { |e| @responses.push [e, @success] }
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'does not try to connect to second server' do
|
106
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return(@responses)
|
107
|
+
Tuktuk.should_not_receive(:send_many_now).with('mx2.domain.com')
|
108
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'and all emails were hard failures (bounces)' do
|
114
|
+
|
115
|
+
before do
|
116
|
+
@responses = []
|
117
|
+
@emails.each { |e| @responses.push [e, @hard_email_bounce] }
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'does not try to connect to second server' do
|
121
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return(@responses)
|
122
|
+
Tuktuk.should_not_receive(:send_many_now).with('mx2.domain.com')
|
123
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'and first server is down' do
|
131
|
+
|
132
|
+
before do
|
133
|
+
@responses = []
|
134
|
+
@emails.each { |e| @responses.push [e, @success] }
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'does not raise error' do
|
138
|
+
Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_raise('Unable to connect.')
|
139
|
+
Tuktuk.should_receive(:init_connection).once.with('mx2.domain.com').and_raise('Unable to connect.')
|
140
|
+
Tuktuk.should_receive(:init_connection).once.with('mx3.domain.com').and_raise('Unable to connect.')
|
141
|
+
# Tuktuk.should_receive(:init_connection).once.and_raise('Unable to connect.')
|
142
|
+
expect do
|
143
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
144
|
+
end.not_to raise_error # (RuntimeError)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'returns empty responses' do
|
148
|
+
Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_raise('Unable to connect.')
|
149
|
+
responses = Tuktuk.send(:send_many_now, 'mx1.domain.com', @emails)
|
150
|
+
responses.should be_empty
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'tries to connect to second server' do
|
154
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return([])
|
155
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx2.domain.com', @emails).and_return(@responses)
|
156
|
+
Tuktuk.should_not_receive(:send_many_now).with('mx3.domain.com')
|
157
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
describe 'and first server receives only one email' do
|
163
|
+
|
164
|
+
before do
|
165
|
+
@first = [@emails[0], @success]
|
166
|
+
@last_two = [[@emails[1], @success], [@emails[2], @soft_email_bounce]]
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'does not try to send that same email to second server' do
|
170
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx1.domain.com', @emails).and_return([@first])
|
171
|
+
last_two_emails = @emails.last(2)
|
172
|
+
last_two_emails.include?(@emails.first).should be_false
|
173
|
+
Tuktuk.should_receive(:send_many_now).once.with('mx2.domain.com', last_two_emails).and_return(@last_two)
|
174
|
+
Tuktuk.should_not_receive(:send_many_now).with('mx3.domain.com')
|
175
|
+
Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
176
|
+
end
|
177
|
+
|
178
|
+
describe 'and other servers are down' do
|
179
|
+
|
180
|
+
before do
|
181
|
+
# TODO: for some reason the :init_connection on line 138 is affecting this
|
182
|
+
# this test should pass when running on its own
|
183
|
+
# Tuktuk.should_receive(:init_connection).once.with('mx1.domain.com').and_return(@mock_smtp)
|
184
|
+
# Tuktuk.should_receive(:init_connection).once.with('mx2.domain.com').and_raise('Unable to connect.')
|
185
|
+
# Tuktuk.should_receive(:init_connection).once.with('mx3.domain.com').and_raise('Unable to connect.')
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should not mark first email as bounced' do
|
189
|
+
Tuktuk.should_receive(:send_many_now).and_return([@first], [], [])
|
190
|
+
responses = Tuktuk.send(:lookup_and_deliver_by_domain, 'domain.com', @emails)
|
191
|
+
responses[1][0].should be_a(Tuktuk::Bounce) if responses[1]
|
192
|
+
responses[0][0].should_not be_a(Tuktuk::Bounce)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
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
|
+
end
|
metadata
CHANGED
@@ -1,92 +1,101 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tuktuk
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 4
|
9
|
+
version: 0.5.4
|
5
10
|
platform: ruby
|
6
|
-
authors:
|
7
|
-
-
|
11
|
+
authors:
|
12
|
+
- "Tom\xC3\xA1s Pollak"
|
8
13
|
autorequire:
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
16
|
+
|
17
|
+
date: 2015-04-08 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
14
21
|
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 1.0.0
|
20
|
-
type: :development
|
21
22
|
prerelease: false
|
22
|
-
|
23
|
-
requirements:
|
24
|
-
- -
|
25
|
-
- !ruby/object:Gem::Version
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 0
|
30
|
+
- 0
|
26
31
|
version: 1.0.0
|
27
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
28
35
|
name: net-dns
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.6.1
|
34
|
-
type: :runtime
|
35
36
|
prerelease: false
|
36
|
-
|
37
|
-
requirements:
|
38
|
-
- -
|
39
|
-
- !ruby/object:Gem::Version
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 6
|
44
|
+
- 1
|
40
45
|
version: 0.6.1
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: mail
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ~>
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '2.3'
|
48
46
|
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: mail
|
49
50
|
prerelease: false
|
50
|
-
|
51
|
-
requirements:
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
52
53
|
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
-
|
56
|
-
|
57
|
-
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 0.0.2
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 2
|
57
|
+
- 3
|
58
|
+
version: "2.3"
|
62
59
|
type: :runtime
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: dkim
|
63
63
|
prerelease: false
|
64
|
-
|
65
|
-
requirements:
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
66
|
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
segments:
|
69
|
+
- 0
|
70
|
+
- 0
|
71
|
+
- 2
|
68
72
|
version: 0.0.2
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: work_queue
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ~>
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 2.5.0
|
76
73
|
type: :runtime
|
74
|
+
version_requirements: *id004
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: work_queue
|
77
77
|
prerelease: false
|
78
|
-
|
79
|
-
requirements:
|
78
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
80
|
- - ~>
|
81
|
-
- !ruby/object:Gem::Version
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 2
|
84
|
+
- 5
|
85
|
+
- 0
|
82
86
|
version: 2.5.0
|
87
|
+
type: :runtime
|
88
|
+
version_requirements: *id005
|
83
89
|
description: Easy way of sending DKIM-signed emails from Ruby, no dependencies needed.
|
84
|
-
email:
|
90
|
+
email:
|
85
91
|
- tomas@forkhq.com
|
86
92
|
executables: []
|
93
|
+
|
87
94
|
extensions: []
|
95
|
+
|
88
96
|
extra_rdoc_files: []
|
89
|
-
|
97
|
+
|
98
|
+
files:
|
90
99
|
- .gitignore
|
91
100
|
- Gemfile
|
92
101
|
- README.md
|
@@ -101,27 +110,37 @@ files:
|
|
101
110
|
- lib/tuktuk/version.rb
|
102
111
|
- spec/deliver_spec.rb
|
103
112
|
- tuktuk.gemspec
|
113
|
+
has_rdoc: true
|
104
114
|
homepage: https://github.com/tomas/tuktuk
|
105
115
|
licenses: []
|
106
|
-
|
116
|
+
|
107
117
|
post_install_message:
|
108
118
|
rdoc_options: []
|
109
|
-
|
119
|
+
|
120
|
+
require_paths:
|
110
121
|
- lib
|
111
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
-
requirements:
|
113
|
-
- -
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
version: "0"
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
segments:
|
134
|
+
- 1
|
135
|
+
- 3
|
136
|
+
- 6
|
120
137
|
version: 1.3.6
|
121
138
|
requirements: []
|
139
|
+
|
122
140
|
rubyforge_project: tuktuk
|
123
|
-
rubygems_version:
|
141
|
+
rubygems_version: 1.3.6
|
124
142
|
signing_key:
|
125
|
-
specification_version:
|
143
|
+
specification_version: 3
|
126
144
|
summary: SMTP client for Ruby with DKIM support.
|
127
145
|
test_files: []
|
146
|
+
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 2d959f61646d7f24739699b467abdd6d3b11a1aa
|
4
|
-
data.tar.gz: 1fd5e0c66ee7aabd178810a0877964913898d5eb
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: c5a744fbeab5b4a3316b822d898052c151f495193918ecc029505ff1fd71c53ba3fc55619a9f74f05ed179f8fec89d62303c80c627fb59b80a554d7f5c02c93b
|
7
|
-
data.tar.gz: f705920b165a4b872003373dc838000a05f5704879515211e2160aaa339c194c76a35b5c187006d78e499f2586679b4e3c2da7b3bfa42d85020df2550aec6b53
|