adamcooper-ar_mailer 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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?
@@ -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
+
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # ar_sendmail Startup script for ar_mailer by Adam Meehan
4
+ #
5
+ # chkconfig: - 85 15
6
+ # description: ar_sendmail manages sending emails for Rails apps.
7
+ #
8
+ require 'yaml'
9
+
10
+ # Config file app mailers
11
+ config_file = '/etc/ar_sendmail.conf'
12
+
13
+ begin
14
+ config = YAML::load(IO.read(config_file)) || {}
15
+ if config.empty? || (config.has_key?('defaults') && config.size == 1)
16
+ puts "No mailers defined. Exiting."
17
+ exit
18
+ end
19
+ rescue Errno::ENOENT
20
+ puts "Config file not found at '#{config_file}'!"
21
+ exit
22
+ end
23
+
24
+ default_options = {'pidfile' => './log/ar_sendmail.pid'}.merge(config.delete('defaults') || {})
25
+
26
+ command, app_name = *ARGV
27
+
28
+ def start(app, options)
29
+ switches = ""
30
+ options.each {|k, v| switches << " --#{k} #{v}"}
31
+ STDOUT.write "Starting mailer for #{app} in #{options['environment']} mode ... "
32
+ status = system("ar_sendmail -d #{switches}") ? "started" : "failed"
33
+ puts status
34
+ end
35
+
36
+ def stop(app, options)
37
+ pid_file = File.expand_path(options['pidfile'], options['chdir'])
38
+ if File.exist? pid_file
39
+ begin
40
+ pid = open(pid_file).read.to_i
41
+ STDOUT.write "Stopping mailer for #{app}... "
42
+ Process.kill('TERM', pid)
43
+ puts "stopped"
44
+ rescue Errno::ESRCH
45
+ puts "Mailer process does not exist. Is not running."
46
+ end
47
+ else
48
+ puts "Skipping mailer for #{app}, no pid file."
49
+ end
50
+ end
51
+
52
+ def restart(app, options)
53
+ puts "Restarting mailer for #{app} ..."
54
+ stop app, options
55
+ start app, options
56
+ end
57
+
58
+ def command_error(msg)
59
+ puts msg
60
+ exit
61
+ end
62
+
63
+ if ['start', 'stop', 'restart'].include?(command)
64
+ apps = config
65
+ if app_name
66
+ command_error "No such app defined in ar_sendmail config" unless config.include?(app_name)
67
+ app_options = config[app_name]
68
+ command_error "Must specify chdir for app in ar_sendmail config" if app_options['chdir'].nil?
69
+ apps = {app_name => app_options}
70
+ end
71
+
72
+ apps.each do |app, options|
73
+ options = default_options.merge(options)
74
+ send(command, app, options)
75
+ end
76
+ else
77
+ command_error "Usage: ar_sendmail {start|stop|restart} [optional app_name]"
78
+ end
@@ -0,0 +1,30 @@
1
+ # This is a configuration file for ar_sendmail daemon init.d script
2
+ #
3
+ # Define the settings for each app which has a mailer that you want start
4
+ # automatically on startup.
5
+ #
6
+ # You can define an optional defaults section which will apply to all
7
+ # applications unless the setting is specified under the applications specific
8
+ # config.
9
+ #
10
+ # Settings not specified in either the defaults or app config section will
11
+ # be implied by the gem binary defaults. The option names are the same as the
12
+ # long format binary option switches. Run 'ar_sendmail -h' to see option switches
13
+ # and default values.
14
+ #
15
+ # Copy this file to /etc/ar_sendmail.conf and it will be read by the init.d
16
+ # script.
17
+ #
18
+
19
+ ## Demo app config
20
+ #
21
+ #defaults:
22
+ # batch-size: 10
23
+ # max-age: 0
24
+ # delay: 60
25
+ #
26
+ #app_name:
27
+ # chdir: /var/www/apps/app_name
28
+ # environment: production
29
+ # pidfile: ./log/ar_sendmail.pid
30
+
@@ -0,0 +1,197 @@
1
+ require 'net/smtp'
2
+ require 'smtp_tls' unless Net::SMTP.instance_methods.include?("enable_starttls_auto")
3
+ require 'time'
4
+
5
+ class Net::SMTP
6
+
7
+ @reset_called = 0
8
+
9
+ @deliveries = []
10
+
11
+ @send_message_block = nil
12
+
13
+ @start_block = nil
14
+
15
+ class << self
16
+
17
+ attr_reader :deliveries
18
+ attr_reader :send_message_block
19
+ attr_accessor :reset_called
20
+
21
+ send :remove_method, :start
22
+
23
+ end
24
+
25
+ def self.on_send_message(&block)
26
+ @send_message_block = block
27
+ end
28
+
29
+ def self.on_start(&block)
30
+ if block_given?
31
+ @start_block = block
32
+ else
33
+ @start_block
34
+ end
35
+ end
36
+
37
+ def self.clear_on_start
38
+ @start_block = nil
39
+ end
40
+
41
+ def self.reset
42
+ deliveries.clear
43
+ on_start
44
+ on_send_message
45
+ @reset_called = 0
46
+ end
47
+
48
+ def start(*args)
49
+ self.class.on_start.call if self.class.on_start
50
+ yield self
51
+ end
52
+
53
+ alias test_old_reset reset if instance_methods.include? 'reset'
54
+
55
+ def reset
56
+ self.class.reset_called += 1
57
+ end
58
+
59
+ alias test_old_send_message send_message
60
+
61
+ def send_message(mail, to, from)
62
+ return self.class.send_message_block.call(mail, to, from) unless
63
+ self.class.send_message_block.nil?
64
+ self.class.deliveries << [mail, to, from]
65
+ return "queued"
66
+ end
67
+
68
+ end
69
+
70
+ ##
71
+ # Stub for ActionMailer::Base
72
+
73
+ module ActionMailer; end
74
+
75
+ class ActionMailer::Base
76
+
77
+ @server_settings = {}
78
+
79
+ class << self
80
+ attr_accessor :delivery_method
81
+ end
82
+
83
+ def self.logger
84
+ o = Object.new
85
+ def o.info(arg) end
86
+ return o
87
+ end
88
+
89
+ def self.method_missing(meth, *args)
90
+ meth.to_s =~ /deliver_(.*)/
91
+ super unless $1
92
+ new($1, *args).deliver!
93
+ end
94
+
95
+ def self.reset
96
+ server_settings.clear
97
+ end
98
+
99
+ def self.server_settings
100
+ @server_settings
101
+ end
102
+
103
+ def initialize(meth = nil)
104
+ send meth if meth
105
+ end
106
+
107
+ def deliver!
108
+ perform_delivery_activerecord @mail
109
+ end
110
+
111
+ end
112
+
113
+ ##
114
+ # Stub for an ActiveRecord model
115
+
116
+ class Email
117
+
118
+ START = Time.parse 'Thu Aug 10 2006 11:19:48'
119
+
120
+ attr_accessor :from, :to, :mail, :last_send_attempt, :created_on, :id
121
+
122
+ @records = []
123
+ @id = 0
124
+
125
+ class << self; attr_accessor :records, :id; end
126
+
127
+ def self.create(record)
128
+ record = new record[:from], record[:to], record[:mail],
129
+ record[:last_send_attempt]
130
+ records << record
131
+ return record
132
+ end
133
+
134
+ def self.destroy_all(conditions)
135
+ timeout = conditions.last
136
+ found = []
137
+
138
+ records.each do |record|
139
+ next if record.last_send_attempt == 0
140
+ next if record.created_on == 0
141
+ next unless record.created_on < timeout
142
+ record.destroy
143
+ found << record
144
+ end
145
+
146
+ found
147
+ end
148
+
149
+ def self.find(_, conditions = nil)
150
+ return records if conditions.nil?
151
+ now = Time.now.to_i - 300
152
+ return records.select do |r|
153
+ r.last_send_attempt < now
154
+ end
155
+ end
156
+
157
+ def self.reset
158
+ @id = 0
159
+ records.clear
160
+ end
161
+
162
+ def initialize(from, to, mail, last_send_attempt = nil)
163
+ @from = from
164
+ @to = to
165
+ @mail = mail
166
+ @id = self.class.id += 1
167
+ @created_on = START + @id
168
+ @last_send_attempt = last_send_attempt || 0
169
+ end
170
+
171
+ def destroy
172
+ self.class.records.delete self
173
+ self.freeze
174
+ end
175
+
176
+ def ==(other)
177
+ other.id == id
178
+ end
179
+
180
+ def save
181
+ end
182
+
183
+ end
184
+
185
+ Mail = Email
186
+
187
+ class String
188
+ def classify
189
+ self
190
+ end
191
+
192
+ def tableize
193
+ self.downcase
194
+ end
195
+
196
+ end
197
+
@@ -0,0 +1,51 @@
1
+ require 'test/unit'
2
+ require 'action_mailer'
3
+ require 'action_mailer/ar_mailer'
4
+
5
+ ##
6
+ # Pretend mailer
7
+
8
+ class Mailer < ActionMailer::Base
9
+ self.delivery_method = :activerecord
10
+
11
+ def mail
12
+ @mail = Object.new
13
+ def @mail.encoded() 'email' end
14
+ def @mail.from() ['nobody@example.com'] end
15
+ def @mail.destinations() %w[user1@example.com user2@example.com] end
16
+ end
17
+
18
+ end
19
+
20
+ class TestARMailer < Test::Unit::TestCase
21
+
22
+ def setup
23
+ Mailer.email_class = Email
24
+
25
+ Email.records.clear
26
+ Mail.records.clear
27
+ end
28
+
29
+ def test_self_email_class_equals
30
+ Mailer.email_class = Mail
31
+
32
+ Mailer.deliver_mail
33
+
34
+ assert_equal 2, Mail.records.length
35
+ end
36
+
37
+ def test_perform_delivery_activerecord
38
+ Mailer.deliver_mail
39
+
40
+ assert_equal 2, Email.records.length
41
+
42
+ record = Email.records.first
43
+ assert_equal 'email', record.mail
44
+ assert_equal 'user1@example.com', record.to
45
+ assert_equal 'nobody@example.com', record.from
46
+
47
+ assert_equal 'user2@example.com', Email.records.last.to
48
+ end
49
+
50
+ end
51
+