tuktuk 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *~
2
+ *.gem
2
3
  test
3
4
  log
4
5
  pkg
data/README.md CHANGED
@@ -19,10 +19,12 @@ To enable DKIM:
19
19
  ````
20
20
  require 'tuktuk'
21
21
 
22
- Tuktuk.dkim = {
22
+ Tuktuk.options = {
23
+ :dkim => {
23
24
  :domain => 'yoursite.com',
24
25
  :selector => 'mailer',
25
26
  :private_key => IO.read('ssl/yoursite.com.key')
27
+ }
26
28
  }
27
29
 
28
30
  email = {
@@ -35,6 +37,17 @@ To enable DKIM:
35
37
  Tuktuk.deliver(email)
36
38
  ````
37
39
 
40
+ Additional options:
41
+
42
+ ````
43
+ Tuktuk.options = {
44
+ :log_to => 'log/mailer.log',
45
+ :max_attempts => 5,
46
+ :retry_sleep => 10,
47
+ :dkim => { ... }
48
+ }
49
+ ````
50
+
38
51
  That's all.
39
52
 
40
53
  --
data/lib/tuktuk/tuktuk.rb CHANGED
@@ -7,19 +7,22 @@ require 'tuktuk/package'
7
7
  DEFAULTS = {
8
8
  :retry_sleep => 10,
9
9
  :max_attempts => 3,
10
- :mailer => "Tuktuk SMTP #{VERSION}"
10
+ :log_to => nil # $stdout
11
11
  }
12
12
 
13
13
  module Tuktuk
14
14
 
15
+ class DNSError < RuntimeError; end
16
+ class MissingFieldsError < ArgumentError; end
17
+
15
18
  class << self
16
19
 
17
20
  def deliver(message, opts = {})
18
21
  options = opts
19
22
  mail = Package.new(message)
20
- mail['X-Mailer'] = config[:mailer]
21
- lookup_and_deliver(mail)
22
- mail
23
+ mail['X-Mailer'] = "Tuktuk SMTP v#{VERSION}"
24
+ response = lookup_and_deliver(mail)
25
+ return response, mail
23
26
  end
24
27
 
25
28
  def options=(hash)
@@ -30,7 +33,6 @@ module Tuktuk
30
33
  end
31
34
 
32
35
  def dkim=(dkim_opts)
33
- # logger.info "Enabling DKIM for domain #{dkim_opts[:domain]}..."
34
36
  Dkim::domain = dkim_opts[:domain]
35
37
  Dkim::selector = dkim_opts[:selector]
36
38
  Dkim::private_key = dkim_opts[:private_key]
@@ -47,11 +49,11 @@ module Tuktuk
47
49
  end
48
50
 
49
51
  def logger
50
- @logger ||= Logger.new(config[:logfile])
52
+ @logger ||= Logger.new(config[:log_to])
51
53
  end
52
54
 
53
55
  def get_domain(email_address)
54
- email_address && email_address[/@([a-z0-9\._-]+)/i, 1]
56
+ email_address && email_address.to_s[/@([a-z0-9\._-]+)/i, 1]
55
57
  end
56
58
 
57
59
  def success(destination)
@@ -64,9 +66,8 @@ module Tuktuk
64
66
  sleep config[:retry_sleep]
65
67
  lookup_and_deliver(mail, attempt+1)
66
68
  else
67
- error_message = error.respond_to?(:message) ? "#{error.message} [#{error.class.name}]" : error
68
- logger.error("#{to} - Error: #{error_message}")
69
- raise "Unable to send to #{to}: #{error_message}"
69
+ logger.error("#{to} - Unable to send after #{attempt} attempts: #{error.message} [#{error.class.name}]")
70
+ raise error
70
71
  end
71
72
  end
72
73
 
@@ -75,51 +76,55 @@ module Tuktuk
75
76
  if mx = res.mx(domain)
76
77
  mx.sort {|x,y| x.preference <=> y.preference}.map {|rr| rr.exchange}
77
78
  else
78
- raise RuntimeError, "Could not locate MX records for domain #{domain}."
79
+ raise DNSError, "Could not locate MX records for domain #{domain}."
79
80
  end
80
81
  end
81
82
 
82
83
  def lookup_and_deliver(mail, attempt = 1)
83
- raise "No destinations found! Forgot to pass the to: field?" if mail.destinations.empty?
84
+ raise MissingFieldsError, "No destinations found! You need to pass a :to field." if mail.destinations.empty?
84
85
 
85
- mail.destinations.each do |destination|
86
+ response = nil
87
+ mail.destinations.each do |to|
86
88
 
87
- domain = get_domain(destination)
89
+ domain = get_domain(to)
88
90
  servers = smtp_servers_for_domain(domain)
89
- error(mail, destination, "Unknown host: #{domain}") && next if servers.empty?
91
+ error(mail, to, DNSError.new("Unknown host: #{domain}")) && next if servers.empty?
90
92
 
91
93
  last_error = nil
92
94
  servers.each do |server|
93
95
  begin
94
- send_now(mail, server, destination)
96
+ response = send_now(mail, server, to)
95
97
  break
96
98
  rescue => e
97
99
  last_error = e
98
100
  end
99
101
  end
100
- error(mail, destination, last_error, attempt) if last_error
102
+ error(mail, to, last_error, attempt) if last_error
101
103
  end
104
+ response
102
105
  end
103
106
 
104
107
  def send_now(mail, server, to)
105
- raw_mail = use_dkim? ? Dkim.sign(mail.to_s).to_s : mail.to_s
108
+ logger.info "#{to} - Delivering email at #{server}..."
106
109
 
110
+ raw_mail = use_dkim? ? Dkim.sign(mail.to_s).to_s : mail.to_s
107
111
  from = mail.return_path || mail.sender || mail.from_addrs.first
108
- logger.info "#{to} - Delivering email at #{server}..."
112
+ helo_domain = Dkim::domain || config[:helo_domain] || get_domain(from)
109
113
 
110
114
  context = OpenSSL::SSL::SSLContext.new
111
115
  context.verify_mode = OpenSSL::SSL::VERIFY_NONE # OpenSSL::SSL::VERIFY_PEER
112
116
 
113
- helo_domain = config[:helo_domain] || Dkim::domain || get_domain(mail[:from])
114
-
115
117
  smtp = Net::SMTP.new(server, nil)
116
118
  smtp.enable_starttls_auto(context)
119
+
120
+ response = nil
117
121
  smtp.start(helo_domain, nil, nil, nil) do |smtp|
118
- result = smtp.send_message(raw_mail, from, to)
119
- logger.info "#{to} - #{result.string.strip}"
122
+ response = smtp.send_message(raw_mail, from, to)
123
+ logger.info "#{to} - #{response.message.strip}"
120
124
  end
121
125
 
122
126
  success(to)
127
+ response
123
128
  end
124
129
 
125
130
  end
@@ -1,7 +1,7 @@
1
1
  module Tuktuk
2
2
  MAJOR = 0
3
- MINOR = 1
4
- PATCH = 3
3
+ MINOR = 2
4
+ PATCH = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
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: 29
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
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-01 00:00:00 Z
18
+ date: 2012-06-02 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: bundler