ar_mailer 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|