ar_mailer 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,36 @@
1
+ = 1.2.0
2
+
3
+ * Bugs fixed
4
+ * Handle SMTPServerBusy by backing off @delay seconds then re-queueing
5
+ * Allow email delivery class to be set in ARMailer.
6
+ * ar_sendmail --mailq works with --table-name now.
7
+ * Miscellaneous Updates
8
+ * Added documentation to require 'action_mailer/ar_mailer' in
9
+ instructions.
10
+ * Moved to ZSS p4 repository
11
+ * Supports TLS now. Requested by Dave Thomas. smtp_tls.rb from Kyle
12
+ Maxwell & etc.
13
+
14
+ = 1.1.0
15
+
16
+ * Features
17
+ * Added --chdir to set rails directory
18
+ * Added --environment to set RAILS_ENV
19
+ * Exits cleanly on TERM or INT signals
20
+ * Added FreeBSD rc.d script
21
+ * Exceptions during SMTP sending are now logged
22
+ * No longer waits if sending email took too long
23
+ * Bugs fixed
24
+ * Fixed last send attempt in --mailq
25
+ * Better SMTP error handling
26
+ * Messages are removed from the queue on 5xx errors
27
+ * Added Net::SMTP.reset to avoid needing to recreate the connection
28
+
29
+ = 1.0.1
30
+
31
+ * Bugs fixed
32
+ * From and to of email destination were swapped
33
+
34
+ = 1.0.0
35
+
36
+ * Birthday
@@ -1,4 +1,6 @@
1
- Copyright 2006, Eric Hodel, The Robot Co-op. All rights reserved.
1
+ Original code copyright 2006, 2007, Eric Hodel, The Robot Co-op. All
2
+ rights reserved. Some code under other license, see individual files
3
+ for details.
2
4
 
3
5
  Redistribution and use in source and binary forms, with or without
4
6
  modification, are permitted provided that the following conditions
data/Manifest.txt CHANGED
@@ -1,10 +1,12 @@
1
- LICENSE
1
+ History.txt
2
+ LICENSE.txt
2
3
  Manifest.txt
3
- README
4
+ README.txt
4
5
  Rakefile
5
6
  bin/ar_sendmail
6
7
  lib/action_mailer/ar_mailer.rb
7
8
  lib/action_mailer/ar_sendmail.rb
9
+ lib/smtp_tls.rb
8
10
  share/ar_sendmail
9
11
  test/action_mailer.rb
10
12
  test/test_armailer.rb
@@ -1,12 +1,18 @@
1
1
  = ar_mailer
2
2
 
3
+ A two-phase delivery agent for ActionMailer
4
+
3
5
  Rubyforge Project:
4
6
 
5
- http://rubyforge.org/projects/rctools
7
+ http://rubyforge.org/projects/seattlerb
6
8
 
7
9
  Documentation:
8
10
 
9
- http://dev.robotcoop.com/Tools/ar_mailer
11
+ http://seattlerb.org/ar_mailer
12
+
13
+ Bugs:
14
+
15
+ http://rubyforge.org/tracker/?func=add&group_id=1513&atid=5921
10
16
 
11
17
  == About
12
18
 
data/Rakefile CHANGED
@@ -1,67 +1,12 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'rake/testtask'
4
- require 'rake/rdoctask'
5
- require 'rake/gempackagetask'
1
+ require 'hoe'
6
2
 
7
- $VERBOSE = nil
8
-
9
- spec = Gem::Specification.new do |s|
10
- s.name = 'ar_mailer'
11
- s.version = '1.1.0'
12
- s.summary = 'A two-phase deliver agent for ActionMailer'
13
- s.description = 'Queues emails from ActionMailer in the database and uses a separate process to send them. Reduces sending overhead when sending hundreds of emails.'
3
+ Hoe.new 'ar_mailer', '1.2.0' do |s|
4
+ s.rubyforge_name = 'seattlerb'
5
+ s.summary = s.paragraphs_of('README.txt', 1).join(' ')
6
+ s.description = s.paragraphs_of('README.txt', 9).join(' ')
7
+ s.url = s.paragraphs_of('README.txt', 5).join(' ')
14
8
  s.author = 'Eric Hodel'
15
- s.email = 'eric@robotcoop.com'
16
-
17
- s.has_rdoc = true
18
- s.files = File.read('Manifest.txt').split($/)
19
- s.require_path = 'lib'
20
-
21
- s.executables = ['ar_sendmail']
22
- end
23
-
24
- desc 'Run tests'
25
- task :default => [ :test ]
26
-
27
- Rake::TestTask.new('test') do |t|
28
- t.libs << 'test'
29
- t.pattern = 'test/test_*.rb'
30
- t.verbose = true
31
- end
32
-
33
- desc 'Update Manifest.txt'
34
- task :update_manifest do
35
- sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
9
+ s.email = 'drbrain@segment7.net'
10
+ s.changes = s.paragraphs_of('History.txt', 0..1).join("\n\n")
36
11
  end
37
12
 
38
- desc 'Generate RDoc'
39
- Rake::RDocTask.new :rdoc do |rd|
40
- rd.rdoc_dir = 'doc'
41
- rd.rdoc_files.add 'lib', 'README', 'LICENSE'
42
- rd.main = 'README'
43
- rd.options << '-d' if `which dot` =~ /\/dot/
44
- rd.options << '-t ar_mailer'
45
- end
46
-
47
- desc 'Generate RDoc for dev.robotcoop.com'
48
- Rake::RDocTask.new :dev_rdoc do |rd|
49
- rd.rdoc_dir = '../../../www/trunk/dev/html/Tools/ar_mailer'
50
- rd.rdoc_files.add 'lib', 'README', 'LICENSE'
51
- rd.main = 'README'
52
- rd.options << '-d' if `which dot` =~ /\/dot/
53
- rd.options << '-t ar_mailer'
54
- end
55
-
56
- desc 'Build Gem'
57
- Rake::GemPackageTask.new spec do |pkg|
58
- pkg.need_tar = true
59
- end
60
-
61
- desc 'Clean up'
62
- task :clean => [ :clobber_rdoc, :clobber_package ]
63
-
64
- desc 'Clean up'
65
- task :clobber => [ :clean ]
66
-
67
- # vim: syntax=Ruby
@@ -7,26 +7,26 @@ require 'action_mailer'
7
7
  # == Converting to ActionMailer::ARMailer
8
8
  #
9
9
  # Go to your Rails project:
10
- #
10
+ #
11
11
  # $ cd your_rails_project
12
- #
12
+ #
13
13
  # Create a new migration:
14
- #
14
+ #
15
15
  # $ ar_sendmail --create-migration
16
- #
16
+ #
17
17
  # You'll need to redirect this into a file. If you want a different name
18
18
  # provide the --table-name option.
19
- #
19
+ #
20
20
  # Create a new model:
21
- #
21
+ #
22
22
  # $ ar_sendmail --create-model
23
- #
23
+ #
24
24
  # You'll need to redirect this into a file. If you want a different name
25
25
  # provide the --table-name option.
26
- #
26
+ #
27
27
  # Change your email classes to inherit from ActionMailer::ARMailer instead of
28
28
  # ActionMailer::Base:
29
- #
29
+ #
30
30
  # --- app/model/emailer.rb.orig 2006-08-10 13:16:33.000000000 -0700
31
31
  # +++ app/model/emailer.rb 2006-08-10 13:16:43.000000000 -0700
32
32
  # @@ -1,4 +1,4 @@
@@ -35,31 +35,64 @@ require 'action_mailer'
35
35
  #
36
36
  # def comment_notification(comment)
37
37
  # from comment.author.email
38
- #
38
+ #
39
+ # You'll need to be sure to set the From address for your emails. Something
40
+ # like:
41
+ #
42
+ # def list_send(recipient)
43
+ # from 'no_reply@example.com'
44
+ # # ...
45
+ #
46
+ # Edit config/environment.rb and require ar_mailer.rb:
47
+ #
48
+ # require 'action_mailer/ar_mailer'
49
+ #
39
50
  # Edit config/environments/production.rb and set the delivery agent:
40
- #
51
+ #
41
52
  # $ grep delivery_method config/environments/production.rb
42
53
  # ActionMailer::Base.delivery_method = :activerecord
43
- #
54
+ #
44
55
  # Run ar_sendmail:
45
- #
56
+ #
46
57
  # $ ar_sendmail
47
- #
58
+ #
48
59
  # You can also run it from cron with -o, or as a daemon with -d.
49
60
  #
50
61
  # See <tt>ar_sendmail -h</tt> for full details.
62
+ #
63
+ # == Alternate Mail Storage
64
+ #
65
+ # If you want to set the ActiveRecord model that emails will be stored in,
66
+ # see ActionMailer::ARMailer::email_class=
51
67
 
52
68
  class ActionMailer::ARMailer < ActionMailer::Base
53
69
 
70
+ VERSION = '1.2.0' # :nodoc:
71
+
72
+ @@email_class = Email
73
+
74
+ ##
75
+ # Current email class for deliveries.
76
+
77
+ def self.email_class
78
+ @@email_class
79
+ end
80
+
81
+ ##
82
+ # Sets the email class for deliveries.
83
+
84
+ def self.email_class=(klass)
85
+ @@email_class = klass
86
+ end
87
+
54
88
  ##
55
89
  # Adds +mail+ to the Email table. Only the first From address for +mail+ is
56
90
  # used.
57
91
 
58
92
  def perform_delivery_activerecord(mail)
59
93
  mail.destinations.each do |destination|
60
- Email.create :mail => mail.encoded,
61
- :to => destination,
62
- :from => mail.from.first
94
+ @@email_class.create :mail => mail.encoded, :to => destination,
95
+ :from => mail.from.first
63
96
  end
64
97
  end
65
98
 
@@ -1,6 +1,7 @@
1
1
  require 'optparse'
2
+ require 'net/smtp'
3
+ require 'smtp_tls'
2
4
  require 'rubygems'
3
- require 'action_mailer'
4
5
 
5
6
  class Object # :nodoc:
6
7
  unless respond_to? :path2class then
@@ -13,7 +14,8 @@ end
13
14
  ##
14
15
  # Hack in RSET
15
16
 
16
- class Net::SMTP # :nodoc:
17
+ module Net # :nodoc:
18
+ class SMTP # :nodoc:
17
19
 
18
20
  unless instance_methods.include? 'reset' then
19
21
  ##
@@ -25,10 +27,18 @@ class Net::SMTP # :nodoc:
25
27
  end
26
28
 
27
29
  end
30
+ end
31
+
32
+ module ActionMailer; end # :nodoc:
28
33
 
29
34
  ##
30
35
  # ActionMailer::ARSendmail delivers email from the email table to the
31
- # configured SMTP server.
36
+ # SMTP server configured in your application's config/environment.rb.
37
+ # ar_sendmail does not work with sendmail delivery.
38
+ #
39
+ # ar_mailer can deliver to SMTP with TLS using smtp_tls.rb borrowed from Kyle
40
+ # Maxwell's action_mailer_optional_tls plugin. Simply set the :tls option in
41
+ # ActionMailer::Base's smtp_settings to true to enable TLS.
32
42
  #
33
43
  # See ar_sendmail -h for the full list of supported options.
34
44
  #
@@ -70,6 +80,7 @@ class ActionMailer::ARSendmail
70
80
  # Creates a new migration using +table_name+ and prints it on stdout.
71
81
 
72
82
  def self.create_migration(table_name)
83
+ require 'active_support'
73
84
  puts <<-EOF
74
85
  class Add#{table_name.classify} < ActiveRecord::Migration
75
86
  def self.up
@@ -78,11 +89,12 @@ class Add#{table_name.classify} < ActiveRecord::Migration
78
89
  t.column :to, :string
79
90
  t.column :last_send_attempt, :integer, :default => 0
80
91
  t.column :mail, :text
92
+ t.column :created_on, :datetime
81
93
  end
82
94
  end
83
95
 
84
96
  def self.down
85
- drop_table :email
97
+ drop_table :emails
86
98
  end
87
99
  end
88
100
  EOF
@@ -92,6 +104,7 @@ end
92
104
  # Creates a new model using +table_name+ and prints it on stdout.
93
105
 
94
106
  def self.create_model(table_name)
107
+ require 'active_support'
95
108
  puts <<-EOF
96
109
  class #{table_name.classify} < ActiveRecord::Base
97
110
  end
@@ -105,8 +118,9 @@ end
105
118
  # known. See http://api.rubyonrails.org/classes/ActiveRecord/Timestamp.html
106
119
  # to learn how to enable ActiveRecord::Timestamp.
107
120
 
108
- def self.mailq
109
- emails = Email.find :all
121
+ def self.mailq(table_name)
122
+ klass = table_name.split('::').inject(Object) { |k,n| k.const_get n }
123
+ emails = klass.find :all
110
124
 
111
125
  if emails.empty? then
112
126
  puts "Mail queue is empty"
@@ -285,7 +299,7 @@ end
285
299
  create_model options[:TableName]
286
300
  exit
287
301
  elsif options.include? :MailQ then
288
- mailq
302
+ mailq options[:TableName]
289
303
  exit
290
304
  end
291
305
 
@@ -296,8 +310,14 @@ end
296
310
 
297
311
  new(options).run
298
312
 
299
- rescue Interrupt
313
+ rescue SystemExit
314
+ raise
315
+ rescue SignalException
300
316
  exit
317
+ rescue Exception => e
318
+ $stderr.puts "Unhandled exception #{e.message}(#{e.class}):"
319
+ $stderr.puts "\t#{e.backtrace.join "\n\t"}"
320
+ exit 1
301
321
  end
302
322
 
303
323
  ##
@@ -338,10 +358,12 @@ end
338
358
  # Delivers +emails+ to ActionMailer's SMTP server and destroys them.
339
359
 
340
360
  def deliver(emails)
361
+ user = server_settings[:user] || server_settings[:user_name]
341
362
  Net::SMTP.start server_settings[:address], server_settings[:port],
342
- server_settings[:domain], server_settings[:user],
363
+ server_settings[:domain], user,
343
364
  server_settings[:password],
344
- server_settings[:authentication] do |smtp|
365
+ server_settings[:authentication],
366
+ server_settings[:tls] do |smtp|
345
367
  until emails.empty? do
346
368
  email = emails.shift
347
369
  begin
@@ -354,8 +376,11 @@ end
354
376
  [email.id, e.message, e.class, e.backtrace.join("\n\t")]
355
377
  email.destroy
356
378
  smtp.reset
357
- rescue Net::SMTPServerBusy, Net::SMTPUnknownError,
358
- Net::SMTPSyntaxError, TimeoutError => e
379
+ rescue Net::SMTPServerBusy => e
380
+ log "server too busy, sleeping #{@delay} seconds"
381
+ sleep delay unless $TESTING
382
+ return
383
+ rescue Net::SMTPServerBusy, Net::SMTPUnknownError, Net::SMTPSyntaxError, TimeoutError => e
359
384
  email.last_send_attempt = Time.now.to_i
360
385
  email.save rescue nil
361
386
  log "error sending email %d: %p(%s):\n\t%s" %
@@ -364,6 +389,8 @@ end
364
389
  end
365
390
  end
366
391
  end
392
+ rescue Net::SMTPServerBusy, SystemCallError
393
+ # ignore SMTPServerBusy/EPIPE/ECONNRESET from Net::SMTP.start's ensure
367
394
  end
368
395
 
369
396
  ##
@@ -371,7 +398,7 @@ end
371
398
 
372
399
  def do_exit
373
400
  log "caught signal, shutting down"
374
- raise Interrupt
401
+ exit
375
402
  end
376
403
 
377
404
  ##
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?
@@ -1,4 +1,5 @@
1
1
  require 'net/smtp'
2
+ require 'smtp_tls'
2
3
  require 'time'
3
4
 
4
5
  class Net::SMTP
@@ -15,7 +16,7 @@ class Net::SMTP
15
16
  attr_reader :send_message_block
16
17
  attr_accessor :reset_called
17
18
 
18
- alias old_start start
19
+ send :remove_method, :start
19
20
 
20
21
  end
21
22
 
@@ -33,13 +34,13 @@ class Net::SMTP
33
34
  @reset_called = 0
34
35
  end
35
36
 
36
- alias old_reset reset if instance_methods.include? 'reset'
37
+ alias test_old_reset reset if instance_methods.include? 'reset'
37
38
 
38
39
  def reset
39
40
  self.class.reset_called += 1
40
41
  end
41
42
 
42
- alias old_send_message send_message
43
+ alias test_old_send_message send_message
43
44
 
44
45
  def send_message(mail, to, from)
45
46
  return self.class.send_message_block.call(mail, to, from) unless
@@ -94,7 +95,7 @@ end
94
95
 
95
96
  class Email
96
97
 
97
- START = Time.parse 'Thu Aug 10 11:19:48'
98
+ START = Time.parse 'Thu Aug 10 2006 11:19:48'
98
99
 
99
100
  attr_accessor :from, :to, :mail, :last_send_attempt, :created_on, :id
100
101
 
@@ -145,6 +146,8 @@ class Email
145
146
 
146
147
  end
147
148
 
149
+ Mail = Email
150
+
148
151
  class String
149
152
  def classify
150
153
  self
@@ -19,7 +19,18 @@ end
19
19
  class TestARMailer < Test::Unit::TestCase
20
20
 
21
21
  def setup
22
+ Mailer.email_class = Email
23
+
22
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
23
34
  end
24
35
 
25
36
  def test_perform_delivery_activerecord
@@ -4,6 +4,8 @@ require 'action_mailer/ar_sendmail'
4
4
  require 'rubygems'
5
5
  require 'test/zentest_assertions'
6
6
 
7
+ $TESTING = true
8
+
7
9
  class TestARSendmail < Test::Unit::TestCase
8
10
 
9
11
  def setup
@@ -23,31 +25,6 @@ class TestARSendmail < Test::Unit::TestCase
23
25
  end
24
26
 
25
27
  def test_class_create_migration
26
- out, = util_capture do
27
- ActionMailer::ARSendmail.create_migration 'Email'
28
- end
29
-
30
- expected = <<-EOF
31
- class AddEmail < ActiveRecord::Migration
32
- def self.up
33
- create_table :email do |t|
34
- t.column :from, :string
35
- t.column :to, :string
36
- t.column :last_send_attempt, :integer, :default => 0
37
- t.column :mail, :text
38
- end
39
- end
40
-
41
- def self.down
42
- drop_table :email
43
- end
44
- end
45
- EOF
46
-
47
- assert_equal expected, out.string
48
- end
49
-
50
- def test_class_create_migration_table_name
51
28
  out, = util_capture do
52
29
  ActionMailer::ARSendmail.create_migration 'Mail'
53
30
  end
@@ -60,11 +37,12 @@ class AddMail < ActiveRecord::Migration
60
37
  t.column :to, :string
61
38
  t.column :last_send_attempt, :integer, :default => 0
62
39
  t.column :mail, :text
40
+ t.column :created_on, :datetime
63
41
  end
64
42
  end
65
43
 
66
44
  def self.down
67
- drop_table :email
45
+ drop_table :emails
68
46
  end
69
47
  end
70
48
  EOF
@@ -73,19 +51,6 @@ end
73
51
  end
74
52
 
75
53
  def test_class_create_model
76
- out, = util_capture do
77
- ActionMailer::ARSendmail.create_model 'Email'
78
- end
79
-
80
- expected = <<-EOF
81
- class Email < ActiveRecord::Base
82
- end
83
- EOF
84
-
85
- assert_equal expected, out.string
86
- end
87
-
88
- def test_class_create_model_table_name
89
54
  out, = util_capture do
90
55
  ActionMailer::ARSendmail.create_model 'Mail'
91
56
  end
@@ -106,10 +71,10 @@ end
106
71
  last = Email.create :from => nobody, :to => 'recip@h2.example.com',
107
72
  :mail => 'body2'
108
73
 
109
- last.last_send_attempt = Time.parse('Thu Aug 10 11:40:05').to_i
74
+ last.last_send_attempt = Time.parse('Thu Aug 10 2006 11:40:05').to_i
110
75
 
111
76
  out, err = util_capture do
112
- ActionMailer::ARSendmail.mailq
77
+ ActionMailer::ARSendmail.mailq 'Email'
113
78
  end
114
79
 
115
80
  expected = <<-EOF
@@ -132,7 +97,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
132
97
 
133
98
  def test_class_mailq_empty
134
99
  out, err = util_capture do
135
- ActionMailer::ARSendmail.mailq
100
+ ActionMailer::ARSendmail.mailq 'Email'
136
101
  end
137
102
 
138
103
  assert_equal "Mail queue is empty\n", out.string
@@ -232,7 +197,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
232
197
 
233
198
  def test_class_parse_args_mailq
234
199
  options = ActionMailer::ARSendmail.process_args []
235
- deny_includes options, :MailQ
200
+ deny_includes :MailQ, options
236
201
 
237
202
  argv = %w[--mailq]
238
203
 
@@ -243,7 +208,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
243
208
 
244
209
  def test_class_parse_args_migration
245
210
  options = ActionMailer::ARSendmail.process_args []
246
- deny_includes options, :Migrate
211
+ deny_includes :Migration, options
247
212
 
248
213
  argv = %w[--create-migration]
249
214
 
@@ -254,7 +219,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
254
219
 
255
220
  def test_class_parse_args_model
256
221
  options = ActionMailer::ARSendmail.process_args []
257
- deny_includes options, :Model
222
+ deny_includes :Model, options
258
223
 
259
224
  argv = %w[--create-model]
260
225
 
@@ -371,7 +336,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
371
336
 
372
337
  def test_deliver_4xx_error
373
338
  Net::SMTP.on_send_message do
374
- e = Net::SMTPServerBusy.new 'try again'
339
+ e = Net::SMTPSyntaxError.new 'try again'
375
340
  e.set_backtrace %w[one two three]
376
341
  raise e
377
342
  end
@@ -390,7 +355,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
390
355
  assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
391
356
 
392
357
  assert_equal '', out.string
393
- assert_equal "error sending email 1: \"try again\"(Net::SMTPServerBusy):\n\tone\n\ttwo\n\tthree\n", err.string
358
+ assert_equal "error sending email 1: \"try again\"(Net::SMTPSyntaxError):\n\tone\n\ttwo\n\tthree\n", err.string
394
359
  end
395
360
 
396
361
  def test_deliver_5xx_error
@@ -416,6 +381,52 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
416
381
  assert_equal "5xx error sending email 1, removing from queue: \"unknown recipient\"(Net::SMTPFatalError):\n\tone\n\ttwo\n\tthree\n", err.string
417
382
  end
418
383
 
384
+ def test_deliver_errno_epipe
385
+ Net::SMTP.on_send_message do
386
+ raise Errno::EPIPE
387
+ end
388
+
389
+ now = Time.now.to_i
390
+
391
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
392
+
393
+ out, err = util_capture do
394
+ @sm.deliver [email]
395
+ end
396
+
397
+ assert_equal 0, Net::SMTP.deliveries.length
398
+ assert_equal 1, Email.records.length
399
+ assert_operator now, :>=, Email.records.first.last_send_attempt
400
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
401
+
402
+ assert_equal '', out.string
403
+ assert_equal '', err.string
404
+ end
405
+
406
+ def test_deliver_server_busy
407
+ Net::SMTP.on_send_message do
408
+ e = Net::SMTPServerBusy.new 'try again'
409
+ e.set_backtrace %w[one two three]
410
+ raise e
411
+ end
412
+
413
+ now = Time.now.to_i
414
+
415
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
416
+
417
+ out, err = util_capture do
418
+ @sm.deliver [email]
419
+ end
420
+
421
+ assert_equal 0, Net::SMTP.deliveries.length
422
+ assert_equal 1, Email.records.length
423
+ assert_operator now, :>=, Email.records.first.last_send_attempt
424
+ assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
425
+
426
+ assert_equal '', out.string
427
+ assert_equal "server too busy, sleeping 60 seconds\n", err.string
428
+ end
429
+
419
430
  def test_deliver_syntax_error
420
431
  Net::SMTP.on_send_message do
421
432
  Net::SMTP.on_send_message # clear
@@ -433,7 +444,7 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
433
444
  @sm.deliver [email1, email2]
434
445
  end
435
446
 
436
- assert_equal 1, Net::SMTP.deliveries.length
447
+ assert_equal 1, Net::SMTP.deliveries.length, 'delivery count'
437
448
  assert_equal 1, Email.records.length
438
449
  assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
439
450
  assert_operator now, :<=, Email.records.first.last_send_attempt
@@ -442,9 +453,33 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
442
453
  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
443
454
  end
444
455
 
456
+ def test_deliver_timeout
457
+ Net::SMTP.on_send_message do
458
+ e = Timeout::Error.new 'timed out'
459
+ e.set_backtrace %w[one two three]
460
+ raise e
461
+ end
462
+
463
+ now = Time.now.to_i
464
+
465
+ email = Email.create :mail => 'body', :to => 'to', :from => 'from'
466
+
467
+ out, err = util_capture do
468
+ @sm.deliver [email]
469
+ end
470
+
471
+ assert_equal 0, Net::SMTP.deliveries.length
472
+ assert_equal 1, Email.records.length
473
+ assert_operator now, :>=, Email.records.first.last_send_attempt
474
+ assert_equal 1, Net::SMTP.reset_called, 'Reset connection on Timeout'
475
+
476
+ assert_equal '', out.string
477
+ assert_equal "error sending email 1: \"timed out\"(Timeout::Error):\n\tone\n\ttwo\n\tthree\n", err.string
478
+ end
479
+
445
480
  def test_do_exit
446
481
  out, err = util_capture do
447
- assert_raise Interrupt do
482
+ assert_raise SystemExit do
448
483
  @sm.do_exit
449
484
  end
450
485
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.99
2
+ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ar_mailer
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.1.0
7
- date: 2006-08-18 00:00:00 -07:00
8
- summary: A two-phase deliver agent for ActionMailer
6
+ version: 1.2.0
7
+ date: 2007-06-05 00:00:00 -07:00
8
+ summary: A two-phase delivery agent for ActionMailer
9
9
  require_paths:
10
10
  - lib
11
- email: eric@robotcoop.com
12
- homepage:
13
- rubyforge_project:
14
- description: Queues emails from ActionMailer in the database and uses a separate process to send them. Reduces sending overhead when sending hundreds of emails.
11
+ email: drbrain@segment7.net
12
+ homepage: http://seattlerb.org/ar_mailer
13
+ rubyforge_project: seattlerb
14
+ description: Even deliviring 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.
15
15
  autorequire:
16
16
  default_executable:
17
17
  bindir: bin
@@ -29,28 +29,43 @@ post_install_message:
29
29
  authors:
30
30
  - Eric Hodel
31
31
  files:
32
- - LICENSE
32
+ - History.txt
33
+ - LICENSE.txt
33
34
  - Manifest.txt
34
- - README
35
+ - README.txt
35
36
  - Rakefile
36
37
  - bin/ar_sendmail
37
38
  - lib/action_mailer/ar_mailer.rb
38
39
  - lib/action_mailer/ar_sendmail.rb
40
+ - lib/smtp_tls.rb
39
41
  - share/ar_sendmail
40
42
  - test/action_mailer.rb
41
43
  - test/test_armailer.rb
42
44
  - test/test_arsendmail.rb
43
- test_files: []
44
-
45
- rdoc_options: []
46
-
47
- extra_rdoc_files: []
48
-
45
+ test_files:
46
+ - test/test_armailer.rb
47
+ - test/test_arsendmail.rb
48
+ rdoc_options:
49
+ - --main
50
+ - README.txt
51
+ extra_rdoc_files:
52
+ - History.txt
53
+ - LICENSE.txt
54
+ - Manifest.txt
55
+ - README.txt
49
56
  executables:
50
57
  - ar_sendmail
51
58
  extensions: []
52
59
 
53
60
  requirements: []
54
61
 
55
- dependencies: []
56
-
62
+ dependencies:
63
+ - !ruby/object:Gem::Dependency
64
+ name: hoe
65
+ version_requirement:
66
+ version_requirements: !ruby/object:Gem::Version::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 1.2.1
71
+ version: