flipstone-ar_mailer 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,542 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
+
3
+ class ArMailer::ARSendmail
4
+ attr_accessor :slept
5
+ def sleep(secs)
6
+ @slept ||= []
7
+ @slept << secs
8
+ end
9
+ end
10
+
11
+ class TestARSendmail < MiniTest::Unit::TestCase
12
+
13
+ def setup
14
+ ActionMailer::Base.reset
15
+ Email.reset
16
+ Net::SMTP.reset
17
+
18
+ @sm = ArMailer::ARSendmail.new
19
+ @sm.verbose = true
20
+
21
+ Net::SMTP.clear_on_start
22
+
23
+ @include_c_e = ! $".grep(/config\/environment.rb/).empty?
24
+ $" << 'config/environment.rb' unless @include_c_e
25
+ end
26
+
27
+ def teardown
28
+ $".delete 'config/environment.rb' unless @include_c_e
29
+ end
30
+
31
+ def test_class_mailq
32
+ Email.create :from => nobody, :to => 'recip@h1.example.com',
33
+ :mail => 'body0'
34
+ Email.create :from => nobody, :to => 'recip@h1.example.com',
35
+ :mail => 'body1'
36
+ last = Email.create :from => nobody, :to => 'recip@h2.example.com',
37
+ :mail => 'body2'
38
+ last_attempt_time = Time.parse('Thu Aug 10 2006 11:40:05')
39
+ last.last_send_attempt = last_attempt_time.to_i
40
+
41
+ out, err = capture_io do
42
+ ArMailer::ARSendmail.mailq
43
+ end
44
+
45
+ expected = <<-EOF
46
+ -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
47
+ 1 5 Thu Aug 10 11:19:49 nobody@example.com
48
+ recip@h1.example.com
49
+
50
+ 2 5 Thu Aug 10 11:19:50 nobody@example.com
51
+ recip@h1.example.com
52
+
53
+ 3 5 Thu Aug 10 11:19:51 nobody@example.com
54
+ Last send attempt: Thu Aug 10 11:40:05 %s 2006
55
+ recip@h2.example.com
56
+
57
+ -- 0 Kbytes in 3 Requests.
58
+ EOF
59
+
60
+ expected = expected % last_attempt_time.strftime('%z')
61
+ assert_equal expected, out
62
+ end
63
+
64
+ def test_class_mailq_empty
65
+ out, err = capture_io do
66
+ ArMailer::ARSendmail.mailq
67
+ end
68
+
69
+ assert_equal "Mail queue is empty\n", out
70
+ end
71
+
72
+ def test_class_new
73
+ @sm = ArMailer::ARSendmail.new
74
+
75
+ assert_equal 60, @sm.delay
76
+ assert_equal nil, @sm.once
77
+ assert_equal nil, @sm.verbose
78
+ assert_equal nil, @sm.batch_size
79
+
80
+ @sm = ArMailer::ARSendmail.new :Delay => 75, :Verbose => true,
81
+ :Once => true, :BatchSize => 1000
82
+
83
+ assert_equal 75, @sm.delay
84
+ assert_equal true, @sm.once
85
+ assert_equal true, @sm.verbose
86
+ assert_equal 1000, @sm.batch_size
87
+ end
88
+
89
+ def test_class_parse_args_batch_size
90
+ options = ArMailer::ARSendmail.process_args %w[-b 500]
91
+
92
+ assert_equal 500, options[:BatchSize]
93
+
94
+ options = ArMailer::ARSendmail.process_args %w[--batch-size 500]
95
+
96
+ assert_equal 500, options[:BatchSize]
97
+ end
98
+
99
+ def test_class_parse_args_chdir
100
+ argv = %w[-c /tmp]
101
+
102
+ options = ArMailer::ARSendmail.process_args argv
103
+
104
+ assert_equal '/tmp', options[:Chdir]
105
+
106
+ argv = %w[--chdir /tmp]
107
+
108
+ options = ArMailer::ARSendmail.process_args argv
109
+
110
+ assert_equal '/tmp', options[:Chdir]
111
+
112
+ argv = %w[-c /nonexistent]
113
+
114
+ out, err = capture_io do
115
+ assert_raises SystemExit do
116
+ ArMailer::ARSendmail.process_args argv
117
+ end
118
+ end
119
+ end
120
+
121
+ def test_class_parse_args_daemon
122
+ argv = %w[-d]
123
+
124
+ options = ArMailer::ARSendmail.process_args argv
125
+
126
+ assert_equal true, options[:Daemon]
127
+
128
+ argv = %w[--daemon]
129
+
130
+ options = ArMailer::ARSendmail.process_args argv
131
+
132
+ assert_equal true, options[:Daemon]
133
+ end
134
+
135
+ def test_class_parse_args_pidfile
136
+ argv = %w[-p ./log/ar_sendmail.pid]
137
+
138
+ options = ArMailer::ARSendmail.process_args argv
139
+
140
+ assert_equal './log/ar_sendmail.pid', options[:Pidfile]
141
+
142
+ argv = %w[--pidfile ./log/ar_sendmail.pid]
143
+
144
+ options = ArMailer::ARSendmail.process_args argv
145
+
146
+ assert_equal './log/ar_sendmail.pid', options[:Pidfile]
147
+ end
148
+
149
+ def test_class_parse_args_delay
150
+ argv = %w[--delay 75]
151
+
152
+ options = ArMailer::ARSendmail.process_args argv
153
+
154
+ assert_equal 75, options[:Delay]
155
+ end
156
+
157
+ def test_class_parse_args_environment
158
+ assert_equal nil, ENV['RAILS_ENV']
159
+
160
+ argv = %w[-e production]
161
+
162
+ options = ArMailer::ARSendmail.process_args argv
163
+
164
+ assert_equal 'production', options[:RailsEnv]
165
+
166
+ assert_equal 'production', ENV['RAILS_ENV']
167
+
168
+ argv = %w[--environment production]
169
+
170
+ options = ArMailer::ARSendmail.process_args argv
171
+
172
+ assert_equal 'production', options[:RailsEnv]
173
+ end
174
+
175
+ def test_class_parse_args_mailq
176
+ options = ArMailer::ARSendmail.process_args []
177
+ refute_includes options, :MailQ
178
+
179
+ argv = %w[--mailq]
180
+
181
+ options = ArMailer::ARSendmail.process_args argv
182
+
183
+ assert_equal true, options[:MailQ]
184
+ end
185
+
186
+ def test_class_parse_args_max_age
187
+ options = ArMailer::ARSendmail.process_args []
188
+ assert_equal 86400 * 7, options[:MaxAge]
189
+
190
+ argv = %w[--max-age 86400]
191
+
192
+ options = ArMailer::ARSendmail.process_args argv
193
+
194
+ assert_equal 86400, options[:MaxAge]
195
+ end
196
+
197
+ def test_class_parse_args_no_config_environment
198
+ $".delete 'config/environment.rb'
199
+
200
+ out, err = capture_io do
201
+ assert_raises SystemExit do
202
+ ArMailer::ARSendmail.process_args []
203
+ end
204
+ end
205
+
206
+ ensure
207
+ $" << 'config/environment.rb' if @include_c_e
208
+ end
209
+
210
+ def test_class_parse_args_once
211
+ argv = %w[-o]
212
+
213
+ options = ArMailer::ARSendmail.process_args argv
214
+
215
+ assert_equal true, options[:Once]
216
+
217
+ argv = %w[--once]
218
+
219
+ options = ArMailer::ARSendmail.process_args argv
220
+
221
+ assert_equal true, options[:Once]
222
+ end
223
+
224
+ def test_class_usage
225
+ out, err = capture_io do
226
+ assert_raises SystemExit do
227
+ ArMailer::ARSendmail.usage 'opts'
228
+ end
229
+ end
230
+
231
+ assert_equal '', out
232
+ assert_equal "opts\n", err
233
+
234
+ out, err = capture_io do
235
+ assert_raises SystemExit do
236
+ ArMailer::ARSendmail.usage 'opts', 'hi'
237
+ end
238
+ end
239
+
240
+ assert_equal '', out
241
+ assert_equal "hi\n\nopts\n", err
242
+ end
243
+
244
+ def test_cleanup
245
+ e1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
246
+ e1.created_on = Time.now
247
+ e2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
248
+ e3 = Email.create :mail => 'body', :to => 'to', :from => 'from'
249
+ e3.last_send_attempt = Time.now
250
+
251
+ out, err = capture_io do
252
+ @sm.cleanup
253
+ end
254
+
255
+ assert_equal '', out
256
+ assert_equal "expired 1 emails from the queue\n", err
257
+ assert_equal 2, Email.records.length
258
+
259
+ assert_equal [e1, e2], Email.records
260
+ end
261
+
262
+ def test_cleanup_disabled
263
+ e1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
264
+ e1.created_on = Time.now
265
+ e2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
266
+
267
+ @sm.max_age = 0
268
+
269
+ out, err = capture_io do
270
+ @sm.cleanup
271
+ end
272
+
273
+ assert_equal '', out
274
+ assert_equal 2, Email.records.length
275
+ end
276
+
277
+ def test_deliver
278
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
279
+
280
+ out, err = capture_io do
281
+ @sm.deliver [email]
282
+ end
283
+
284
+ assert_equal 1, Net::SMTP.deliveries.length
285
+ assert_equal ['body', 'from', 'to'], Net::SMTP.deliveries.first
286
+ assert_equal 0, Email.records.length
287
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
288
+
289
+ assert_equal '', out
290
+ assert_equal "sent email 00000000001 from from to to: \"queued\"\n", err
291
+ end
292
+
293
+ def test_deliver_not_called_when_no_emails
294
+ sm = ArMailer::ARSendmail.new({:Once => true})
295
+ sm.expects(:deliver).never
296
+ sm.run
297
+ end
298
+
299
+ def test_deliver_auth_error
300
+ Net::SMTP.on_start do
301
+ e = Net::SMTPAuthenticationError.new 'try again'
302
+ e.set_backtrace %w[one two three]
303
+ raise e
304
+ end
305
+
306
+ now = Time.now.to_i
307
+
308
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
309
+
310
+ out, err = capture_io do
311
+ @sm.deliver [email]
312
+ end
313
+
314
+ assert_equal 0, Net::SMTP.deliveries.length
315
+ assert_equal 1, Email.records.length
316
+ assert_equal 0, Email.records.first.last_send_attempt
317
+ assert_equal 0, Net::SMTP.reset_called
318
+ assert_equal 1, @sm.failed_auth_count
319
+ assert_equal [60], @sm.slept
320
+
321
+ assert_equal '', out
322
+ assert_equal "authentication error, retrying: try again\n", err
323
+ end
324
+
325
+ def test_deliver_auth_error_recover
326
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
327
+ @sm.failed_auth_count = 1
328
+
329
+ out, err = capture_io do @sm.deliver [email] end
330
+
331
+ assert_equal 0, @sm.failed_auth_count
332
+ assert_equal 1, Net::SMTP.deliveries.length
333
+ end
334
+
335
+ def test_deliver_auth_error_twice
336
+ Net::SMTP.on_start do
337
+ e = Net::SMTPAuthenticationError.new 'try again'
338
+ e.set_backtrace %w[one two three]
339
+ raise e
340
+ end
341
+
342
+ @sm.failed_auth_count = 1
343
+
344
+ out, err = capture_io do
345
+ assert_raises Net::SMTPAuthenticationError do
346
+ @sm.deliver []
347
+ end
348
+ end
349
+
350
+ assert_equal 2, @sm.failed_auth_count
351
+ assert_equal "authentication error, giving up: try again\n", err
352
+ end
353
+
354
+ def test_deliver_4xx_error
355
+ Net::SMTP.on_send_message do
356
+ e = Net::SMTPSyntaxError.new 'try again'
357
+ e.set_backtrace %w[one two three]
358
+ raise e
359
+ end
360
+
361
+ now = Time.now.to_i
362
+
363
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
364
+
365
+ out, err = capture_io do
366
+ @sm.deliver [email]
367
+ end
368
+
369
+ assert_equal 0, Net::SMTP.deliveries.length
370
+ assert_equal 1, Email.records.length
371
+ assert_operator now, :<=, Email.records.first.last_send_attempt
372
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
373
+
374
+ assert_equal '', out
375
+ assert_equal "error sending email 1: \"try again\"(Net::SMTPSyntaxError):\n\tone\n\ttwo\n\tthree\n", err
376
+ end
377
+
378
+ def test_deliver_5xx_error
379
+ Net::SMTP.on_send_message do
380
+ e = Net::SMTPFatalError.new 'unknown recipient'
381
+ e.set_backtrace %w[one two three]
382
+ raise e
383
+ end
384
+
385
+ now = Time.now.to_i
386
+
387
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
388
+
389
+ out, err = capture_io do
390
+ @sm.deliver [email]
391
+ end
392
+
393
+ assert_equal 0, Net::SMTP.deliveries.length
394
+ assert_equal 1, Email.records.length
395
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
396
+
397
+ assert_kind_of Time, Email.records.first.failed_at
398
+ assert_equal Email.records.first.failure_message, "unknown recipient"
399
+
400
+ assert_equal '', out
401
+ assert_equal "5xx error sending email 1, removing from queue: \"unknown recipient\"(Net::SMTPFatalError):\n\tone\n\ttwo\n\tthree\n", err
402
+ end
403
+
404
+ def test_deliver_errno_epipe
405
+ Net::SMTP.on_send_message do
406
+ raise Errno::EPIPE
407
+ end
408
+
409
+ now = Time.now.to_i
410
+
411
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
412
+
413
+ out, err = capture_io 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_operator now, :>=, Email.records.first.last_send_attempt
420
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
421
+
422
+ assert_equal '', out
423
+ assert_equal '', err
424
+ end
425
+
426
+ def test_deliver_syntax_error
427
+ Net::SMTP.on_send_message do
428
+ Net::SMTP.on_send_message # clear
429
+ e = Net::SMTPSyntaxError.new 'blah blah blah'
430
+ e.set_backtrace %w[one two three]
431
+ raise e
432
+ end
433
+
434
+ now = Time.now.to_i
435
+
436
+ email1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
437
+ email2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
438
+
439
+ out, err = capture_io do
440
+ @sm.deliver [email1, email2]
441
+ end
442
+
443
+ assert_equal 1, Net::SMTP.deliveries.length, 'delivery count'
444
+ assert_equal 1, Email.records.length
445
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
446
+ assert_operator now, :<=, Email.records.first.last_send_attempt
447
+
448
+ assert_equal '', out
449
+ 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
450
+ end
451
+
452
+ def test_deliver_timeout
453
+ Net::SMTP.on_send_message do
454
+ e = Timeout::Error.new 'timed out'
455
+ e.set_backtrace %w[one two three]
456
+ raise e
457
+ end
458
+
459
+ now = Time.now.to_i
460
+
461
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
462
+
463
+ out, err = capture_io do
464
+ @sm.deliver [email]
465
+ end
466
+
467
+ assert_equal 0, Net::SMTP.deliveries.length
468
+ assert_equal 1, Email.records.length
469
+ assert_operator now, :>=, Email.records.first.last_send_attempt
470
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on Timeout'
471
+
472
+ assert_equal '', out
473
+ assert_equal "error sending email 1: \"timed out\"(Timeout::Error):\n\tone\n\ttwo\n\tthree\n", err
474
+ end
475
+
476
+ def test_do_exit
477
+ out, err = capture_io do
478
+ assert_raises SystemExit do
479
+ @sm.do_exit
480
+ end
481
+ end
482
+
483
+ assert_equal '', out
484
+ assert_equal "caught signal, shutting down\n", err
485
+ end
486
+
487
+ def test_log
488
+ out, err = capture_io do
489
+ @sm.log 'hi'
490
+ end
491
+
492
+ assert_equal "hi\n", err
493
+ end
494
+
495
+ def test_find_emails
496
+ email_data = [
497
+ { :mail => 'body0', :to => 'recip@h1.example.com', :from => nobody },
498
+ { :mail => 'body1', :to => 'recip@h1.example.com', :from => nobody },
499
+ { :mail => 'body2', :to => 'recip@h2.example.com', :from => nobody },
500
+ ]
501
+
502
+ emails = email_data.map do |email_data| Email.create email_data end
503
+
504
+ tried = Email.create :mail => 'body3', :to => 'recip@h3.example.com',
505
+ :from => nobody
506
+
507
+ tried.last_send_attempt = Time.now.to_i - 258
508
+
509
+ found_emails = []
510
+
511
+ out, err = capture_io do
512
+ found_emails = @sm.find_emails
513
+ end
514
+
515
+ assert_equal emails, found_emails
516
+
517
+ assert_equal '', out
518
+ assert_equal "found 3 emails to send\n", err
519
+ end
520
+
521
+ def test_find_emails_no_5xx_error_recovery
522
+ Email.create :failed_at => Time.now.utc
523
+ found_emails = []
524
+
525
+ out, err = capture_io do
526
+ found_emails = @sm.find_emails
527
+ end
528
+
529
+ assert_equal [], found_emails
530
+ end
531
+
532
+ def test_smtp_settings
533
+ ActionMailer::Base.server_settings[:address] = 'localhost'
534
+
535
+ assert_equal 'localhost', @sm.smtp_settings[:address]
536
+ end
537
+
538
+ def nobody
539
+ 'nobody@example.com'
540
+ end
541
+
542
+ end
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_support'
4
+ require 'active_support/core_ext/class/attribute_accessors' # d: why need to require?
5
+ require 'active_support/core_ext/string/inflections' # d: why need to require?
6
+ require 'test/resources/action_mailer'
7
+ require 'minitest/autorun'
8
+ require 'mocha'
9
+
10
+ require 'ar_mailer/active_record'
11
+ require 'ar_mailer/ar_sendmail'
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flipstone-ar_mailer
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 3
7
+ - 0
8
+ - 0
9
+ version: 3.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Eric Hodel
13
+ - Adam Meehan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-13 00:00:00 -05:00
19
+ default_executable: ar_sendmail
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: minitest
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 1
31
+ - 5
32
+ - 0
33
+ version: 1.5.0
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: mocha
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 0
46
+ - 9
47
+ - 8
48
+ version: 0.9.8
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: Even delivering email to the local machine may take too long when you have to send hundreds of messages. ar_mailer allows you to store messages into the database for later delivery by a separate process, ar_sendmail.
52
+ email: david@flipstone.com
53
+ executables:
54
+ - ar_sendmail
55
+ extensions: []
56
+
57
+ extra_rdoc_files:
58
+ - History.txt
59
+ - LICENSE.txt
60
+ - README.rdoc
61
+ files:
62
+ - History.txt
63
+ - LICENSE.txt
64
+ - README.rdoc
65
+ - Rakefile
66
+ - bin/ar_sendmail
67
+ - generators/ar_mailer/ar_mailer_generator.rb
68
+ - generators/ar_mailer/templates/migration.rb
69
+ - generators/ar_mailer/templates/model.rb
70
+ - lib/flipstone-ar_mailer.rb
71
+ - lib/ar_mailer/active_record.rb
72
+ - lib/ar_mailer/ar_sendmail.rb
73
+ - lib/smtp_tls.rb
74
+ - share/bsd/ar_sendmail
75
+ - share/linux/ar_sendmail
76
+ - share/linux/ar_sendmail.conf
77
+ - test/resources/action_mailer.rb
78
+ - test/test_armailer.rb
79
+ - test/test_arsendmail.rb
80
+ - test/test_helper.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/flipstone/ar_mailer
83
+ licenses: []
84
+
85
+ post_install_message:
86
+ rdoc_options:
87
+ - --main
88
+ - README.rdoc
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ requirements: []
108
+
109
+ rubyforge_project: seattlerb
110
+ rubygems_version: 1.3.7
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: A two-phase delivery agent for ActionMailer
114
+ test_files:
115
+ - test/test_armailer.rb
116
+ - test/test_arsendmail.rb