tuktuk 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f62d4bf43a7a59fc76ce9fec973740c593a40914
4
+ data.tar.gz: dd1bc1790077737e8d9c7c7b05f838bf8e2f2fed
5
+ SHA512:
6
+ metadata.gz: 067e0525fcf6209b3a7023c123a7d7972cf7587b46c73a2e7100dde5e7cba23175e0f5a9afc9cbf73cce6a6b7de5da6355be06e1bf6f9895b7b1c9a65304fc1b
7
+ data.tar.gz: 454def2bcb6549622b77bc7c1668240d87176c98efca5e178a2d3a6f8c7f8e6b64f65d487d999236aa49a767d669a6618200660fd832b18c54a0dc36778e0df0
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  Tuktuk - SMTP client for Ruby
2
2
  =============================
3
3
 
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
4
+ Unlike famous ol' Pony gem (which is friggin' awesome by the way), Tuktuk does not rely on
5
+ `sendmail` or a separate SMTP server in order to deliver email. Tuktuk looks up the
6
6
  MX servers of the destination address and connects directly using Net::SMTP.
7
7
  This way you don't need to install Exim or Postfix and you can actually handle
8
8
  response status codes -- like bounces, 5xx -- within your application.
@@ -32,7 +32,7 @@ The `response` is either a Net::SMTP::Response object, or a Bounce exception (Ha
32
32
 
33
33
  response, email = Tuktuk.deliver(message)
34
34
 
35
- if response.is_a?(Bounce)
35
+ if response.is_a?(Tuktuk::Bounce)
36
36
  puts 'Email bounced. Type: ' + response.class.name # => HardBounce or SoftBounce
37
37
  else
38
38
  puts 'Email delivered!'
@@ -55,7 +55,7 @@ result = Tuktuk.deliver_many(messages)
55
55
 
56
56
  result.each do |response, email|
57
57
 
58
- if response.is_a?(Bounce)
58
+ if response.is_a?(Tuktuk::Bounce)
59
59
  puts 'Email bounced. Type: ' + response.class.name
60
60
  else
61
61
  puts 'Email delivered!'
@@ -87,18 +87,55 @@ response, email = Tuktuk.deliver(message)
87
87
 
88
88
  For DKIM to work, you need to set up a TXT record in your domain's DNS.
89
89
 
90
- Additional Tuktuk options:
90
+ All available options, with their defaults:
91
91
 
92
92
  ``` ruby
93
93
  Tuktuk.options = {
94
- :log_to => 'log/mailer.log',
95
- :helo_domain => 'mydomain.com',
96
- :max_workers => 'auto', # spawns a new thread for each domain
94
+ :log_to => nil, # e.g. log/mailer.log
95
+ :helo_domain => nil, # your server's domain goes here
96
+ :max_workers => 0, # controls number of threads for delivering_many emails (read below)
97
+ :open_timeout => 20, # max seconds to wait for opening a connection
98
+ :read_timeout => 20, # 20 seconds to wait for a response, once connected
99
+ :verify_ssl => true, # whether to skip SSL keys verification or not
100
+ :debug => false, # connects and delivers email to localhost, instead of real target server. CAUTION!
97
101
  :dkim => { ... }
98
102
  }
99
103
  ```
100
104
 
101
- That's all.
105
+ You can set the `max_threads` option to `auto`, which will spawn the necessary threads to connect in paralell to all target MX servers when delivering multiple messages. When set to `0`, these batches will be delivered sequentially.
106
+
107
+ In other words, if you have three emails targeted to Gmail users and two for Hotmail users, using `auto` Tuktuk will spawn two threads and connect to both servers at once. Using `0` will have email deliveried to one host and then the other.
108
+
109
+ Using with Rails
110
+ ----------------
111
+
112
+ Tuktuk comes with ActionMailer support out of the box. In your environment.rb or environments/{env}.rb:
113
+
114
+ ``` ruby
115
+ require 'tuktuk/rails'
116
+
117
+ [...]
118
+
119
+ config.action_mailer.delivery_method = :tuktuk
120
+ ```
121
+
122
+ Since Tuktuk delivers email directly to the user's MX servers, it's probably a good idea to set `config.action_mailer.raise_delivery_errors` to true. That way you can actually know if an email couldn't make it to its destination.
123
+
124
+ When used with ActionMailer, you can pass options using ActionMailer's interface, like this:
125
+
126
+ ``` ruby
127
+
128
+ config.action_mailer.delivery_method = :tuktuk
129
+
130
+ config.action_mailer.tuktuk_settings = {
131
+ :log_to => 'log/mailer.log', # when not set, Tuktuk will use Rails.logger
132
+ :dkim => {
133
+ :domain => 'yoursite.com',
134
+ :selector => 'mailer',
135
+ :private_key => IO.read('ssl/yoursite.com.key')
136
+ }
137
+ }
138
+ ```
102
139
 
103
140
  --
104
141
 
@@ -9,22 +9,33 @@ module Tuktuk
9
9
  module Package
10
10
 
11
11
  class << self
12
+
13
+ def build(message, index = nil)
14
+ mail = message.is_a?(Hash) ? new(message) : message.is_a?(Mail) ? message : Mail.read_from_string(message.to_s)
15
+ mail.array_index = index if index
16
+ mail
17
+ end
12
18
 
13
- def new(message, index = nil)
19
+ def new(message)
14
20
  mail = message[:html_body] ? mixed(message) : plain(message)
15
- mail.array_index = index if index
16
21
  mail.charset = 'UTF-8'
17
22
 
18
- mail['In-Reply-To'] = message[:in_reply_to] if message[:in_reply_to]
19
- mail['List-Archive'] = message[:list_archive] if message[:list_archive]
20
- mail['List-Id'] = message[:list_id] if message[:list_id]
21
- mail['X-Mailer'] = "Tuktuk SMTP v#{Tuktuk::VERSION}"
23
+ mail['In-Reply-To'] = message[:in_reply_to] if message[:in_reply_to]
24
+ mail['List-Archive'] = message[:list_archive] if message[:list_archive]
25
+ mail['List-Id'] = message[:list_id] if message[:list_id]
26
+ mail['X-Mailer'] = "Tuktuk SMTP v#{Tuktuk::VERSION}"
22
27
 
23
28
  if message[:return_path]
24
29
  mail['Return-Path'] = message[:return_path]
25
30
  mail['Bounces-To'] = message[:return_path]
26
31
  mail['Errors-To'] = message[:return_path]
27
32
  end
33
+
34
+ if message[:attachments].any?
35
+ message[:attachments].each do |file|
36
+ mail.add_file(file)
37
+ end
38
+ end
28
39
 
29
40
  mail
30
41
  end
@@ -0,0 +1,30 @@
1
+ if ActionMailer::Base.respond_to?(:add_delivery_method)
2
+
3
+ ActionMailer::Base.add_delivery_method :tuktuk, Tuktuk
4
+
5
+ module Tuktuk
6
+
7
+ def self.new(options)
8
+ self.options = options
9
+ self
10
+ end
11
+
12
+ end
13
+
14
+ else
15
+
16
+ require 'tuktuk'
17
+
18
+ class ActionMailer::Base
19
+
20
+ def self.tuktuk_settings=(opts)
21
+ Tuktuk.options = opts
22
+ end
23
+
24
+ def perform_delivery_tuktuk(mail)
25
+ Tuktuk.deliver!(mail)
26
+ end
27
+
28
+ end
29
+
30
+ end
data/lib/tuktuk/tuktuk.rb CHANGED
@@ -14,6 +14,7 @@ DEFAULTS = {
14
14
  :read_timeout => 20,
15
15
  :open_timeout => 20,
16
16
  :verify_ssl => true,
17
+ :debug => false,
17
18
  :log_to => nil # $stdout,
18
19
  }
19
20
 
@@ -26,13 +27,20 @@ module Tuktuk
26
27
  end
27
28
 
28
29
  def deliver(message, opts = {})
29
- raise 'Please pass a valid message object.' unless messages[:to]
30
+ # raise 'Please pass a valid message object.' unless message[:to]
30
31
  self.options = opts if opts.any?
31
- mail = Package.new(message)
32
+ mail = Package.build(message)
32
33
  response = lookup_and_deliver(mail)
33
34
  return response, mail
34
35
  end
35
36
 
37
+ # same as deliver but raises error. used by ActionMailer
38
+ def deliver!(mail)
39
+ @logger = Rails.logger if defined?(Rails) and !config[:log_to]
40
+ resp, email = deliver(mail)
41
+ raise resp if resp.is_a?(Exception)
42
+ end
43
+
36
44
  def deliver_many(messages, opts = {})
37
45
  raise 'Please pass an array of messages.' unless messages.any?
38
46
  self.options = opts if opts.any?
@@ -74,7 +82,7 @@ module Tuktuk
74
82
  def reorder_by_domain(array)
75
83
  hash = {}
76
84
  array.each_with_index do |message, i|
77
- mail = Package.new(message, i)
85
+ mail = Package.build(message, i)
78
86
  raise "Invalid destination count: #{mail.destinations.count}" if mail.destinations.count != 1
79
87
 
80
88
  if to = mail.destinations.first and domain = get_domain(to)
@@ -199,7 +207,6 @@ module Tuktuk
199
207
  from = get_from(mail)
200
208
 
201
209
  response = nil
202
- server = 'localhost' if ENV['DEBUG']
203
210
  socket = init_connection(server)
204
211
  socket.start(get_helo_domain(from), nil, nil, nil) do |smtp|
205
212
  response = smtp.send_message(get_raw_mail(mail), from, to)
@@ -213,7 +220,6 @@ module Tuktuk
213
220
  logger.info "Delivering #{mails.count} mails at #{server}..."
214
221
  responses = {}
215
222
 
216
- server = 'localhost' if ENV['DEBUG']
217
223
  socket = init_connection(server)
218
224
  socket.start(get_helo_domain, nil, nil, nil) do |smtp|
219
225
  mails.each do |mail|
@@ -230,8 +236,8 @@ module Tuktuk
230
236
 
231
237
  responses
232
238
  rescue => e # SMTPServerBusy, SMTPSyntaxError, SMTPUnsupportedCommand, SMTPUnknownError (unexpected reply code)
233
- logger.error "[SERVER ERROR: #{server}] #{e.message}"
234
- @last_error = e
239
+ logger.error "[SERVER ERROR: #{server}] #{e.message}"
240
+ @last_error = e
235
241
  responses
236
242
  end
237
243
 
@@ -252,6 +258,10 @@ module Tuktuk
252
258
  context.verify_mode = config[:verify_ssl] ?
253
259
  OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
254
260
 
261
+ if config[:debug]
262
+ logger.warn "Debug option enabled. Connecting to localhost!"
263
+ server = 'localhost'
264
+ end
255
265
  smtp = Net::SMTP.new(server, nil)
256
266
  smtp.enable_starttls_auto(context)
257
267
  smtp.read_timeout = config[:read_timeout] if config[:read_timeout]
@@ -1,7 +1,7 @@
1
1
  module Tuktuk
2
2
  MAJOR = 0
3
3
  MINOR = 5
4
- PATCH = 1
4
+ PATCH = 2
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tuktuk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
5
- prerelease:
4
+ version: 0.5.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tomás Pollak
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-27 00:00:00.000000000 Z
11
+ date: 2013-08-06 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.0.0
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: 1.0.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: net-dns
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - '='
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - '='
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: mail
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,7 +48,6 @@ dependencies:
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
@@ -62,7 +55,6 @@ dependencies:
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: dkim
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: work_queue
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,7 +76,6 @@ dependencies:
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
@@ -107,32 +96,32 @@ files:
107
96
  - lib/tuktuk/cache.rb
108
97
  - lib/tuktuk/dns.rb
109
98
  - lib/tuktuk/package.rb
99
+ - lib/tuktuk/rails.rb
110
100
  - lib/tuktuk/tuktuk.rb
111
101
  - lib/tuktuk/version.rb
112
102
  - spec/deliver_spec.rb
113
103
  - tuktuk.gemspec
114
104
  homepage: https://github.com/tomas/tuktuk
115
105
  licenses: []
106
+ metadata: {}
116
107
  post_install_message:
117
108
  rdoc_options: []
118
109
  require_paths:
119
110
  - lib
120
111
  required_ruby_version: !ruby/object:Gem::Requirement
121
- none: false
122
112
  requirements:
123
- - - ! '>='
113
+ - - '>='
124
114
  - !ruby/object:Gem::Version
125
115
  version: '0'
126
116
  required_rubygems_version: !ruby/object:Gem::Requirement
127
- none: false
128
117
  requirements:
129
- - - ! '>='
118
+ - - '>='
130
119
  - !ruby/object:Gem::Version
131
120
  version: 1.3.6
132
121
  requirements: []
133
122
  rubyforge_project: tuktuk
134
- rubygems_version: 1.8.23
123
+ rubygems_version: 2.0.2
135
124
  signing_key:
136
- specification_version: 3
125
+ specification_version: 4
137
126
  summary: SMTP client for Ruby with DKIM support.
138
127
  test_files: []