ar_mailer 1.0.1 → 1.1.0
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.
- data/Manifest.txt +1 -0
- data/README +5 -1
- data/Rakefile +1 -1
- data/bin/ar_sendmail +0 -5
- data/lib/action_mailer/ar_mailer.rb +3 -2
- data/lib/action_mailer/ar_sendmail.rb +116 -33
- data/share/ar_sendmail +30 -0
- data/test/action_mailer.rb +31 -4
- data/test/test_arsendmail.rb +157 -23
- metadata +3 -2
data/Manifest.txt
CHANGED
data/README
CHANGED
@@ -6,7 +6,7 @@ http://rubyforge.org/projects/rctools
|
|
6
6
|
|
7
7
|
Documentation:
|
8
8
|
|
9
|
-
http://dev.robotcoop.com/
|
9
|
+
http://dev.robotcoop.com/Tools/ar_mailer
|
10
10
|
|
11
11
|
== About
|
12
12
|
|
@@ -24,3 +24,7 @@ See ActionMailer::ARMailer for instructions on converting to ARMailer.
|
|
24
24
|
|
25
25
|
See ar_sendmail -h for options to ar_sendmail.
|
26
26
|
|
27
|
+
=== ar_sendmail on FreeBSD or NetBSD
|
28
|
+
|
29
|
+
An rc.d script is included in share/ar_sendmail.
|
30
|
+
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ $VERBOSE = nil
|
|
8
8
|
|
9
9
|
spec = Gem::Specification.new do |s|
|
10
10
|
s.name = 'ar_mailer'
|
11
|
-
s.version = '1.0
|
11
|
+
s.version = '1.1.0'
|
12
12
|
s.summary = 'A two-phase deliver agent for ActionMailer'
|
13
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.'
|
14
14
|
s.author = 'Eric Hodel'
|
data/bin/ar_sendmail
CHANGED
@@ -36,9 +36,10 @@ require 'action_mailer'
|
|
36
36
|
# def comment_notification(comment)
|
37
37
|
# from comment.author.email
|
38
38
|
#
|
39
|
-
# Edit config/
|
39
|
+
# Edit config/environments/production.rb and set the delivery agent:
|
40
40
|
#
|
41
|
-
# $
|
41
|
+
# $ grep delivery_method config/environments/production.rb
|
42
|
+
# ActionMailer::Base.delivery_method = :activerecord
|
42
43
|
#
|
43
44
|
# Run ar_sendmail:
|
44
45
|
#
|
@@ -10,6 +10,22 @@ class Object # :nodoc:
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
##
|
14
|
+
# Hack in RSET
|
15
|
+
|
16
|
+
class Net::SMTP # :nodoc:
|
17
|
+
|
18
|
+
unless instance_methods.include? 'reset' then
|
19
|
+
##
|
20
|
+
# Resets the SMTP connection.
|
21
|
+
|
22
|
+
def reset
|
23
|
+
getok 'RSET'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
13
29
|
##
|
14
30
|
# ActionMailer::ARSendmail delivers email from the email table to the
|
15
31
|
# configured SMTP server.
|
@@ -51,10 +67,10 @@ class ActionMailer::ARSendmail
|
|
51
67
|
attr_reader :once
|
52
68
|
|
53
69
|
##
|
54
|
-
# Creates a new migration using +table_name+ and prints it on
|
70
|
+
# Creates a new migration using +table_name+ and prints it on stdout.
|
55
71
|
|
56
72
|
def self.create_migration(table_name)
|
57
|
-
|
73
|
+
puts <<-EOF
|
58
74
|
class Add#{table_name.classify} < ActiveRecord::Migration
|
59
75
|
def self.up
|
60
76
|
create_table :#{table_name.tableize} do |t|
|
@@ -70,20 +86,16 @@ class Add#{table_name.classify} < ActiveRecord::Migration
|
|
70
86
|
end
|
71
87
|
end
|
72
88
|
EOF
|
73
|
-
|
74
|
-
$stdout.puts migration
|
75
89
|
end
|
76
90
|
|
77
91
|
##
|
78
|
-
# Creates a new model using +table_name+ and prints it on
|
92
|
+
# Creates a new model using +table_name+ and prints it on stdout.
|
79
93
|
|
80
94
|
def self.create_model(table_name)
|
81
|
-
|
95
|
+
puts <<-EOF
|
82
96
|
class #{table_name.classify} < ActiveRecord::Base
|
83
97
|
end
|
84
98
|
EOF
|
85
|
-
|
86
|
-
$stdout.puts model
|
87
99
|
end
|
88
100
|
|
89
101
|
##
|
@@ -97,13 +109,13 @@ end
|
|
97
109
|
emails = Email.find :all
|
98
110
|
|
99
111
|
if emails.empty? then
|
100
|
-
|
112
|
+
puts "Mail queue is empty"
|
101
113
|
return
|
102
114
|
end
|
103
115
|
|
104
116
|
total_size = 0
|
105
117
|
|
106
|
-
|
118
|
+
puts "-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------"
|
107
119
|
emails.each do |email|
|
108
120
|
size = email.mail.length
|
109
121
|
total_size += size
|
@@ -119,15 +131,15 @@ end
|
|
119
131
|
create_timestamp.strftime '%a %b %d %H:%M:%S'
|
120
132
|
end
|
121
133
|
|
122
|
-
|
123
|
-
if email.last_send_attempt then
|
124
|
-
|
134
|
+
puts "%10d %8d %s %s" % [email.id, size, created, email.from]
|
135
|
+
if email.last_send_attempt > 0 then
|
136
|
+
puts "Last send attempt: #{Time.at email.last_send_attempt}"
|
125
137
|
end
|
126
|
-
|
127
|
-
|
138
|
+
puts " #{email.to}"
|
139
|
+
puts
|
128
140
|
end
|
129
141
|
|
130
|
-
|
142
|
+
puts "-- #{total_size/1024} Kbytes in #{emails.length} Requests."
|
131
143
|
end
|
132
144
|
|
133
145
|
##
|
@@ -141,6 +153,8 @@ end
|
|
141
153
|
options[:Delay] = 60
|
142
154
|
options[:Once] = false
|
143
155
|
options[:TableName] = 'Email'
|
156
|
+
options[:Chdir] = '.'
|
157
|
+
options[:RailsEnv] = ENV['RAILS_ENV']
|
144
158
|
|
145
159
|
opts = OptionParser.new do |opts|
|
146
160
|
opts.banner = "Usage: #{name} [options]"
|
@@ -149,7 +163,7 @@ end
|
|
149
163
|
opts.separator "#{name} scans the email table for new messages and sends them to the"
|
150
164
|
opts.separator "website's configured SMTP host."
|
151
165
|
opts.separator ''
|
152
|
-
opts.separator "#{name} must be run from
|
166
|
+
opts.separator "#{name} must be run from a Rails application's root."
|
153
167
|
|
154
168
|
opts.separator ''
|
155
169
|
opts.separator 'Sendmail options:'
|
@@ -189,19 +203,33 @@ end
|
|
189
203
|
|
190
204
|
opts.on( "--create-migration",
|
191
205
|
"Prints a migration to add an Email table",
|
192
|
-
"to
|
206
|
+
"to stdout") do |create|
|
193
207
|
options[:Migrate] = true
|
194
208
|
end
|
195
209
|
|
196
210
|
opts.on( "--create-model",
|
197
211
|
"Prints a model for an Email ActiveRecord",
|
198
|
-
"object to
|
212
|
+
"object to stdout") do |create|
|
199
213
|
options[:Model] = true
|
200
214
|
end
|
201
215
|
|
202
216
|
opts.separator ''
|
203
217
|
opts.separator 'Generic Options:'
|
204
218
|
|
219
|
+
opts.on("-c", "--chdir PATH",
|
220
|
+
"Use PATH for the application path",
|
221
|
+
"Default: #{options[:Chdir]}") do |path|
|
222
|
+
usage opts, "#{path} is not a directory" unless File.directory? path
|
223
|
+
usage opts, "#{path} is not readable" unless File.readable? path
|
224
|
+
options[:Chdir] = path
|
225
|
+
end
|
226
|
+
|
227
|
+
opts.on("-e", "--environment RAILS_ENV",
|
228
|
+
"Set the RAILS_ENV constant",
|
229
|
+
"Default: #{options[:RailsEnv]}") do |env|
|
230
|
+
options[:RailsEnv] = env
|
231
|
+
end
|
232
|
+
|
205
233
|
opts.on("-t", "--table-name TABLE_NAME",
|
206
234
|
"Name of table holding emails",
|
207
235
|
"Used for both sendmail and",
|
@@ -218,8 +246,7 @@ end
|
|
218
246
|
|
219
247
|
opts.on("-h", "--help",
|
220
248
|
"You're looking at it") do
|
221
|
-
|
222
|
-
exit 1
|
249
|
+
usage opts
|
223
250
|
end
|
224
251
|
|
225
252
|
opts.separator ''
|
@@ -227,12 +254,19 @@ end
|
|
227
254
|
|
228
255
|
opts.parse! args
|
229
256
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
257
|
+
return options if options.include? :Migrate or options.include? :Model
|
258
|
+
|
259
|
+
ENV['RAILS_ENV'] = options[:RailsEnv]
|
260
|
+
|
261
|
+
Dir.chdir options[:Chdir] do
|
262
|
+
begin
|
263
|
+
require 'config/environment'
|
264
|
+
rescue LoadError
|
265
|
+
usage opts, <<-EOF
|
266
|
+
#{name} must be run from a Rails application's root to deliver email.
|
267
|
+
#{Dir.pwd} does not appear to be a Rails application root.
|
268
|
+
EOF
|
269
|
+
end
|
236
270
|
end
|
237
271
|
|
238
272
|
return options
|
@@ -261,6 +295,22 @@ end
|
|
261
295
|
end
|
262
296
|
|
263
297
|
new(options).run
|
298
|
+
|
299
|
+
rescue Interrupt
|
300
|
+
exit
|
301
|
+
end
|
302
|
+
|
303
|
+
##
|
304
|
+
# Prints a usage message to $stderr using +opts+ and exits
|
305
|
+
|
306
|
+
def self.usage(opts, message = nil)
|
307
|
+
if message then
|
308
|
+
$stderr.puts message
|
309
|
+
$stderr.puts
|
310
|
+
end
|
311
|
+
|
312
|
+
$stderr.puts opts
|
313
|
+
exit 1
|
264
314
|
end
|
265
315
|
|
266
316
|
##
|
@@ -292,19 +342,38 @@ end
|
|
292
342
|
server_settings[:domain], server_settings[:user],
|
293
343
|
server_settings[:password],
|
294
344
|
server_settings[:authentication] do |smtp|
|
295
|
-
emails.
|
345
|
+
until emails.empty? do
|
346
|
+
email = emails.shift
|
296
347
|
begin
|
297
348
|
res = smtp.send_message email.mail, email.from, email.to
|
298
349
|
email.destroy
|
299
|
-
log "sent email from %s to %s: %p" %
|
300
|
-
|
301
|
-
|
350
|
+
log "sent email %011d from %s to %s: %p" %
|
351
|
+
[email.id, email.from, email.to, res]
|
352
|
+
rescue Net::SMTPFatalError => e
|
353
|
+
log "5xx error sending email %d, removing from queue: %p(%s):\n\t%s" %
|
354
|
+
[email.id, e.message, e.class, e.backtrace.join("\n\t")]
|
355
|
+
email.destroy
|
356
|
+
smtp.reset
|
357
|
+
rescue Net::SMTPServerBusy, Net::SMTPUnknownError,
|
358
|
+
Net::SMTPSyntaxError, TimeoutError => e
|
302
359
|
email.last_send_attempt = Time.now.to_i
|
360
|
+
email.save rescue nil
|
361
|
+
log "error sending email %d: %p(%s):\n\t%s" %
|
362
|
+
[email.id, e.message, e.class, e.backtrace.join("\n\t")]
|
363
|
+
smtp.reset
|
303
364
|
end
|
304
365
|
end
|
305
366
|
end
|
306
367
|
end
|
307
368
|
|
369
|
+
##
|
370
|
+
# Prepares ar_sendmail for exiting
|
371
|
+
|
372
|
+
def do_exit
|
373
|
+
log "caught signal, shutting down"
|
374
|
+
raise Interrupt
|
375
|
+
end
|
376
|
+
|
308
377
|
##
|
309
378
|
# Returns emails in email_class that haven't had a delivery attempt in the
|
310
379
|
# last 300 seconds.
|
@@ -318,6 +387,14 @@ end
|
|
318
387
|
mail
|
319
388
|
end
|
320
389
|
|
390
|
+
##
|
391
|
+
# Installs signal handlers to gracefully exit.
|
392
|
+
|
393
|
+
def install_signal_handlers
|
394
|
+
trap 'TERM' do do_exit end
|
395
|
+
trap 'INT' do do_exit end
|
396
|
+
end
|
397
|
+
|
321
398
|
##
|
322
399
|
# Logs +message+ if verbose
|
323
400
|
|
@@ -331,10 +408,16 @@ end
|
|
331
408
|
# once is true.
|
332
409
|
|
333
410
|
def run
|
411
|
+
install_signal_handlers
|
412
|
+
|
334
413
|
loop do
|
335
|
-
|
414
|
+
now = Time.now
|
415
|
+
begin
|
416
|
+
deliver find_emails
|
417
|
+
rescue ActiveRecord::Transactions::TransactionError
|
418
|
+
end
|
336
419
|
break if @once
|
337
|
-
sleep @delay
|
420
|
+
sleep @delay if now + @delay > Time.now
|
338
421
|
end
|
339
422
|
end
|
340
423
|
|
data/share/ar_sendmail
ADDED
@@ -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
|
+
|
data/test/action_mailer.rb
CHANGED
@@ -3,6 +3,8 @@ require 'time'
|
|
3
3
|
|
4
4
|
class Net::SMTP
|
5
5
|
|
6
|
+
@reset_called = 0
|
7
|
+
|
6
8
|
@deliveries = []
|
7
9
|
|
8
10
|
@send_message_block = nil
|
@@ -11,6 +13,7 @@ class Net::SMTP
|
|
11
13
|
|
12
14
|
attr_reader :deliveries
|
13
15
|
attr_reader :send_message_block
|
16
|
+
attr_accessor :reset_called
|
14
17
|
|
15
18
|
alias old_start start
|
16
19
|
|
@@ -24,12 +27,25 @@ class Net::SMTP
|
|
24
27
|
@send_message_block = block
|
25
28
|
end
|
26
29
|
|
30
|
+
def self.reset
|
31
|
+
deliveries.clear
|
32
|
+
on_send_message
|
33
|
+
@reset_called = 0
|
34
|
+
end
|
35
|
+
|
36
|
+
alias old_reset reset if instance_methods.include? 'reset'
|
37
|
+
|
38
|
+
def reset
|
39
|
+
self.class.reset_called += 1
|
40
|
+
end
|
41
|
+
|
27
42
|
alias old_send_message send_message
|
28
43
|
|
29
44
|
def send_message(mail, to, from)
|
30
45
|
return self.class.send_message_block.call(mail, to, from) unless
|
31
46
|
self.class.send_message_block.nil?
|
32
47
|
self.class.deliveries << [mail, to, from]
|
48
|
+
return "queued"
|
33
49
|
end
|
34
50
|
|
35
51
|
end
|
@@ -55,6 +71,10 @@ class ActionMailer::Base
|
|
55
71
|
new($1, *args).deliver!
|
56
72
|
end
|
57
73
|
|
74
|
+
def self.reset
|
75
|
+
server_settings.clear
|
76
|
+
end
|
77
|
+
|
58
78
|
def self.server_settings
|
59
79
|
@server_settings
|
60
80
|
end
|
@@ -93,16 +113,22 @@ class Email
|
|
93
113
|
return records if conditions.nil?
|
94
114
|
now = Time.now.to_i - 300
|
95
115
|
return records.select do |r|
|
96
|
-
r.last_send_attempt
|
116
|
+
r.last_send_attempt < now
|
97
117
|
end
|
98
118
|
end
|
99
119
|
|
120
|
+
def self.reset
|
121
|
+
@id = 0
|
122
|
+
records.clear
|
123
|
+
end
|
124
|
+
|
100
125
|
def initialize(from, to, mail)
|
101
126
|
@from = from
|
102
127
|
@to = to
|
103
128
|
@mail = mail
|
104
129
|
@id = self.class.id += 1
|
105
130
|
@created_on = START + @id
|
131
|
+
@last_send_attempt = 0
|
106
132
|
end
|
107
133
|
|
108
134
|
def destroy
|
@@ -111,9 +137,10 @@ class Email
|
|
111
137
|
end
|
112
138
|
|
113
139
|
def ==(other)
|
114
|
-
other.
|
115
|
-
|
116
|
-
|
140
|
+
other.id == id
|
141
|
+
end
|
142
|
+
|
143
|
+
def save
|
117
144
|
end
|
118
145
|
|
119
146
|
end
|
data/test/test_arsendmail.rb
CHANGED
@@ -7,13 +7,12 @@ require 'test/zentest_assertions'
|
|
7
7
|
class TestARSendmail < Test::Unit::TestCase
|
8
8
|
|
9
9
|
def setup
|
10
|
-
ActionMailer::Base.
|
11
|
-
Email.
|
12
|
-
|
13
|
-
Net::SMTP.deliveries.clear
|
14
|
-
Net::SMTP.on_send_message # reset
|
10
|
+
ActionMailer::Base.reset
|
11
|
+
Email.reset
|
12
|
+
Net::SMTP.reset
|
15
13
|
|
16
14
|
@sm = ActionMailer::ARSendmail.new
|
15
|
+
@sm.verbose = true
|
17
16
|
|
18
17
|
@include_c_e = ! $".grep(/config\/environment.rb/).empty?
|
19
18
|
$" << 'config/environment.rb' unless @include_c_e
|
@@ -107,7 +106,7 @@ end
|
|
107
106
|
last = Email.create :from => nobody, :to => 'recip@h2.example.com',
|
108
107
|
:mail => 'body2'
|
109
108
|
|
110
|
-
last.last_send_attempt = Time.parse
|
109
|
+
last.last_send_attempt = Time.parse('Thu Aug 10 11:40:05').to_i
|
111
110
|
|
112
111
|
out, err = util_capture do
|
113
112
|
ActionMailer::ARSendmail.mailq
|
@@ -140,6 +139,8 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
140
139
|
end
|
141
140
|
|
142
141
|
def test_class_new
|
142
|
+
@sm = ActionMailer::ARSendmail.new
|
143
|
+
|
143
144
|
assert_equal 60, @sm.delay
|
144
145
|
assert_equal Email, @sm.email_class
|
145
146
|
assert_equal nil, @sm.once
|
@@ -167,6 +168,28 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
167
168
|
assert_equal 500, options[:BatchSize]
|
168
169
|
end
|
169
170
|
|
171
|
+
def test_class_parse_args_chdir
|
172
|
+
argv = %w[-c /tmp]
|
173
|
+
|
174
|
+
options = ActionMailer::ARSendmail.process_args argv
|
175
|
+
|
176
|
+
assert_equal '/tmp', options[:Chdir]
|
177
|
+
|
178
|
+
argv = %w[--chdir /tmp]
|
179
|
+
|
180
|
+
options = ActionMailer::ARSendmail.process_args argv
|
181
|
+
|
182
|
+
assert_equal '/tmp', options[:Chdir]
|
183
|
+
|
184
|
+
argv = %w[-c /nonexistent]
|
185
|
+
|
186
|
+
out, err = util_capture do
|
187
|
+
assert_raises SystemExit do
|
188
|
+
ActionMailer::ARSendmail.process_args argv
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
170
193
|
def test_class_parse_args_daemon
|
171
194
|
argv = %w[-d]
|
172
195
|
|
@@ -189,6 +212,24 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
189
212
|
assert_equal 75, options[:Delay]
|
190
213
|
end
|
191
214
|
|
215
|
+
def test_class_parse_args_environment
|
216
|
+
assert_equal nil, ENV['RAILS_ENV']
|
217
|
+
|
218
|
+
argv = %w[-e production]
|
219
|
+
|
220
|
+
options = ActionMailer::ARSendmail.process_args argv
|
221
|
+
|
222
|
+
assert_equal 'production', options[:RailsEnv]
|
223
|
+
|
224
|
+
assert_equal 'production', ENV['RAILS_ENV']
|
225
|
+
|
226
|
+
argv = %w[--environment production]
|
227
|
+
|
228
|
+
options = ActionMailer::ARSendmail.process_args argv
|
229
|
+
|
230
|
+
assert_equal 'production', options[:RailsEnv]
|
231
|
+
end
|
232
|
+
|
192
233
|
def test_class_parse_args_mailq
|
193
234
|
options = ActionMailer::ARSendmail.process_args []
|
194
235
|
deny_includes options, :MailQ
|
@@ -225,8 +266,8 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
225
266
|
def test_class_parse_args_no_config_environment
|
226
267
|
$".delete 'config/environment.rb'
|
227
268
|
|
228
|
-
|
229
|
-
|
269
|
+
out, err = util_capture do
|
270
|
+
assert_raise SystemExit do
|
230
271
|
ActionMailer::ARSendmail.process_args []
|
231
272
|
end
|
232
273
|
end
|
@@ -292,35 +333,127 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
292
333
|
assert_equal 'Email', options[:TableName]
|
293
334
|
end
|
294
335
|
|
336
|
+
def test_class_usage
|
337
|
+
out, err = util_capture do
|
338
|
+
assert_raises SystemExit do
|
339
|
+
ActionMailer::ARSendmail.usage 'opts'
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
assert_equal '', out.string
|
344
|
+
assert_equal "opts\n", err.string
|
345
|
+
|
346
|
+
out, err = util_capture do
|
347
|
+
assert_raises SystemExit do
|
348
|
+
ActionMailer::ARSendmail.usage 'opts', 'hi'
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
assert_equal '', out.string
|
353
|
+
assert_equal "hi\n\nopts\n", err.string
|
354
|
+
end
|
355
|
+
|
295
356
|
def test_deliver
|
296
357
|
email = Email.create :mail => 'body', :to => 'to', :from => 'from'
|
297
358
|
|
298
|
-
|
359
|
+
out, err = util_capture do
|
360
|
+
@sm.deliver [email]
|
361
|
+
end
|
299
362
|
|
300
363
|
assert_equal 1, Net::SMTP.deliveries.length
|
301
364
|
assert_equal ['body', 'from', 'to'], Net::SMTP.deliveries.first
|
302
365
|
assert_equal 0, Email.records.length
|
366
|
+
assert_equal 0, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
|
367
|
+
|
368
|
+
assert_equal '', out.string
|
369
|
+
assert_equal "sent email 00000000001 from from to to: \"queued\"\n", err.string
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_deliver_4xx_error
|
373
|
+
Net::SMTP.on_send_message do
|
374
|
+
e = Net::SMTPServerBusy.new 'try again'
|
375
|
+
e.set_backtrace %w[one two three]
|
376
|
+
raise e
|
377
|
+
end
|
378
|
+
|
379
|
+
now = Time.now.to_i
|
380
|
+
|
381
|
+
email = Email.create :mail => 'body', :to => 'to', :from => 'from'
|
382
|
+
|
383
|
+
out, err = util_capture do
|
384
|
+
@sm.deliver [email]
|
385
|
+
end
|
386
|
+
|
387
|
+
assert_equal 0, Net::SMTP.deliveries.length
|
388
|
+
assert_equal 1, Email.records.length
|
389
|
+
assert_operator now, :<=, Email.records.first.last_send_attempt
|
390
|
+
assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
|
391
|
+
|
392
|
+
assert_equal '', out.string
|
393
|
+
assert_equal "error sending email 1: \"try again\"(Net::SMTPServerBusy):\n\tone\n\ttwo\n\tthree\n", err.string
|
303
394
|
end
|
304
395
|
|
305
|
-
def
|
396
|
+
def test_deliver_5xx_error
|
306
397
|
Net::SMTP.on_send_message do
|
307
|
-
|
398
|
+
e = Net::SMTPFatalError.new 'unknown recipient'
|
399
|
+
e.set_backtrace %w[one two three]
|
400
|
+
raise e
|
308
401
|
end
|
309
402
|
|
310
403
|
now = Time.now.to_i
|
311
404
|
|
312
405
|
email = Email.create :mail => 'body', :to => 'to', :from => 'from'
|
313
406
|
|
314
|
-
|
407
|
+
out, err = util_capture do
|
408
|
+
@sm.deliver [email]
|
409
|
+
end
|
315
410
|
|
316
411
|
assert_equal 0, Net::SMTP.deliveries.length
|
412
|
+
assert_equal 0, Email.records.length
|
413
|
+
assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
|
414
|
+
|
415
|
+
assert_equal '', out.string
|
416
|
+
assert_equal "5xx error sending email 1, removing from queue: \"unknown recipient\"(Net::SMTPFatalError):\n\tone\n\ttwo\n\tthree\n", err.string
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_deliver_syntax_error
|
420
|
+
Net::SMTP.on_send_message do
|
421
|
+
Net::SMTP.on_send_message # clear
|
422
|
+
e = Net::SMTPSyntaxError.new 'blah blah blah'
|
423
|
+
e.set_backtrace %w[one two three]
|
424
|
+
raise e
|
425
|
+
end
|
426
|
+
|
427
|
+
now = Time.now.to_i
|
428
|
+
|
429
|
+
email1 = Email.create :mail => 'body', :to => 'to', :from => 'from'
|
430
|
+
email2 = Email.create :mail => 'body', :to => 'to', :from => 'from'
|
431
|
+
|
432
|
+
out, err = util_capture do
|
433
|
+
@sm.deliver [email1, email2]
|
434
|
+
end
|
435
|
+
|
436
|
+
assert_equal 1, Net::SMTP.deliveries.length
|
317
437
|
assert_equal 1, Email.records.length
|
438
|
+
assert_equal 1, Net::SMTP.reset_called, 'Reset connection on SyntaxError'
|
318
439
|
assert_operator now, :<=, Email.records.first.last_send_attempt
|
440
|
+
|
441
|
+
assert_equal '', out.string
|
442
|
+
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
|
319
443
|
end
|
320
444
|
|
321
|
-
def
|
322
|
-
|
445
|
+
def test_do_exit
|
446
|
+
out, err = util_capture do
|
447
|
+
assert_raise Interrupt do
|
448
|
+
@sm.do_exit
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
assert_equal '', out.string
|
453
|
+
assert_equal "caught signal, shutting down\n", err.string
|
454
|
+
end
|
323
455
|
|
456
|
+
def test_log
|
324
457
|
out, err = util_capture do
|
325
458
|
@sm.log 'hi'
|
326
459
|
end
|
@@ -329,28 +462,29 @@ Last send attempt: Thu Aug 10 11:40:05 -0700 2006
|
|
329
462
|
end
|
330
463
|
|
331
464
|
def test_find_emails
|
332
|
-
|
465
|
+
email_data = [
|
333
466
|
{ :mail => 'body0', :to => 'recip@h1.example.com', :from => nobody },
|
334
467
|
{ :mail => 'body1', :to => 'recip@h1.example.com', :from => nobody },
|
335
468
|
{ :mail => 'body2', :to => 'recip@h2.example.com', :from => nobody },
|
336
469
|
]
|
337
470
|
|
338
|
-
emails.
|
471
|
+
emails = email_data.map do |email_data| Email.create email_data end
|
339
472
|
|
340
473
|
tried = Email.create :mail => 'body3', :to => 'recip@h3.example.com',
|
341
474
|
:from => nobody
|
342
475
|
|
343
476
|
tried.last_send_attempt = Time.now.to_i - 258
|
344
477
|
|
345
|
-
found_emails =
|
478
|
+
found_emails = []
|
346
479
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
480
|
+
out, err = util_capture do
|
481
|
+
found_emails = @sm.find_emails
|
482
|
+
end
|
483
|
+
|
484
|
+
assert_equal emails, found_emails
|
352
485
|
|
353
|
-
assert_equal
|
486
|
+
assert_equal '', out.string
|
487
|
+
assert_equal "found 3 emails to send\n", err.string
|
354
488
|
end
|
355
489
|
|
356
490
|
def test_server_settings
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.99
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ar_mailer
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2006-08-
|
6
|
+
version: 1.1.0
|
7
|
+
date: 2006-08-18 00:00:00 -07:00
|
8
8
|
summary: A two-phase deliver agent for ActionMailer
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -36,6 +36,7 @@ files:
|
|
36
36
|
- bin/ar_sendmail
|
37
37
|
- lib/action_mailer/ar_mailer.rb
|
38
38
|
- lib/action_mailer/ar_sendmail.rb
|
39
|
+
- share/ar_sendmail
|
39
40
|
- test/action_mailer.rb
|
40
41
|
- test/test_armailer.rb
|
41
42
|
- test/test_arsendmail.rb
|