aussiegeek-ar_sendmail_delayed 1.3.2

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