adzap-ar_mailer 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/smtp_tls.rb ADDED
@@ -0,0 +1,105 @@
1
+ # Original code believed public domain from ruby-talk or ruby-core email.
2
+ # Modifications by Kyle Maxwell <kyle@kylemaxwell.com> used under MIT license.
3
+
4
+ require "openssl"
5
+ require "net/smtp"
6
+
7
+ # :stopdoc:
8
+
9
+ class Net::SMTP
10
+
11
+ class << self
12
+ send :remove_method, :start
13
+ end
14
+
15
+ def self.start( address, port = nil,
16
+ helo = 'localhost.localdomain',
17
+ user = nil, secret = nil, authtype = nil, use_tls = false,
18
+ &block) # :yield: smtp
19
+ new(address, port).start(helo, user, secret, authtype, use_tls, &block)
20
+ end
21
+
22
+ alias tls_old_start start
23
+
24
+ def start( helo = 'localhost.localdomain',
25
+ user = nil, secret = nil, authtype = nil, use_tls = false ) # :yield: smtp
26
+ start_method = use_tls ? :do_tls_start : :do_start
27
+ if block_given?
28
+ begin
29
+ send start_method, helo, user, secret, authtype
30
+ return yield(self)
31
+ ensure
32
+ do_finish
33
+ end
34
+ else
35
+ send start_method, helo, user, secret, authtype
36
+ return self
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def do_tls_start(helodomain, user, secret, authtype)
43
+ raise IOError, 'SMTP session already started' if @started
44
+ check_auth_args user, secret, authtype if user or secret
45
+
46
+ sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
47
+ @socket = Net::InternetMessageIO.new(sock)
48
+ @socket.read_timeout = 60 #@read_timeout
49
+ @socket.debug_output = STDERR #@debug_output
50
+
51
+ check_response(critical { recv_response() })
52
+ do_helo(helodomain)
53
+
54
+ raise 'openssl library not installed' unless defined?(OpenSSL)
55
+ starttls
56
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
57
+ ssl.sync_close = true
58
+ ssl.connect
59
+ @socket = Net::InternetMessageIO.new(ssl)
60
+ @socket.read_timeout = 60 #@read_timeout
61
+ @socket.debug_output = STDERR #@debug_output
62
+ do_helo(helodomain)
63
+
64
+ authenticate user, secret, authtype if user
65
+ @started = true
66
+ ensure
67
+ unless @started
68
+ # authentication failed, cancel connection.
69
+ @socket.close if not @started and @socket and not @socket.closed?
70
+ @socket = nil
71
+ end
72
+ end
73
+
74
+ def do_helo(helodomain)
75
+ begin
76
+ if @esmtp
77
+ ehlo helodomain
78
+ else
79
+ helo helodomain
80
+ end
81
+ rescue Net::ProtocolError
82
+ if @esmtp
83
+ @esmtp = false
84
+ @error_occured = false
85
+ retry
86
+ end
87
+ raise
88
+ end
89
+ end
90
+
91
+ def starttls
92
+ getok('STARTTLS')
93
+ end
94
+
95
+ alias tls_old_quit quit
96
+
97
+ def quit
98
+ begin
99
+ getok('QUIT')
100
+ rescue EOFError
101
+ end
102
+ end
103
+
104
+ end unless Net::SMTP.private_method_defined? :do_tls_start or
105
+ Net::SMTP.method_defined? :tls?
data/share/ar_sendmail ADDED
@@ -0,0 +1,30 @@
1
+ #!/bin/sh
2
+ # PROVIDE: ar_sendmail
3
+ # REQUIRE: DAEMON
4
+ # BEFORE: LOGIN
5
+ # KEYWORD: FreeBSD shutdown
6
+
7
+ #
8
+ # Add the following lines to /etc/rc.conf to enable ar_sendmail:
9
+ #
10
+ #ar_sendmail_enable="YES"
11
+
12
+ . /etc/rc.subr
13
+
14
+ name="ar_sendmail"
15
+ rcvar=`set_rcvar`
16
+
17
+ command="/usr/local/bin/ar_sendmail"
18
+ command_interpreter="/usr/local/bin/ruby18"
19
+
20
+ # set defaults
21
+
22
+ ar_sendmail_rails_env=${ar_sendmail_rails_env:-"production"}
23
+ ar_sendmail_chdir=${ar_sendmail_chdir:-"/"}
24
+ ar_sendmail_enable=${ar_sendmail_enable:-"NO"}
25
+ ar_sendmail_flags=${ar_sendmail_flags:-"-d"}
26
+
27
+ load_rc_config $name
28
+ export RAILS_ENV=$ar_sendmail_rails_env
29
+ run_rc_command "$1"
30
+
@@ -0,0 +1,185 @@
1
+ require 'net/smtp'
2
+ require 'smtp_tls'
3
+ require 'time'
4
+
5
+ class Net::SMTP
6
+
7
+ @reset_called = 0
8
+
9
+ @deliveries = []
10
+
11
+ @send_message_block = nil
12
+
13
+ @start_block = nil
14
+
15
+ class << self
16
+
17
+ attr_reader :deliveries
18
+ attr_reader :send_message_block
19
+ attr_accessor :reset_called
20
+
21
+ send :remove_method, :start
22
+
23
+ end
24
+
25
+ def self.start(*args)
26
+ @start_block.call if @start_block
27
+ yield new(nil)
28
+ end
29
+
30
+ def self.on_send_message(&block)
31
+ @send_message_block = block
32
+ end
33
+
34
+ def self.on_start(&block)
35
+ @start_block = block
36
+ end
37
+
38
+ def self.reset
39
+ deliveries.clear
40
+ on_start
41
+ on_send_message
42
+ @reset_called = 0
43
+ end
44
+
45
+ alias test_old_reset reset if instance_methods.include? 'reset'
46
+
47
+ def reset
48
+ self.class.reset_called += 1
49
+ end
50
+
51
+ alias test_old_send_message send_message
52
+
53
+ def send_message(mail, to, from)
54
+ return self.class.send_message_block.call(mail, to, from) unless
55
+ self.class.send_message_block.nil?
56
+ self.class.deliveries << [mail, to, from]
57
+ return "queued"
58
+ end
59
+
60
+ end
61
+
62
+ ##
63
+ # Stub for ActionMailer::Base
64
+
65
+ module ActionMailer; end
66
+
67
+ class ActionMailer::Base
68
+
69
+ @server_settings = {}
70
+
71
+ def self.logger
72
+ o = Object.new
73
+ def o.info(arg) end
74
+ return o
75
+ end
76
+
77
+ def self.method_missing(meth, *args)
78
+ meth.to_s =~ /deliver_(.*)/
79
+ super unless $1
80
+ new($1, *args).deliver!
81
+ end
82
+
83
+ def self.reset
84
+ server_settings.clear
85
+ end
86
+
87
+ def self.server_settings
88
+ @server_settings
89
+ end
90
+
91
+ def initialize(meth = nil)
92
+ send meth if meth
93
+ end
94
+
95
+ def deliver!
96
+ perform_delivery_activerecord @mail
97
+ end
98
+
99
+ end
100
+
101
+ ##
102
+ # Stub for an ActiveRecord model
103
+
104
+ class Email
105
+
106
+ START = Time.parse 'Thu Aug 10 2006 11:19:48'
107
+
108
+ attr_accessor :from, :to, :mail, :last_send_attempt, :created_on, :id
109
+
110
+ @records = []
111
+ @id = 0
112
+
113
+ class << self; attr_accessor :records, :id; end
114
+
115
+ def self.create(record)
116
+ record = new record[:from], record[:to], record[:mail],
117
+ record[:last_send_attempt]
118
+ records << record
119
+ return record
120
+ end
121
+
122
+ def self.destroy_all(conditions)
123
+ timeout = conditions.last
124
+ found = []
125
+
126
+ records.each do |record|
127
+ next if record.last_send_attempt == 0
128
+ next if record.created_on == 0
129
+ next unless record.created_on < timeout
130
+ record.destroy
131
+ found << record
132
+ end
133
+
134
+ found
135
+ end
136
+
137
+ def self.find(_, conditions = nil)
138
+ return records if conditions.nil?
139
+ now = Time.now.to_i - 300
140
+ return records.select do |r|
141
+ r.last_send_attempt < now
142
+ end
143
+ end
144
+
145
+ def self.reset
146
+ @id = 0
147
+ records.clear
148
+ end
149
+
150
+ def initialize(from, to, mail, last_send_attempt = nil)
151
+ @from = from
152
+ @to = to
153
+ @mail = mail
154
+ @id = self.class.id += 1
155
+ @created_on = START + @id
156
+ @last_send_attempt = last_send_attempt || 0
157
+ end
158
+
159
+ def destroy
160
+ self.class.records.delete self
161
+ self.freeze
162
+ end
163
+
164
+ def ==(other)
165
+ other.id == id
166
+ end
167
+
168
+ def save
169
+ end
170
+
171
+ end
172
+
173
+ Mail = Email
174
+
175
+ class String
176
+ def classify
177
+ self
178
+ end
179
+
180
+ def tableize
181
+ self.downcase
182
+ end
183
+
184
+ end
185
+
@@ -0,0 +1,50 @@
1
+ require 'test/unit'
2
+ require 'action_mailer'
3
+ require 'action_mailer/ar_mailer'
4
+
5
+ ##
6
+ # Pretend mailer
7
+
8
+ class Mailer < ActionMailer::ARMailer
9
+
10
+ def mail
11
+ @mail = Object.new
12
+ def @mail.encoded() 'email' end
13
+ def @mail.from() ['nobody@example.com'] end
14
+ def @mail.destinations() %w[user1@example.com user2@example.com] end
15
+ end
16
+
17
+ end
18
+
19
+ class TestARMailer < Test::Unit::TestCase
20
+
21
+ def setup
22
+ Mailer.email_class = Email
23
+
24
+ Email.records.clear
25
+ Mail.records.clear
26
+ end
27
+
28
+ def test_self_email_class_equals
29
+ Mailer.email_class = Mail
30
+
31
+ Mailer.deliver_mail
32
+
33
+ assert_equal 2, Mail.records.length
34
+ end
35
+
36
+ def test_perform_delivery_activerecord
37
+ Mailer.deliver_mail
38
+
39
+ assert_equal 2, Email.records.length
40
+
41
+ record = Email.records.first
42
+ assert_equal 'email', record.mail
43
+ assert_equal 'user1@example.com', record.to
44
+ assert_equal 'nobody@example.com', record.from
45
+
46
+ assert_equal 'user2@example.com', Email.records.last.to
47
+ end
48
+
49
+ end
50
+
@@ -0,0 +1,657 @@
1
+ require 'test/unit'
2
+ require 'action_mailer'
3
+ require 'action_mailer/ar_sendmail'
4
+ require 'rubygems'
5
+ require 'test/zentest_assertions'
6
+
7
+ class ActionMailer::ARSendmail
8
+ attr_accessor :slept
9
+ def sleep(secs)
10
+ @slept ||= []
11
+ @slept << secs
12
+ end
13
+ end
14
+
15
+ class TestARSendmail < Test::Unit::TestCase
16
+
17
+ def setup
18
+ ActionMailer::Base.reset
19
+ Email.reset
20
+ Net::SMTP.reset
21
+
22
+ @sm = ActionMailer::ARSendmail.new
23
+ @sm.verbose = true
24
+
25
+ @include_c_e = ! $".grep(/config\/environment.rb/).empty?
26
+ $" << 'config/environment.rb' unless @include_c_e
27
+ end
28
+
29
+ def teardown
30
+ $".delete 'config/environment.rb' unless @include_c_e
31
+ end
32
+
33
+ def test_class_create_migration
34
+ out, = util_capture do
35
+ ActionMailer::ARSendmail.create_migration 'Mail'
36
+ end
37
+
38
+ expected = <<-EOF
39
+ class AddMail < ActiveRecord::Migration
40
+ def self.up
41
+ create_table :mail do |t|
42
+ t.column :from, :string
43
+ t.column :to, :string
44
+ t.column :last_send_attempt, :integer, :default => 0
45
+ t.column :mail, :text
46
+ t.column :created_on, :datetime
47
+ end
48
+ end
49
+
50
+ def self.down
51
+ drop_table :mail
52
+ end
53
+ end
54
+ EOF
55
+
56
+ assert_equal expected, out
57
+ end
58
+
59
+ def test_class_create_model
60
+ out, = util_capture do
61
+ ActionMailer::ARSendmail.create_model 'Mail'
62
+ end
63
+
64
+ expected = <<-EOF
65
+ class Mail < ActiveRecord::Base
66
+ end
67
+ EOF
68
+
69
+ assert_equal expected, out
70
+ end
71
+
72
+ def test_class_mailq
73
+ Email.create :from => nobody, :to => 'recip@h1.example.com',
74
+ :mail => 'body0'
75
+ Email.create :from => nobody, :to => 'recip@h1.example.com',
76
+ :mail => 'body1'
77
+ last = Email.create :from => nobody, :to => 'recip@h2.example.com',
78
+ :mail => 'body2'
79
+
80
+ last.last_send_attempt = Time.parse('Thu Aug 10 2006 11:40:05').to_i
81
+
82
+ out, err = util_capture do
83
+ ActionMailer::ARSendmail.mailq 'Email'
84
+ end
85
+
86
+ expected = <<-EOF
87
+ -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
88
+ 1 5 Thu Aug 10 11:19:49 nobody@example.com
89
+ recip@h1.example.com
90
+
91
+ 2 5 Thu Aug 10 11:19:50 nobody@example.com
92
+ recip@h1.example.com
93
+
94
+ 3 5 Thu Aug 10 11:19:51 nobody@example.com
95
+ Last send attempt: Thu Aug 10 11:40:05 %s 2006
96
+ recip@h2.example.com
97
+
98
+ -- 0 Kbytes in 3 Requests.
99
+ EOF
100
+
101
+ expected = expected % Time.new.strftime('%z')
102
+ assert_equal expected, out
103
+ end
104
+
105
+ def test_class_mailq_empty
106
+ out, err = util_capture do
107
+ ActionMailer::ARSendmail.mailq 'Email'
108
+ end
109
+
110
+ assert_equal "Mail queue is empty\n", out
111
+ end
112
+
113
+ def test_class_new
114
+ @sm = ActionMailer::ARSendmail.new
115
+
116
+ assert_equal 60, @sm.delay
117
+ assert_equal Email, @sm.email_class
118
+ assert_equal nil, @sm.once
119
+ assert_equal nil, @sm.verbose
120
+ assert_equal nil, @sm.batch_size
121
+
122
+ @sm = ActionMailer::ARSendmail.new :Delay => 75, :Verbose => true,
123
+ :TableName => 'Object', :Once => true,
124
+ :BatchSize => 1000
125
+
126
+ assert_equal 75, @sm.delay
127
+ assert_equal Object, @sm.email_class
128
+ assert_equal true, @sm.once
129
+ assert_equal true, @sm.verbose
130
+ assert_equal 1000, @sm.batch_size
131
+ end
132
+
133
+ def test_class_parse_args_batch_size
134
+ options = ActionMailer::ARSendmail.process_args %w[-b 500]
135
+
136
+ assert_equal 500, options[:BatchSize]
137
+
138
+ options = ActionMailer::ARSendmail.process_args %w[--batch-size 500]
139
+
140
+ assert_equal 500, options[:BatchSize]
141
+ end
142
+
143
+ def test_class_parse_args_chdir
144
+ argv = %w[-c /tmp]
145
+
146
+ options = ActionMailer::ARSendmail.process_args argv
147
+
148
+ assert_equal '/tmp', options[:Chdir]
149
+
150
+ argv = %w[--chdir /tmp]
151
+
152
+ options = ActionMailer::ARSendmail.process_args argv
153
+
154
+ assert_equal '/tmp', options[:Chdir]
155
+
156
+ argv = %w[-c /nonexistent]
157
+
158
+ out, err = util_capture do
159
+ assert_raises SystemExit do
160
+ ActionMailer::ARSendmail.process_args argv
161
+ end
162
+ end
163
+ end
164
+
165
+ def test_class_parse_args_daemon
166
+ argv = %w[-d]
167
+
168
+ options = ActionMailer::ARSendmail.process_args argv
169
+
170
+ assert_equal true, options[:Daemon]
171
+
172
+ argv = %w[--daemon]
173
+
174
+ options = ActionMailer::ARSendmail.process_args argv
175
+
176
+ assert_equal true, options[:Daemon]
177
+ end
178
+
179
+ def test_class_parse_args_pidfile
180
+ argv = %w[-p ./log/ar_sendmail.pid]
181
+
182
+ options = ActionMailer::ARSendmail.process_args argv
183
+
184
+ assert_equal './log/ar_sendmail.pid', options[:Pidfile]
185
+
186
+ argv = %w[--pidfile ./log/ar_sendmail.pid]
187
+
188
+ options = ActionMailer::ARSendmail.process_args argv
189
+
190
+ assert_equal './log/ar_sendmail.pid', options[:Pidfile]
191
+ end
192
+
193
+ def test_class_parse_args_delay
194
+ argv = %w[--delay 75]
195
+
196
+ options = ActionMailer::ARSendmail.process_args argv
197
+
198
+ assert_equal 75, options[:Delay]
199
+ end
200
+
201
+ def test_class_parse_args_environment
202
+ assert_equal nil, ENV['RAILS_ENV']
203
+
204
+ argv = %w[-e production]
205
+
206
+ options = ActionMailer::ARSendmail.process_args argv
207
+
208
+ assert_equal 'production', options[:RailsEnv]
209
+
210
+ assert_equal 'production', ENV['RAILS_ENV']
211
+
212
+ argv = %w[--environment production]
213
+
214
+ options = ActionMailer::ARSendmail.process_args argv
215
+
216
+ assert_equal 'production', options[:RailsEnv]
217
+ end
218
+
219
+ def test_class_parse_args_mailq
220
+ options = ActionMailer::ARSendmail.process_args []
221
+ deny_includes options, :MailQ
222
+
223
+ argv = %w[--mailq]
224
+
225
+ options = ActionMailer::ARSendmail.process_args argv
226
+
227
+ assert_equal true, options[:MailQ]
228
+ end
229
+
230
+ def test_class_parse_args_max_age
231
+ options = ActionMailer::ARSendmail.process_args []
232
+ assert_equal 86400 * 7, options[:MaxAge]
233
+
234
+ argv = %w[--max-age 86400]
235
+
236
+ options = ActionMailer::ARSendmail.process_args argv
237
+
238
+ assert_equal 86400, options[:MaxAge]
239
+ end
240
+
241
+ def test_class_parse_args_migration
242
+ options = ActionMailer::ARSendmail.process_args []
243
+ deny_includes options, :Migration
244
+
245
+ argv = %w[--create-migration]
246
+
247
+ options = ActionMailer::ARSendmail.process_args argv
248
+
249
+ assert_equal true, options[:Migrate]
250
+ end
251
+
252
+ def test_class_parse_args_model
253
+ options = ActionMailer::ARSendmail.process_args []
254
+ deny_includes options, :Model
255
+
256
+ argv = %w[--create-model]
257
+
258
+ options = ActionMailer::ARSendmail.process_args argv
259
+
260
+ assert_equal true, options[:Model]
261
+ end
262
+
263
+ def test_class_parse_args_no_config_environment
264
+ $".delete 'config/environment.rb'
265
+
266
+ out, err = util_capture do
267
+ assert_raise SystemExit do
268
+ ActionMailer::ARSendmail.process_args []
269
+ end
270
+ end
271
+
272
+ ensure
273
+ $" << 'config/environment.rb' if @include_c_e
274
+ end
275
+
276
+ def test_class_parse_args_no_config_environment_migrate
277
+ $".delete 'config/environment.rb'
278
+
279
+ out, err = util_capture do
280
+ ActionMailer::ARSendmail.process_args %w[--create-migration]
281
+ end
282
+
283
+ assert true # count
284
+
285
+ ensure
286
+ $" << 'config/environment.rb' if @include_c_e
287
+ end
288
+
289
+ def test_class_parse_args_no_config_environment_model
290
+ $".delete 'config/environment.rb'
291
+
292
+ out, err = util_capture do
293
+ ActionMailer::ARSendmail.process_args %w[--create-model]
294
+ end
295
+
296
+ assert true # count
297
+
298
+ rescue SystemExit
299
+ flunk 'Should not exit'
300
+
301
+ ensure
302
+ $" << 'config/environment.rb' if @include_c_e
303
+ end
304
+
305
+ def test_class_parse_args_once
306
+ argv = %w[-o]
307
+
308
+ options = ActionMailer::ARSendmail.process_args argv
309
+
310
+ assert_equal true, options[:Once]
311
+
312
+ argv = %w[--once]
313
+
314
+ options = ActionMailer::ARSendmail.process_args argv
315
+
316
+ assert_equal true, options[:Once]
317
+ end
318
+
319
+ def test_class_parse_args_table_name
320
+ argv = %w[-t Email]
321
+
322
+ options = ActionMailer::ARSendmail.process_args argv
323
+
324
+ assert_equal 'Email', options[:TableName]
325
+
326
+ argv = %w[--table-name=Email]
327
+
328
+ options = ActionMailer::ARSendmail.process_args argv
329
+
330
+ assert_equal 'Email', options[:TableName]
331
+ end
332
+
333
+ def test_class_usage
334
+ out, err = util_capture do
335
+ assert_raises SystemExit do
336
+ ActionMailer::ARSendmail.usage 'opts'
337
+ end
338
+ end
339
+
340
+ assert_equal '', out
341
+ assert_equal "opts\n", err
342
+
343
+ out, err = util_capture do
344
+ assert_raises SystemExit do
345
+ ActionMailer::ARSendmail.usage 'opts', 'hi'
346
+ end
347
+ end
348
+
349
+ assert_equal '', out
350
+ assert_equal "hi\n\nopts\n", err
351
+ end
352
+
353
+ def test_cleanup
354
+ e1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
355
+ e1.created_on = Time.now
356
+ e2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
357
+ e3 = Email.create :mail => 'body', :to => 'to', :from => 'from'
358
+ e3.last_send_attempt = Time.now
359
+
360
+ out, err = util_capture do
361
+ @sm.cleanup
362
+ end
363
+
364
+ assert_equal '', out
365
+ assert_equal "expired 1 emails from the queue\n", err
366
+ assert_equal 2, Email.records.length
367
+
368
+ assert_equal [e1, e2], Email.records
369
+ end
370
+
371
+ def test_cleanup_disabled
372
+ e1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
373
+ e1.created_on = Time.now
374
+ e2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
375
+
376
+ @sm.max_age = 0
377
+
378
+ out, err = util_capture do
379
+ @sm.cleanup
380
+ end
381
+
382
+ assert_equal '', out
383
+ assert_equal 2, Email.records.length
384
+ end
385
+
386
+ def test_deliver
387
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
388
+
389
+ out, err = util_capture do
390
+ @sm.deliver [email]
391
+ end
392
+
393
+ assert_equal 1, Net::SMTP.deliveries.length
394
+ assert_equal ['body', 'from', 'to'], Net::SMTP.deliveries.first
395
+ assert_equal 0, Email.records.length
396
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
397
+
398
+ assert_equal '', out
399
+ assert_equal "sent email 00000000001 from from to to: \"queued\"\n", err
400
+ end
401
+
402
+ def test_deliver_auth_error
403
+ Net::SMTP.on_start do
404
+ e = Net::SMTPAuthenticationError.new 'try again'
405
+ e.set_backtrace %w[one two three]
406
+ raise e
407
+ end
408
+
409
+ now = Time.now.to_i
410
+
411
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
412
+
413
+ out, err = util_capture do
414
+ @sm.deliver [email]
415
+ end
416
+
417
+ assert_equal 0, Net::SMTP.deliveries.length
418
+ assert_equal 1, Email.records.length
419
+ assert_equal 0, Email.records.first.last_send_attempt
420
+ assert_equal 0, Net::SMTP.reset_called
421
+ assert_equal 1, @sm.failed_auth_count
422
+ assert_equal [60], @sm.slept
423
+
424
+ assert_equal '', out
425
+ assert_equal "authentication error, retrying: try again\n", err
426
+ end
427
+
428
+ def test_deliver_auth_error_recover
429
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
430
+ @sm.failed_auth_count = 1
431
+
432
+ out, err = util_capture do @sm.deliver [email] end
433
+
434
+ assert_equal 0, @sm.failed_auth_count
435
+ assert_equal 1, Net::SMTP.deliveries.length
436
+ end
437
+
438
+ def test_deliver_auth_error_twice
439
+ Net::SMTP.on_start do
440
+ e = Net::SMTPAuthenticationError.new 'try again'
441
+ e.set_backtrace %w[one two three]
442
+ raise e
443
+ end
444
+
445
+ @sm.failed_auth_count = 1
446
+
447
+ out, err = util_capture do
448
+ assert_raise Net::SMTPAuthenticationError do
449
+ @sm.deliver []
450
+ end
451
+ end
452
+
453
+ assert_equal 2, @sm.failed_auth_count
454
+ assert_equal "authentication error, giving up: try again\n", err
455
+ end
456
+
457
+ def test_deliver_4xx_error
458
+ Net::SMTP.on_send_message do
459
+ e = Net::SMTPSyntaxError.new 'try again'
460
+ e.set_backtrace %w[one two three]
461
+ raise e
462
+ end
463
+
464
+ now = Time.now.to_i
465
+
466
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
467
+
468
+ out, err = util_capture do
469
+ @sm.deliver [email]
470
+ end
471
+
472
+ assert_equal 0, Net::SMTP.deliveries.length
473
+ assert_equal 1, Email.records.length
474
+ assert_operator now, :<=, Email.records.first.last_send_attempt
475
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
476
+
477
+ assert_equal '', out
478
+ assert_equal "error sending email 1: \"try again\"(Net::SMTPSyntaxError):\n\tone\n\ttwo\n\tthree\n", err
479
+ end
480
+
481
+ def test_deliver_5xx_error
482
+ Net::SMTP.on_send_message do
483
+ e = Net::SMTPFatalError.new 'unknown recipient'
484
+ e.set_backtrace %w[one two three]
485
+ raise e
486
+ end
487
+
488
+ now = Time.now.to_i
489
+
490
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
491
+
492
+ out, err = util_capture do
493
+ @sm.deliver [email]
494
+ end
495
+
496
+ assert_equal 0, Net::SMTP.deliveries.length
497
+ assert_equal 0, Email.records.length
498
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
499
+
500
+ assert_equal '', out
501
+ assert_equal "5xx error sending email 1, removing from queue: \"unknown recipient\"(Net::SMTPFatalError):\n\tone\n\ttwo\n\tthree\n", err
502
+ end
503
+
504
+ def test_deliver_errno_epipe
505
+ Net::SMTP.on_send_message do
506
+ raise Errno::EPIPE
507
+ end
508
+
509
+ now = Time.now.to_i
510
+
511
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
512
+
513
+ out, err = util_capture do
514
+ @sm.deliver [email]
515
+ end
516
+
517
+ assert_equal 0, Net::SMTP.deliveries.length
518
+ assert_equal 1, Email.records.length
519
+ assert_operator now, :>=, Email.records.first.last_send_attempt
520
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
521
+
522
+ assert_equal '', out
523
+ assert_equal '', err
524
+ end
525
+
526
+ def test_deliver_server_busy
527
+ Net::SMTP.on_send_message do
528
+ e = Net::SMTPServerBusy.new 'try again'
529
+ e.set_backtrace %w[one two three]
530
+ raise e
531
+ end
532
+
533
+ now = Time.now.to_i
534
+
535
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
536
+
537
+ out, err = util_capture do
538
+ @sm.deliver [email]
539
+ end
540
+
541
+ assert_equal 0, Net::SMTP.deliveries.length
542
+ assert_equal 1, Email.records.length
543
+ assert_operator now, :>=, Email.records.first.last_send_attempt
544
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
545
+ assert_equal [60], @sm.slept
546
+
547
+ assert_equal '', out
548
+ assert_equal "server too busy, sleeping 60 seconds\n", err
549
+ end
550
+
551
+ def test_deliver_syntax_error
552
+ Net::SMTP.on_send_message do
553
+ Net::SMTP.on_send_message # clear
554
+ e = Net::SMTPSyntaxError.new 'blah blah blah'
555
+ e.set_backtrace %w[one two three]
556
+ raise e
557
+ end
558
+
559
+ now = Time.now.to_i
560
+
561
+ email1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
562
+ email2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
563
+
564
+ out, err = util_capture do
565
+ @sm.deliver [email1, email2]
566
+ end
567
+
568
+ assert_equal 1, Net::SMTP.deliveries.length, 'delivery count'
569
+ assert_equal 1, Email.records.length
570
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
571
+ assert_operator now, :<=, Email.records.first.last_send_attempt
572
+
573
+ assert_equal '', out
574
+ assert_equal "error sending email 1: \"blah blah blah\"(Net::SMTPSyntaxError):\n\tone\n\ttwo\n\tthree\nsent email 00000000002 from from to to: \"queued\"\n", err
575
+ end
576
+
577
+ def test_deliver_timeout
578
+ Net::SMTP.on_send_message do
579
+ e = Timeout::Error.new 'timed out'
580
+ e.set_backtrace %w[one two three]
581
+ raise e
582
+ end
583
+
584
+ now = Time.now.to_i
585
+
586
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
587
+
588
+ out, err = util_capture do
589
+ @sm.deliver [email]
590
+ end
591
+
592
+ assert_equal 0, Net::SMTP.deliveries.length
593
+ assert_equal 1, Email.records.length
594
+ assert_operator now, :>=, Email.records.first.last_send_attempt
595
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on Timeout'
596
+
597
+ assert_equal '', out
598
+ assert_equal "error sending email 1: \"timed out\"(Timeout::Error):\n\tone\n\ttwo\n\tthree\n", err
599
+ end
600
+
601
+ def test_do_exit
602
+ out, err = util_capture do
603
+ assert_raise SystemExit do
604
+ @sm.do_exit
605
+ end
606
+ end
607
+
608
+ assert_equal '', out
609
+ assert_equal "caught signal, shutting down\n", err
610
+ end
611
+
612
+ def test_log
613
+ out, err = util_capture do
614
+ @sm.log 'hi'
615
+ end
616
+
617
+ assert_equal "hi\n", err
618
+ end
619
+
620
+ def test_find_emails
621
+ email_data = [
622
+ { :mail => 'body0', :to => 'recip@h1.example.com', :from => nobody },
623
+ { :mail => 'body1', :to => 'recip@h1.example.com', :from => nobody },
624
+ { :mail => 'body2', :to => 'recip@h2.example.com', :from => nobody },
625
+ ]
626
+
627
+ emails = email_data.map do |email_data| Email.create email_data end
628
+
629
+ tried = Email.create :mail => 'body3', :to => 'recip@h3.example.com',
630
+ :from => nobody
631
+
632
+ tried.last_send_attempt = Time.now.to_i - 258
633
+
634
+ found_emails = []
635
+
636
+ out, err = util_capture do
637
+ found_emails = @sm.find_emails
638
+ end
639
+
640
+ assert_equal emails, found_emails
641
+
642
+ assert_equal '', out
643
+ assert_equal "found 3 emails to send\n", err
644
+ end
645
+
646
+ def test_smtp_settings
647
+ ActionMailer::Base.server_settings[:address] = 'localhost'
648
+
649
+ assert_equal 'localhost', @sm.smtp_settings[:address]
650
+ end
651
+
652
+ def nobody
653
+ 'nobody@example.com'
654
+ end
655
+
656
+ end
657
+