aussiegeek-ar_sendmail_delayed 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+