prioritized_ar_mailer_rails3 2.1.12

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,3 @@
1
+ test
2
+ pkg
3
+ .DS_Store
@@ -0,0 +1,163 @@
1
+ = 2.1.12
2
+
3
+ * Miscellaneous Updates
4
+ * Added feature to send mail with priority.
5
+
6
+ = 2.1.8
7
+
8
+ * Bugs fixed
9
+ * Fix BCC addresses being visible to all recipients (laserlemon)
10
+
11
+ = 2.1.7
12
+
13
+ * Miscellaneous Updates
14
+ * Added adzap-ar_mailer file to end the need for the config.gem :lib option
15
+
16
+ * Bugs fixed
17
+ * Fix from address being set as address header object.
18
+
19
+ = 2.1.6
20
+
21
+ * Miscellaneous Updates
22
+ * Use return-path as from address if set, as per default ActionMailer::Base SMTP delivery (Dustin Tinney)
23
+ * Always wait full delay between deliveries (cyu)
24
+
25
+ * Bugs fixed
26
+ * Non-zero return code returned in init.d script (hennk)
27
+ * Use updated Timeout error class (hennk)
28
+
29
+ = 2.1.5
30
+
31
+ * Bugs fixed
32
+ * Load ar_mailer after environment to fix issue with lazy loading of ActionMailer in Rails 2.3
33
+
34
+ = 2.1.4
35
+
36
+ * Bugs fixed
37
+ * Explicitly require ar_mailer in ar_sendmail because its not getting loaded by the Rails environment for some reason
38
+
39
+ = 2.1.3
40
+
41
+ * Tests now pass on gem install
42
+ * Removed deprecated ActionMailer::ARMailer class
43
+ * Bugs fixed
44
+ * Fixed issue with pre-loading ActionMailer. No use ActionMailer::Base.email_class directly rather than store in ARSendmail instance var so no need to pre-load ActionMailer.
45
+
46
+ = 2.1.2
47
+
48
+ * Bugs fixed
49
+ * Require ar_mailer in ar_sendmail since the change to remove TableName and use email_class
50
+
51
+ = 2.1.1
52
+
53
+ * Force gem rebuild
54
+
55
+ = 2.1.0
56
+
57
+ * Switched to using a Rails generator for migration and model files. The ar_sendmail options have been removed.
58
+
59
+ = 2.0.2
60
+
61
+ * Removed TableName option from ar_sendmail options as its redundant. The Rails environment gets loaded so the settings for email class also get loaded
62
+ * Bugs fixed
63
+ * Email class reloading issue in development mode causing AR email class defaults to be lost when cached
64
+
65
+ = 2.0.1
66
+
67
+ * Added option to use smtp setting of :tls => false to disable TLS auto start in Ruby 1.8.7+
68
+ * Removed some cruft which can be handled by ActiveSupport
69
+
70
+ = 2.0.0
71
+
72
+ * Removed need to use ARMailer subclass. Just set the delivery method and you are ready to go. Backwards compatible with a deprecation notice if you subclass old ARMailer class.
73
+ * Only include SMTP TLS patch if Ruby version < 1.8.7 as it has an alternative. Changes based on Calvin Yu's [cyu] fork.
74
+ * Renamed default migration name to the modern Rails default
75
+ * Only authenticate if emails waiting to be sent
76
+ * Added --version switch to ar_sendmail binary
77
+ * Created a lighthouse account for this project (adzap fork only). See README.
78
+
79
+ = 1.4.4
80
+
81
+ * Exit init.d script with message if no mailers defined.
82
+
83
+ = 1.4.3
84
+
85
+ * Bugs fixed
86
+ * Replaced mistaken call to log when removing pid file artifact for
87
+ non-running daemon
88
+
89
+ = 1.4.2
90
+
91
+ * New Features
92
+ * Added Ruby based linux init.d script for handling daemon startup using yaml
93
+ config file. See files share/linux/ar_sendmail and ar_sendmail.conf
94
+ * Bugs fixed
95
+ * Proper handling for relative and absolute paths for the pid file
96
+ * Removed hoe dependency since we need the explicit gemspec file for github and
97
+ not deploying to RubyForge its not as useful.
98
+ * Moved old BSD rc.d script to share/bsd folder
99
+ * Updated README with github gem install, docs and init script info
100
+
101
+ = 1.4.1
102
+
103
+ * Bugs fixed
104
+ * Daemon failed on startup fixed with expanding full path of pid file
105
+
106
+ = 1.4.0
107
+
108
+ * Forked gem and published on GitHub (gem sources -a http://gems.github.com)
109
+ * New Features
110
+ * Added pid file creation on daemonize with command line option to specify pid filename [Dylan Egan]
111
+
112
+ = 1.3.1
113
+
114
+ * Fix bug #12530, gmail causes SSL errors. Submitted by Kyle Maxwell
115
+ and Alex Ostleitner.
116
+ * Try ActionMailer::Base::server_settings then ::smtp_settings. Fixes
117
+ bug #12516. Submitted by Alex Ostleitner.
118
+
119
+ = 1.3.0
120
+
121
+ * New Features
122
+ * Added automatic mail queue cleanup.
123
+ * MAY CAUSE LOSS OF DATA. If you haven't run ar_sendmail within
124
+ the expiry time, set it to 0.
125
+ * Bugs fixed
126
+ * Authentication errors are now handled by retrying once.
127
+
128
+ = 1.2.0
129
+
130
+ * Bugs fixed
131
+ * Handle SMTPServerBusy by backing off @delay seconds then re-queueing
132
+ * Allow email delivery class to be set in ARMailer.
133
+ * ar_sendmail --mailq works with --table-name now.
134
+ * Miscellaneous Updates
135
+ * Added documentation to require 'action_mailer/ar_mailer' in
136
+ instructions.
137
+ * Moved to ZSS p4 repository
138
+ * Supports TLS now. Requested by Dave Thomas. smtp_tls.rb from Kyle
139
+ Maxwell & etc.
140
+
141
+ = 1.1.0
142
+
143
+ * Features
144
+ * Added --chdir to set rails directory
145
+ * Added --environment to set RAILS_ENV
146
+ * Exits cleanly on TERM or INT signals
147
+ * Added FreeBSD rc.d script
148
+ * Exceptions during SMTP sending are now logged
149
+ * No longer waits if sending email took too long
150
+ * Bugs fixed
151
+ * Fixed last send attempt in --mailq
152
+ * Better SMTP error handling
153
+ * Messages are removed from the queue on 5xx errors
154
+ * Added Net::SMTP.reset to avoid needing to recreate the connection
155
+
156
+ = 1.0.1
157
+
158
+ * Bugs fixed
159
+ * From and to of email destination were swapped
160
+
161
+ = 1.0.0
162
+
163
+ * Birthday
@@ -0,0 +1,28 @@
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.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ 3. Neither the names of the authors nor the names of their contributors
15
+ may be used to endorse or promote products derived from this software
16
+ without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
19
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
22
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
23
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
24
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,123 @@
1
+ = ar_mailer_rails3
2
+
3
+ A two-phase delivery agent for ActionMailer which works for Rails 3 with feature for setting mail priority.
4
+
5
+ https://github.com/yzhang/ar_mailer_rails3
6
+
7
+ and for forked additions
8
+
9
+ https://github.com/gsoni-ror/ar_mailer_rails3/wikis
10
+
11
+
12
+ == About
13
+
14
+ Even delivering email to the local machine may take too long when you have to
15
+ send hundreds of messages. ar_mailer allows you to store messages into the
16
+ database for later delivery by a separate process, ar_sendmail. Now also allows to set priorities to the mails or skip mail from getting into the queue if required.
17
+
18
+ == Installing ar_mailer_rails3
19
+
20
+ Don't need remove adzap-ar_mailer or ar_mailer, just install ar_mailer_rails3
21
+
22
+ $ sudo gem install prioritized_ar_mailer_rails3
23
+
24
+ == Usage
25
+
26
+ Go to your Rails project:
27
+
28
+ $ cd your_rails_project
29
+
30
+ Create the migration, model and initializer:
31
+
32
+ This shows the options which are only the model name, which defaults to Email
33
+
34
+ ./script/generate ar_mailer_rails3 -h
35
+
36
+ Then run with defaults
37
+
38
+ ./script/generate ar_mailer email
39
+
40
+ Or specify a custom model name
41
+
42
+ ./script/generate ar_mailer newsletter
43
+
44
+ See Alternate Mail Storage if you use a custom model name
45
+
46
+ In your mailer class methods you must be sure to set the From address for your emails.
47
+ Something like:
48
+
49
+ def list_send(recipient)
50
+ from 'no_reply@example.com'
51
+ # ...
52
+
53
+ And if you want to set the mail priority, add request level variable @priority Something like:
54
+
55
+ def list_send(recipient)
56
+ @priority = 5
57
+ # ...
58
+
59
+ @priority could be any number, ar_mailer sort mails on priority and send it in the desc order.
60
+
61
+ Just in case you want to skip any mail from getting into the queue[for Urgent mails], you can assign @priority = -1 :)
62
+
63
+ Edit config/initializer/ar_mailer_rails3.rb and uncomment below line to use ar_mailer as
64
+ default delivery method:
65
+
66
+ ActionMailer::Base.delivery_method = :active_record
67
+
68
+ Or if you need to, you can set each mailer class delivery method individually:
69
+
70
+ class MyMailer < ActionMailer::Base
71
+ self.delivery_method = :active_record
72
+ end
73
+
74
+ This can be useful when using plugins like ExceptionNotification. Where it
75
+ might be foolish to tie the sending of the email alert to the database when the
76
+ database might be causing the exception being raised. In this instance you could
77
+ override ExceptionNofitier delivery method to be smtp or set the other
78
+ mailer classes to use ARMailer explicitly.
79
+
80
+ Then to run it:
81
+
82
+ $ ar_sendmail_rails3
83
+
84
+ You can also run it from cron with -o, or as a daemon with -d.
85
+
86
+ See <tt>ar_sendmail_rails3 -h</tt> for full details.
87
+
88
+ === Alternate Mail Storage
89
+
90
+ By default ar_mailer_rails3 assumes you are using an ActiveRecord model called
91
+ Email to store the emails created before sending. If you want to change
92
+ this you alter it in an intializer like so:
93
+
94
+ ActionMailer::Base.add_delivery_method :active_record, ArMailer::ActiveRecord, :email_class => Newsletter
95
+
96
+ === A Word on TLS
97
+
98
+ If you are using Ruby >= 1.8.7, TLS will be enabled automatically if your
99
+ SMTP server supports it. If you do not want it to automatically enabled then
100
+ set the :tls option to false in your smtp_settings.
101
+
102
+ If you are on Ruby <= 1.8.6, then the TLS patch included in this plugin will
103
+ be loaded, so you don't need another TLS plugin to add the capability. This
104
+ patch allows you to explicit set if the server supports TLS by setting the
105
+ :tls option to true in your smtp_settings.
106
+
107
+ === Help
108
+
109
+ See ar_sendmail_rails3 -h for options to ar_sendmail_rails3.
110
+
111
+ NOTE: You may need to delete an smtp_tls.rb file if you have one lying
112
+ around. ar_mailer supplies it own.
113
+
114
+ == Run as a service (init.d/rc.d scripts)
115
+
116
+ For Linux both script and demo config files are in share/linux.
117
+ See ar_sendmail.conf for setting up your config. Copy the ar_sendmail file
118
+ to /etc/init.d/ and make it executable. Then for Debian based distros run
119
+ 'sudo update-rc.d ar_sendmail defaults' and it should work. Make sure you have
120
+ the config file /etc/ar_sendmail.conf in place before starting.
121
+
122
+ For FreeBSD or NetBSD script is share/bsd/ar_sendmail. This is old and does not
123
+ support the config file unless someone wants to submit a patch.
@@ -0,0 +1,18 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |s|
7
+ s.name = "prioritized_ar_mailer_rails3"
8
+ s.summary = "ArMailer wrapper for Rails 3 with mail priority"
9
+ s.email = "raveformails@gmail.com"
10
+ s.homepage = "https://github.com/gsoni-ror/ar_mailer_rails3"
11
+ s.description = "ArMailer wrapper for Rails 3 with mail priority"
12
+ s.authors = ["Gaurav Soni"]
13
+ s.files = FileList["[A-Z]*", "bin/*", "share/*", "test/*", "{lib}/**/*", '.gitignore']
14
+ s.test_files = []
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
18
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 2.1.12
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ar_mailer_rails3/ar_sendmail'
4
+
5
+ ArMailerRails3::ARSendmail.run
6
+
@@ -0,0 +1 @@
1
+ require 'ar_mailer_rails3/active_record'
@@ -0,0 +1,59 @@
1
+ module ArMailerRails3
2
+ # A delivery method implementation which sends via sendmail.
3
+ #
4
+ # To use this, first find out where the sendmail binary is on your computer,
5
+ # if you are on a mac or unix box, it is usually in /usr/sbin/sendmail, this will
6
+ # be your sendmail location.
7
+ #
8
+ # Mail.defaults do
9
+ # delivery_method :sendmail
10
+ # end
11
+ #
12
+ # Or if your sendmail binary is not at '/usr/sbin/sendmail'
13
+ #
14
+ # Mail.defaults do
15
+ # delivery_method :sendmail, :location => '/absolute/path/to/your/sendmail'
16
+ # end
17
+ #
18
+ # Then just deliver the email as normal:
19
+ #
20
+ # Mail.deliver do
21
+ # to 'mikel@test.lindsaar.net'
22
+ # from 'ada@test.lindsaar.net'
23
+ # subject 'testing sendmail'
24
+ # body 'testing sendmail'
25
+ # end
26
+ #
27
+ # Or by calling deliver on a Mail message
28
+ #
29
+ # mail = Mail.new do
30
+ # to 'mikel@test.lindsaar.net'
31
+ # from 'ada@test.lindsaar.net'
32
+ # subject 'testing sendmail'
33
+ # body 'testing sendmail'
34
+ # end
35
+ #
36
+ # mail.deliver!
37
+ class ActiveRecord
38
+
39
+ def initialize(options)
40
+ self.email_class = options[:email_class] || Email
41
+ end
42
+
43
+ attr_accessor :email_class_name, :email_class
44
+
45
+ def deliver!(mail)
46
+ require "action_mailer/ar_sendmail"
47
+ destinations = mail.destinations
48
+ sender = mail.return_path || mail.sender || mail.from_addrs.first
49
+ destinations.each do |destination|
50
+ m = self.email_class.create :mail => mail.encoded, :to => destination, :from => sender, :priority => (@priority.present? ? @priority : 3)
51
+ if m.priority==-1
52
+ sendmail = ArMailerRails3::ARSendmail.new
53
+ sendmail.deliver([m])
54
+ m.destroy
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,489 @@
1
+ require 'optparse'
2
+ require 'net/smtp'
3
+ require 'smtp_tls' unless Net::SMTP.instance_methods.include?("enable_starttls_auto")
4
+
5
+ ##
6
+ # Hack in RSET
7
+
8
+ module Net # :nodoc:
9
+ class SMTP # :nodoc:
10
+
11
+ unless instance_methods.include? 'reset' then
12
+ ##
13
+ # Resets the SMTP connection.
14
+
15
+ def reset
16
+ getok 'RSET'
17
+ end
18
+ end
19
+
20
+ end
21
+ end
22
+
23
+ ##
24
+ # ActionMailer::ARSendmail delivers email from the email table to the
25
+ # SMTP server configured in your application's config/environment.rb.
26
+ # ar_sendmail does not work with sendmail delivery.
27
+ #
28
+ # ar_mailer can deliver to SMTP with TLS using smtp_tls.rb borrowed from Kyle
29
+ # Maxwell's action_mailer_optional_tls plugin. Simply set the :tls option in
30
+ # ActionMailer::Base's smtp_settings to true to enable TLS.
31
+ #
32
+ # See ar_sendmail -h for the full list of supported options.
33
+ #
34
+ # The interesting options are:
35
+ # * --daemon
36
+ # * --mailq
37
+
38
+ module ArMailerRails3; end
39
+
40
+ class ArMailerRails3::ARSendmail
41
+
42
+ ##
43
+ # The version of ActionMailer::ARSendmail you are running.
44
+
45
+ VERSION = '2.1.12'
46
+
47
+ ##
48
+ # Maximum number of times authentication will be consecutively retried
49
+
50
+ MAX_AUTH_FAILURES = 2
51
+
52
+ ##
53
+ # Email delivery attempts per run
54
+
55
+ attr_accessor :batch_size
56
+
57
+ ##
58
+ # Seconds to delay between runs
59
+
60
+ attr_accessor :delay
61
+
62
+ ##
63
+ # Maximum age of emails in seconds before they are removed from the queue.
64
+
65
+ attr_accessor :max_age
66
+
67
+ ##
68
+ # Be verbose
69
+
70
+ attr_accessor :verbose
71
+
72
+
73
+ ##
74
+ # True if only one delivery attempt will be made per call to run
75
+
76
+ attr_reader :once
77
+
78
+ ##
79
+ # Times authentication has failed
80
+
81
+ attr_accessor :failed_auth_count
82
+
83
+ @@pid_file = nil
84
+
85
+ def self.remove_pid_file
86
+ if @@pid_file
87
+ require 'shell'
88
+ sh = Shell.new
89
+ sh.rm @@pid_file
90
+ end
91
+ end
92
+
93
+ ##
94
+ # Get email class
95
+
96
+ def self.email_class
97
+ ActionMailer::Base.active_record_settings[:email_class]
98
+ end
99
+
100
+ ##
101
+ # Prints a list of unsent emails and the last delivery attempt, if any.
102
+ #
103
+ # If ActiveRecord::Timestamp is not being used the arrival time will not be
104
+ # known. See http://api.rubyonrails.org/classes/ActiveRecord/Timestamp.html
105
+ # to learn how to enable ActiveRecord::Timestamp.
106
+
107
+ def self.mailq
108
+ emails = self.email_class.find :all, :order=>"priority desc"
109
+
110
+ if emails.empty? then
111
+ puts "Mail queue is empty"
112
+ return
113
+ end
114
+
115
+ total_size = 0
116
+
117
+ puts "-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------"
118
+ emails.each do |email|
119
+ size = email.mail.length
120
+ total_size += size
121
+
122
+ create_timestamp = email.created_on rescue
123
+ email.created_at rescue
124
+ Time.at(email.created_date) rescue # for Robot Co-op
125
+ nil
126
+
127
+ created = if create_timestamp.nil? then
128
+ ' Unknown'
129
+ else
130
+ create_timestamp.strftime '%a %b %d %H:%M:%S'
131
+ end
132
+
133
+ puts "%10d %8d %s %s" % [email.id, size, created, email.from]
134
+ if email.last_send_attempt > 0 then
135
+ puts "Last send attempt: #{Time.at email.last_send_attempt}"
136
+ end
137
+ puts " #{email.to}"
138
+ puts
139
+ end
140
+
141
+ puts "-- #{total_size/1024} Kbytes in #{emails.length} Requests."
142
+ end
143
+
144
+ ##
145
+ # Processes command line options in +args+
146
+
147
+ def self.process_args(args)
148
+ name = File.basename $0
149
+
150
+ options = {}
151
+ options[:Chdir] = '.'
152
+ options[:Daemon] = false
153
+ options[:Delay] = 60
154
+ options[:MaxAge] = 86400 * 7
155
+ options[:Once] = false
156
+ options[:RailsEnv] = ENV['RAILS_ENV']
157
+ options[:Pidfile] = options[:Chdir] + '/log/ar_sendmail.pid'
158
+
159
+ opts = OptionParser.new do |opts|
160
+ opts.banner = "Usage: #{name} [options]"
161
+ opts.separator ''
162
+
163
+ opts.separator "#{name} scans the email table for new messages and sends them to the"
164
+ opts.separator "website's configured SMTP host."
165
+ opts.separator ''
166
+ opts.separator "#{name} must be run from a Rails application's root."
167
+
168
+ opts.separator ''
169
+ opts.separator 'Sendmail options:'
170
+
171
+ opts.on("-b", "--batch-size BATCH_SIZE",
172
+ "Maximum number of emails to send per delay",
173
+ "Default: Deliver all available emails", Integer) do |batch_size|
174
+ options[:BatchSize] = batch_size
175
+ end
176
+
177
+ opts.on( "--delay DELAY",
178
+ "Delay between checks for new mail",
179
+ "in the database",
180
+ "Default: #{options[:Delay]}", Integer) do |delay|
181
+ options[:Delay] = delay
182
+ end
183
+
184
+ opts.on( "--max-age MAX_AGE",
185
+ "Maxmimum age for an email. After this",
186
+ "it will be removed from the queue.",
187
+ "Set to 0 to disable queue cleanup.",
188
+ "Default: #{options[:MaxAge]} seconds", Integer) do |max_age|
189
+ options[:MaxAge] = max_age
190
+ end
191
+
192
+ opts.on("-o", "--once",
193
+ "Only check for new mail and deliver once",
194
+ "Default: #{options[:Once]}") do |once|
195
+ options[:Once] = once
196
+ end
197
+
198
+ opts.on("-d", "--daemonize",
199
+ "Run as a daemon process",
200
+ "Default: #{options[:Daemon]}") do |daemon|
201
+ options[:Daemon] = true
202
+ end
203
+
204
+ opts.on("-p", "--pidfile PIDFILE",
205
+ "Set the pidfile location",
206
+ "Default: #{options[:Chdir]}#{options[:Pidfile]}", String) do |pidfile|
207
+ options[:Pidfile] = pidfile
208
+ end
209
+
210
+ opts.on( "--mailq",
211
+ "Display a list of emails waiting to be sent") do |mailq|
212
+ options[:MailQ] = true
213
+ end
214
+
215
+ opts.separator ''
216
+ opts.separator 'Setup Options:'
217
+
218
+ opts.separator ''
219
+ opts.separator 'Generic Options:'
220
+
221
+ opts.on("-c", "--chdir PATH",
222
+ "Use PATH for the application path",
223
+ "Default: #{options[:Chdir]}") do |path|
224
+ usage opts, "#{path} is not a directory" unless File.directory? path
225
+ usage opts, "#{path} is not readable" unless File.readable? path
226
+ options[:Chdir] = path
227
+ end
228
+
229
+ opts.on("-e", "--environment RAILS_ENV",
230
+ "Set the RAILS_ENV constant",
231
+ "Default: #{options[:RailsEnv]}") do |env|
232
+ options[:RailsEnv] = env
233
+ end
234
+
235
+ opts.on("-v", "--[no-]verbose",
236
+ "Be verbose",
237
+ "Default: #{options[:Verbose]}") do |verbose|
238
+ options[:Verbose] = verbose
239
+ end
240
+
241
+ opts.on("-h", "--help",
242
+ "You're looking at it") do
243
+ usage opts
244
+ end
245
+
246
+ opts.on("--version", "Version of ARMailer") do
247
+ usage "ar_mailer #{VERSION} (adzap fork)"
248
+ end
249
+
250
+ opts.separator ''
251
+ end
252
+
253
+ opts.parse! args
254
+
255
+ ENV['RAILS_ENV'] = options[:RailsEnv]
256
+
257
+ Dir.chdir options[:Chdir] do
258
+ begin
259
+ require Dir.pwd + '/config/environment'
260
+ require 'ar_mailer_rails3/active_record'
261
+ rescue LoadError
262
+ usage opts, <<-EOF
263
+ #{name} must be run from a Rails application's root to deliver email.
264
+ #{Dir.pwd} does not appear to be a Rails application root.
265
+ EOF
266
+ end
267
+ end
268
+
269
+ return options
270
+ end
271
+
272
+ ##
273
+ # Processes +args+ and runs as appropriate
274
+
275
+ def self.run(args = ARGV)
276
+ options = process_args args
277
+
278
+ if options.include? :MailQ then
279
+ mailq
280
+ exit
281
+ end
282
+
283
+ if options[:Daemon] then
284
+ require 'webrick/server'
285
+ @@pid_file = File.expand_path(options[:Pidfile], options[:Chdir])
286
+ if File.exists? @@pid_file
287
+ # check to see if process is actually running
288
+ pid = ''
289
+ File.open(@@pid_file, 'r') {|f| pid = f.read.chomp }
290
+ if system("ps -p #{pid} | grep #{pid}") # returns true if process is running, o.w. false
291
+ $stderr.puts "Warning: The pid file #{@@pid_file} exists and ar_sendmail is running. Shutting down."
292
+ exit -1
293
+ else
294
+ # not running, so remove existing pid file and continue
295
+ self.remove_pid_file
296
+ $stderr.puts "ar_sendmail is not running. Removing existing pid file and starting up..."
297
+ end
298
+ end
299
+ WEBrick::Daemon.start
300
+ File.open(@@pid_file, 'w') {|f| f.write("#{Process.pid}\n")}
301
+ end
302
+
303
+ new(options).run
304
+
305
+ rescue SystemExit
306
+ raise
307
+ rescue SignalException
308
+ exit
309
+ rescue Exception => e
310
+ $stderr.puts "Unhandled exception #{e.message}(#{e.class}):"
311
+ $stderr.puts "\t#{e.backtrace.join "\n\t"}"
312
+ exit -2
313
+ end
314
+
315
+ ##
316
+ # Prints a usage message to $stderr using +opts+ and exits
317
+
318
+ def self.usage(opts, message = nil)
319
+ if message then
320
+ $stderr.puts message
321
+ $stderr.puts
322
+ end
323
+
324
+ $stderr.puts opts
325
+ exit 1
326
+ end
327
+
328
+ ##
329
+ # Creates a new ARSendmail.
330
+ #
331
+ # Valid options are:
332
+ # <tt>:BatchSize</tt>:: Maximum number of emails to send per delay
333
+ # <tt>:Delay</tt>:: Delay between deliver attempts
334
+ # <tt>:Once</tt>:: Only attempt to deliver emails once when run is called
335
+ # <tt>:Verbose</tt>:: Be verbose.
336
+
337
+ def initialize(options = {})
338
+ options[:Delay] ||= 60
339
+ options[:MaxAge] ||= 86400 * 7
340
+
341
+ @batch_size = options[:BatchSize]
342
+ @delay = options[:Delay]
343
+ @once = options[:Once]
344
+ @verbose = options[:Verbose]
345
+ @max_age = options[:MaxAge]
346
+
347
+ @failed_auth_count = 0
348
+ end
349
+
350
+ ##
351
+ # Removes emails that have lived in the queue for too long. If max_age is
352
+ # set to 0, no emails will be removed.
353
+
354
+ def cleanup
355
+ return if @max_age == 0
356
+ timeout = Time.now - @max_age
357
+ conditions = ['last_send_attempt > 0 and created_on < ?', timeout]
358
+ mail = self.class.email_class.destroy_all conditions
359
+
360
+ log "expired #{mail.length} emails from the queue"
361
+ end
362
+
363
+ ##
364
+ # Delivers +emails+ to ActionMailer's SMTP server and destroys them.
365
+
366
+ def deliver(emails)
367
+ settings = [
368
+ smtp_settings[:domain],
369
+ (smtp_settings[:user] || smtp_settings[:user_name]),
370
+ smtp_settings[:password],
371
+ smtp_settings[:authentication]
372
+ ]
373
+
374
+ smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
375
+ if smtp.respond_to?(:enable_starttls_auto)
376
+ smtp.enable_starttls_auto unless smtp_settings[:tls] == false
377
+ else
378
+ settings << smtp_settings[:tls]
379
+ end
380
+
381
+ smtp.start(*settings) do |session|
382
+ @failed_auth_count = 0
383
+ until emails.empty? do
384
+ email = emails.shift
385
+ begin
386
+ res = session.send_message email.mail, email.from, email.to
387
+ email.destroy
388
+ log "sent email %011d from %s to %s: %p" %
389
+ [email.id, email.from, email.to, res]
390
+ rescue Net::SMTPFatalError => e
391
+ log "5xx error sending email %d, removing from queue: %p(%s):\n\t%s" %
392
+ [email.id, e.message, e.class, e.backtrace.join("\n\t")]
393
+ email.destroy
394
+ session.reset
395
+ rescue Net::SMTPServerBusy => e
396
+ log "server too busy, stopping delivery cycle"
397
+ return
398
+ rescue Net::SMTPUnknownError, Net::SMTPSyntaxError, TimeoutError, Timeout::Error => e
399
+ email.last_send_attempt = Time.now.to_i
400
+ email.save rescue nil
401
+ log "error sending email %d: %p(%s):\n\t%s" %
402
+ [email.id, e.message, e.class, e.backtrace.join("\n\t")]
403
+ session.reset
404
+ end
405
+ end
406
+ end
407
+ rescue Net::SMTPAuthenticationError => e
408
+ @failed_auth_count += 1
409
+ if @failed_auth_count >= MAX_AUTH_FAILURES then
410
+ log "authentication error, giving up: #{e.message}"
411
+ raise e
412
+ else
413
+ log "authentication error, retrying: #{e.message}"
414
+ end
415
+ sleep delay
416
+ rescue Net::SMTPServerBusy, SystemCallError, OpenSSL::SSL::SSLError
417
+ # ignore SMTPServerBusy/EPIPE/ECONNRESET from Net::SMTP.start's ensure
418
+ end
419
+
420
+ ##
421
+ # Prepares ar_sendmail for exiting
422
+
423
+ def do_exit
424
+ log "caught signal, shutting down"
425
+ self.class.remove_pid_file
426
+ exit 130
427
+ end
428
+
429
+ ##
430
+ # Returns emails in email_class that haven't had a delivery attempt in the
431
+ # last 300 seconds.
432
+
433
+ def find_emails
434
+ options = { :conditions => ['last_send_attempt < ?', Time.now.to_i - 300], :order=> "priority desc" }
435
+ options[:limit] = batch_size unless batch_size.nil?
436
+ mail = self.class.email_class.find :all, options
437
+
438
+ log "found #{mail.length} emails to send"
439
+ mail
440
+ end
441
+
442
+ ##
443
+ # Installs signal handlers to gracefully exit.
444
+
445
+ def install_signal_handlers
446
+ trap 'TERM' do do_exit end
447
+ trap 'INT' do do_exit end
448
+ end
449
+
450
+ ##
451
+ # Logs +message+ if verbose
452
+
453
+ def log(message)
454
+ $stderr.puts message if @verbose
455
+ ActionMailer::Base.logger.info "ar_sendmail: #{message}"
456
+ end
457
+
458
+ ##
459
+ # Scans for emails and delivers them every delay seconds. Only returns if
460
+ # once is true.
461
+
462
+ def run
463
+ install_signal_handlers
464
+
465
+ loop do
466
+ begin
467
+ cleanup
468
+ emails = find_emails
469
+ deliver(emails) unless emails.empty?
470
+ rescue
471
+ end
472
+ break if @once
473
+ sleep @delay
474
+ end
475
+ end
476
+
477
+ ##
478
+ # Proxy to ActionMailer::Base::smtp_settings. See
479
+ # http://api.rubyonrails.org/classes/ActionMailer/Base.html
480
+ # for instructions on how to configure ActionMailer's SMTP server.
481
+ #
482
+ # Falls back to ::server_settings if ::smtp_settings doesn't exist for
483
+ # backwards compatibility.
484
+
485
+ def smtp_settings
486
+ ActionMailer::Base.smtp_settings rescue ActionMailer::Base.server_settings
487
+ end
488
+
489
+ end
@@ -0,0 +1,31 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class ArMailerRails3Generator < Rails::Generators::NamedBase
5
+ include Rails::Generators::Migration
6
+
7
+ def create_ar_mailer_files
8
+ self.class.check_class_collision class_name
9
+ template('ar_mailer.rb', 'config/initializers/ar_mailer.rb')
10
+ template('model.rb', File.join('app/models', class_path, "#{file_name}.rb"))
11
+ migration_template 'migration.rb', "db/migrate/create_#{file_path.gsub(/\//, '_').pluralize}.rb"
12
+ end
13
+
14
+ def self.source_root
15
+ File.join(File.dirname(__FILE__), 'templates')
16
+ end
17
+
18
+ # Implement the required interface for Rails::Generators::Migration.
19
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
20
+ def self.next_migration_number(dirname)
21
+ if ActiveRecord::Base.timestamped_migrations
22
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
23
+ else
24
+ "%.3d" % (current_migration_number(dirname) + 1)
25
+ end
26
+ end
27
+
28
+ def self.banner
29
+ "Usage: #{$0} ar_mailer_rails3 EmailModelName (default: Email)"
30
+ end
31
+ end
@@ -0,0 +1,2 @@
1
+ ActionMailer::Base.add_delivery_method :active_record, ArMailerRails3::ActiveRecord, :email_class => <%= class_name %>
2
+ ActionMailer::Base.delivery_method = :active_record
@@ -0,0 +1,16 @@
1
+ class <%= migration_class_name.gsub(/::/, '') %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :<%= table_name %> do |t|
4
+ t.column :from, :string
5
+ t.column :to, :string
6
+ t.column :last_send_attempt, :integer, :default => 0
7
+ t.column :mail, :text
8
+ t.column :priority, :integer
9
+ t.column :created_on, :datetime
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :<%= table_name %>
15
+ end
16
+ end
@@ -0,0 +1,2 @@
1
+ class <%= class_name %> < ActiveRecord::Base
2
+ end
@@ -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?
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prioritized_ar_mailer_rails3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 2
8
+ - 1
9
+ - 12
10
+ version: 2.1.12
11
+ platform: ruby
12
+ authors:
13
+ - Gaurav Soni
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-21 00:00:00 +05:30
19
+ default_executable: ar_sendmail_rails3
20
+ dependencies: []
21
+
22
+ description: ArMailer wrapper for Rails 3 with mail priority
23
+ email: raveformails@gmail.com
24
+ executables:
25
+ - ar_sendmail_rails3
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - LICENSE.txt
30
+ - README.rdoc
31
+ files:
32
+ - .gitignore
33
+ - History.txt
34
+ - LICENSE.txt
35
+ - README.rdoc
36
+ - Rakefile
37
+ - VERSION
38
+ - bin/ar_sendmail_rails3
39
+ - lib/ar_mailer_rails3.rb
40
+ - lib/ar_mailer_rails3/active_record.rb
41
+ - lib/ar_mailer_rails3/ar_sendmail.rb
42
+ - lib/generators/ar_mailer_rails3/ar_mailer_rails3_generator.rb
43
+ - lib/generators/ar_mailer_rails3/templates/ar_mailer.rb
44
+ - lib/generators/ar_mailer_rails3/templates/migration.rb
45
+ - lib/generators/ar_mailer_rails3/templates/model.rb
46
+ - lib/smtp_tls.rb
47
+ has_rdoc: true
48
+ homepage: https://github.com/gsoni-ror/ar_mailer_rails3
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ requirements: []
75
+
76
+ rubyforge_project:
77
+ rubygems_version: 1.3.7
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: ArMailer wrapper for Rails 3 with mail priority
81
+ test_files: []
82
+