tuktuk 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -6
- data/lib/tuktuk/cache.rb +28 -0
- data/lib/tuktuk/tuktuk.rb +21 -6
- data/lib/tuktuk/version.rb +1 -1
- data/tuktuk.gemspec +1 -1
- metadata +6 -5
data/README.md
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
Tuktuk - SMTP client for Ruby
|
2
2
|
=============================
|
3
3
|
|
4
|
-
|
4
|
+
Unlike Pony (which is friggin' awesome by the way) Tuktuk does not rely on
|
5
|
+
`sendmail` or a separate SMTP server in order to send email. Tuktuk looks up the
|
6
|
+
MX servers of the destination address and connects directly using Net::SMTP.
|
7
|
+
This way you don't need to install Exim or Postfix and you can actually handle
|
8
|
+
response status codes -- like bounces, 5xx -- within your application.
|
9
|
+
|
10
|
+
Plus, it supports DKIM out of the box.
|
11
|
+
|
12
|
+
``` ruby
|
5
13
|
require 'tuktuk'
|
6
14
|
|
7
15
|
email = {
|
@@ -12,11 +20,11 @@ Tuktuk - SMTP client for Ruby
|
|
12
20
|
}
|
13
21
|
|
14
22
|
Tuktuk.deliver(email)
|
15
|
-
|
23
|
+
```
|
16
24
|
|
17
25
|
To enable DKIM:
|
18
26
|
|
19
|
-
|
27
|
+
``` ruby
|
20
28
|
require 'tuktuk'
|
21
29
|
|
22
30
|
Tuktuk.options = {
|
@@ -35,18 +43,18 @@ To enable DKIM:
|
|
35
43
|
}
|
36
44
|
|
37
45
|
Tuktuk.deliver(email)
|
38
|
-
|
46
|
+
```
|
39
47
|
|
40
48
|
Additional options:
|
41
49
|
|
42
|
-
|
50
|
+
``` ruby
|
43
51
|
Tuktuk.options = {
|
44
52
|
:log_to => 'log/mailer.log',
|
45
53
|
:max_attempts => 5,
|
46
54
|
:retry_sleep => 10,
|
47
55
|
:dkim => { ... }
|
48
56
|
}
|
49
|
-
|
57
|
+
```
|
50
58
|
|
51
59
|
That's all.
|
52
60
|
|
data/lib/tuktuk/cache.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class Cache
|
2
|
+
|
3
|
+
attr_reader :store, :max_keys
|
4
|
+
|
5
|
+
def initialize(max_keys = 1000)
|
6
|
+
@store = {}
|
7
|
+
@max_keys = max_keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(key)
|
11
|
+
store[key]
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(key, value)
|
15
|
+
return if store[key] == value
|
16
|
+
pop if store.length > max_keys
|
17
|
+
store[key] = value
|
18
|
+
end
|
19
|
+
|
20
|
+
def pop
|
21
|
+
store.delete(store.keys.last)
|
22
|
+
end
|
23
|
+
|
24
|
+
def show
|
25
|
+
store.each { |k,v| puts "#{k} -> #{v}" }; nil
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/lib/tuktuk/tuktuk.rb
CHANGED
@@ -3,10 +3,12 @@ require 'net/dns/resolver'
|
|
3
3
|
require 'dkim'
|
4
4
|
require 'logger'
|
5
5
|
require 'tuktuk/package'
|
6
|
+
require 'tuktuk/cache'
|
6
7
|
|
7
8
|
DEFAULTS = {
|
8
9
|
:retry_sleep => 10,
|
9
10
|
:max_attempts => 3,
|
11
|
+
:read_timeout => nil,
|
10
12
|
:verify_ssl => true,
|
11
13
|
:log_to => nil # $stdout,
|
12
14
|
}
|
@@ -18,6 +20,10 @@ module Tuktuk
|
|
18
20
|
|
19
21
|
class << self
|
20
22
|
|
23
|
+
def cache
|
24
|
+
@cache ||= Cache.new(100)
|
25
|
+
end
|
26
|
+
|
21
27
|
def deliver(message, opts = {})
|
22
28
|
self.options = opts if opts.any?
|
23
29
|
mail = Package.new(message)
|
@@ -61,8 +67,8 @@ module Tuktuk
|
|
61
67
|
logger.info("#{to} - Successfully sent!")
|
62
68
|
end
|
63
69
|
|
64
|
-
def error(mail, to, error, attempt
|
65
|
-
if attempt
|
70
|
+
def error(mail, to, error, attempt)
|
71
|
+
if attempt < config[:max_attempts] and (error.is_a?(EOFError) || error.is_a?(TimeoutError))
|
66
72
|
logger.info "#{to} - Got #{error.class.name} error. Retrying after #{config[:retry_sleep]} secs..."
|
67
73
|
sleep config[:retry_sleep]
|
68
74
|
lookup_and_deliver(mail, attempt+1)
|
@@ -73,11 +79,19 @@ module Tuktuk
|
|
73
79
|
end
|
74
80
|
|
75
81
|
def smtp_servers_for_domain(domain)
|
76
|
-
|
77
|
-
|
82
|
+
unless servers = cache.get(domain)
|
83
|
+
if servers = lookup_smtp_servers(domain) and servers.any?
|
84
|
+
cache.set(domain, servers)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
servers
|
88
|
+
end
|
89
|
+
|
90
|
+
def lookup_smtp_servers(domain)
|
91
|
+
if mx = Net::DNS::Resolver.new.mx(domain)
|
78
92
|
mx.sort {|x,y| x.preference <=> y.preference}.map {|rr| rr.exchange}
|
79
93
|
else
|
80
|
-
raise DNSError, "
|
94
|
+
raise DNSError, "No MX records found for domain #{domain}."
|
81
95
|
end
|
82
96
|
end
|
83
97
|
|
@@ -89,7 +103,7 @@ module Tuktuk
|
|
89
103
|
|
90
104
|
domain = get_domain(to)
|
91
105
|
servers = smtp_servers_for_domain(domain)
|
92
|
-
error(mail, to, DNSError.new("Unknown host: #{domain}")) && next if servers.empty?
|
106
|
+
error(mail, to, DNSError.new("Unknown host: #{domain}"), attempt) && next if servers.empty?
|
93
107
|
|
94
108
|
last_error = nil
|
95
109
|
servers.each do |server|
|
@@ -118,6 +132,7 @@ module Tuktuk
|
|
118
132
|
|
119
133
|
smtp = Net::SMTP.new(server, nil)
|
120
134
|
smtp.enable_starttls_auto(context)
|
135
|
+
smtp.read_timeout = config[:read_timeout] if config[:read_timeout]
|
121
136
|
|
122
137
|
response = nil
|
123
138
|
smtp.start(helo_domain, nil, nil, nil) do |smtp|
|
data/lib/tuktuk/version.rb
CHANGED
data/tuktuk.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ['tomas@forkhq.com']
|
10
10
|
s.homepage = "https://github.com/tomas/tuktuk"
|
11
11
|
s.summary = "SMTP client for Ruby with DKIM support."
|
12
|
-
s.description = "Easy way of sending DKIM-signed emails from Ruby, no
|
12
|
+
s.description = "Easy way of sending DKIM-signed emails from Ruby, no dependencies needed."
|
13
13
|
|
14
14
|
s.required_rubygems_version = ">= 1.3.6"
|
15
15
|
s.rubyforge_project = "tuktuk"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tuktuk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Tom\xC3\xA1s Pollak"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-07-13 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: bundler
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
version: 0.0.2
|
81
81
|
type: :runtime
|
82
82
|
version_requirements: *id004
|
83
|
-
description: Easy way of sending DKIM-signed emails from Ruby, no
|
83
|
+
description: Easy way of sending DKIM-signed emails from Ruby, no dependencies needed.
|
84
84
|
email:
|
85
85
|
- tomas@forkhq.com
|
86
86
|
executables: []
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- README.md
|
96
96
|
- Rakefile
|
97
97
|
- lib/tuktuk.rb
|
98
|
+
- lib/tuktuk/cache.rb
|
98
99
|
- lib/tuktuk/package.rb
|
99
100
|
- lib/tuktuk/tuktuk.rb
|
100
101
|
- lib/tuktuk/version.rb
|