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 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
 
@@ -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 = 1)
65
- if attempt <= config[:max_attempts] && (error.is_a?(Net::SMTPServerBusy) or error.is_a?(EOFError))
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
- res = Net::DNS::Resolver.new
77
- if mx = res.mx(domain)
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, "Could not locate MX records for domain #{domain}."
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|
@@ -1,7 +1,7 @@
1
1
  module Tuktuk
2
2
  MAJOR = 0
3
3
  MINOR = 2
4
- PATCH = 1
4
+ PATCH = 2
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
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 depenencies needed."
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: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
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-06-02 00:00:00 Z
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 depenencies needed.
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