tuktuk 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|