morten-ar_mailer 1.4.5

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,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
+