rq 3.3.0 → 3.4.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/a.rb +1 -0
- data/bin/rq +10 -0
- data/bin/rqmailer +45 -26
- data/lib/rq/cron.rb +16 -4
- data/lib/rq/jobqueue.rb +4 -1
- data/lib/rq/updater.rb +0 -1
- data/rails/data/config +1 -1
- data/rails/example.rb +5 -2
- metadata +9 -23
- data/q/bin/rqmailer +0 -16
- data/q/db +0 -0
- data/q/db.schema +0 -28
- data/q/lock +0 -0
- data/rails/q/bin/rqmailer +0 -847
- data/rails/q/db +0 -0
- data/rails/q/db.schema +0 -28
- data/rails/q/lock +0 -0
data/bin/rq
CHANGED
|
@@ -424,6 +424,8 @@
|
|
|
424
424
|
tail
|
|
425
425
|
when 'cron'
|
|
426
426
|
cron
|
|
427
|
+
when 'crontab'
|
|
428
|
+
crontab
|
|
427
429
|
else
|
|
428
430
|
raise "invalid mode <#{ @mode }>"
|
|
429
431
|
end
|
|
@@ -717,6 +719,14 @@
|
|
|
717
719
|
cron.cron
|
|
718
720
|
#--}}}
|
|
719
721
|
end
|
|
722
|
+
def crontab
|
|
723
|
+
#--{{{
|
|
724
|
+
argv.unshift 'tab'
|
|
725
|
+
init_logging
|
|
726
|
+
cron = Cron::new self
|
|
727
|
+
cron.cron
|
|
728
|
+
#--}}}
|
|
729
|
+
end
|
|
720
730
|
|
|
721
731
|
def dump_ios which, jids
|
|
722
732
|
#--{{{
|
data/bin/rqmailer
CHANGED
|
@@ -32,8 +32,6 @@ Main {
|
|
|
32
32
|
argument_required
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
SMTP = {}
|
|
36
|
-
|
|
37
35
|
def run #--{{{
|
|
38
36
|
indicating_that_rqmailer_failed do
|
|
39
37
|
setup
|
|
@@ -51,6 +49,10 @@ Main {
|
|
|
51
49
|
@config = {}
|
|
52
50
|
@rq = ENV['RQ']
|
|
53
51
|
@rq_data = ENV['RQ_DATA']
|
|
52
|
+
if(@rq.nil? and @rq_data.nil? and argv.first and test(?d, argv.first))
|
|
53
|
+
@rq_data = File.expand_path argv.shift
|
|
54
|
+
@rq = true
|
|
55
|
+
end
|
|
54
56
|
@exit_status = 0
|
|
55
57
|
@exception = nil
|
|
56
58
|
@template_expander = TemplateExpander.instance
|
|
@@ -163,38 +165,55 @@ Main {
|
|
|
163
165
|
def mail_message #--{{{
|
|
164
166
|
build_mail!
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
168
|
+
deliver = @config.has_key?('smtp') ? 'smtp' : 'sendmail'
|
|
169
|
+
|
|
170
|
+
if deliver == 'smtp'
|
|
171
|
+
hash = @config['smtp'] || {}
|
|
172
|
+
server = hash['server']
|
|
173
|
+
port = Integer hash['port']
|
|
174
|
+
hostname = hash['hostname'] || @hostname || 'localhost.localdomain'
|
|
175
|
+
account = hash['account']
|
|
176
|
+
password = hash['password']
|
|
177
|
+
authtype = hash['authtype'] || :plain
|
|
178
|
+
tls = hash['tls'] ? true : false
|
|
179
|
+
else
|
|
180
|
+
sendmail = @config['sendmail'] || '/usr/sbin/sendmail -i -t'
|
|
181
|
+
end
|
|
174
182
|
|
|
175
183
|
if @belch
|
|
176
184
|
if @send
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
185
|
+
case deliver
|
|
186
|
+
when 'smtp'
|
|
187
|
+
smtp = Net::SMTP.new server, port
|
|
188
|
+
smtp.set_debug_output STDERR
|
|
189
|
+
smtp.start hostname, account, password, authtype, tls do |connection|
|
|
190
|
+
connection.send_message @mail, account, @mail.recipients
|
|
191
|
+
end
|
|
192
|
+
when 'sendmail'
|
|
193
|
+
IO.popen(sendmail, 'w+') do |pipe|
|
|
194
|
+
pipe.write @mail.to_s.gsub(%r/\r/,'')
|
|
195
|
+
pipe.flush
|
|
196
|
+
end
|
|
181
197
|
end
|
|
182
198
|
end
|
|
183
199
|
STDOUT.puts @mail
|
|
184
200
|
else
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
201
|
+
case deliver
|
|
202
|
+
when 'smtp'
|
|
203
|
+
debug_output = open File.join(@rq_data, 'smtp'), 'w'
|
|
204
|
+
at_exit{ debug_output.close rescue nil }
|
|
205
|
+
smtp = Net::SMTP.new server, port
|
|
206
|
+
smtp.set_debug_output debug_output
|
|
207
|
+
smtp.start hostname, account, password, authtype, tls do |connection|
|
|
208
|
+
connection.send_message @mail, account, @mail.recipients
|
|
209
|
+
end
|
|
210
|
+
when 'sendmail'
|
|
211
|
+
IO.popen(sendmail, 'w+') do |pipe|
|
|
212
|
+
pipe.write @mail.to_s.gsub(%r/\r/,'')
|
|
213
|
+
pipe.flush
|
|
214
|
+
end
|
|
192
215
|
end
|
|
193
|
-
|
|
194
|
-
if @rq
|
|
195
|
-
open(File.join(@rq_data, 'mail'), 'w'){|fd| fd.write @mail}
|
|
196
|
-
end
|
|
197
|
-
|
|
216
|
+
open(File.join(@rq_data, 'mail'), 'w'){|fd| fd.write @mail} rescue nil
|
|
198
217
|
STDERR.puts @mail
|
|
199
218
|
end
|
|
200
219
|
|
data/lib/rq/cron.rb
CHANGED
|
@@ -74,19 +74,29 @@ unless defined? $__rq_cron__
|
|
|
74
74
|
puts entry
|
|
75
75
|
end
|
|
76
76
|
end
|
|
77
|
+
#--}}}
|
|
78
|
+
end
|
|
79
|
+
def cron_tab
|
|
80
|
+
#--{{{
|
|
81
|
+
opts = @options.map{|kv| "'--#{ kv.join('=') }'" }.join(' ')
|
|
82
|
+
entries = [
|
|
83
|
+
"*/15 * * * * #{ @cmd } start #{ opts } ###md5:#{ @md5[:start] }\n",
|
|
84
|
+
"0 0 * * * #{ @cmd } rotate ###md5:#{ @md5[:start] }\n",
|
|
85
|
+
]
|
|
86
|
+
puts entries
|
|
77
87
|
#--}}}
|
|
78
88
|
end
|
|
79
89
|
def cron_start
|
|
80
90
|
#--{{{
|
|
81
91
|
cron_add
|
|
82
|
-
main.start
|
|
92
|
+
#main.start
|
|
83
93
|
#--}}}
|
|
84
94
|
end
|
|
85
95
|
def cron_delete
|
|
86
96
|
#--{{{
|
|
87
97
|
lines = `crontab -l`.split "\n"
|
|
88
98
|
|
|
89
|
-
re = %r/###\s*md5
|
|
99
|
+
re = %r/###\s*md5:(#{ @md5[:start] })/
|
|
90
100
|
found = []
|
|
91
101
|
|
|
92
102
|
lines.each_with_index do |line, idx|
|
|
@@ -100,9 +110,11 @@ unless defined? $__rq_cron__
|
|
|
100
110
|
found << idx if(re.match entry)
|
|
101
111
|
end
|
|
102
112
|
|
|
113
|
+
p found
|
|
114
|
+
|
|
103
115
|
unless found.empty?
|
|
104
|
-
deleted =
|
|
105
|
-
lines.delete_at
|
|
116
|
+
deleted = []
|
|
117
|
+
found.each{|idx| deleted << lines[idx]; lines.delete_at(idx)}
|
|
106
118
|
tmp = Tempfile::new Process::pid.to_s
|
|
107
119
|
lines.each{|line| tmp << "#{ line }\n"}
|
|
108
120
|
tmp.close
|
data/lib/rq/jobqueue.rb
CHANGED
|
@@ -239,7 +239,10 @@ unless defined? $__rq_jobqueue__
|
|
|
239
239
|
end
|
|
240
240
|
def tmp_stdin stdin = nil
|
|
241
241
|
#--{{{
|
|
242
|
-
stdin = nil if stdin.to_s.empty?
|
|
242
|
+
#stdin = nil if stdin.to_s.empty?
|
|
243
|
+
if stdin.to_s.empty?
|
|
244
|
+
return(block_given? ? yield(nil) : nil)
|
|
245
|
+
end
|
|
243
246
|
stdin = STDIN if stdin == '-'
|
|
244
247
|
|
|
245
248
|
was_opened = false
|
data/lib/rq/updater.rb
CHANGED
data/rails/data/config
CHANGED
data/rails/example.rb
CHANGED
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
Subject: testing 1-2-3
|
|
26
26
|
Cc: ara.t.howard@gmail.com
|
|
27
27
|
attach: #{ this_file }
|
|
28
|
+
yml
|
|
28
29
|
|
|
30
|
+
### put this in theconfig if you want to use smtp
|
|
31
|
+
=begin
|
|
29
32
|
smtp:
|
|
30
33
|
account : ara.t.howard@eparklabs.com
|
|
31
34
|
tls : true
|
|
@@ -33,8 +36,8 @@
|
|
|
33
36
|
server : secure.eparklabs.com
|
|
34
37
|
domain : eparklabs.com
|
|
35
38
|
authtype : :plain
|
|
36
|
-
password :
|
|
37
|
-
|
|
39
|
+
password : :password
|
|
40
|
+
=end
|
|
38
41
|
|
|
39
42
|
config = YAML.load yml
|
|
40
43
|
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
|
-
rubygems_version: 0.9.
|
|
2
|
+
rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
|
4
4
|
name: rq
|
|
5
5
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: 3.
|
|
7
|
-
date: 2007-
|
|
6
|
+
version: 3.4.0
|
|
7
|
+
date: 2007-12-18 00:00:00 -07:00
|
|
8
8
|
summary: rq
|
|
9
9
|
require_paths:
|
|
10
10
|
- lib
|
|
@@ -29,6 +29,7 @@ post_install_message:
|
|
|
29
29
|
authors:
|
|
30
30
|
- Ara T. Howard
|
|
31
31
|
files:
|
|
32
|
+
- a.rb
|
|
32
33
|
- all
|
|
33
34
|
- all/install.rb
|
|
34
35
|
- all/install.sh
|
|
@@ -47,6 +48,7 @@ files:
|
|
|
47
48
|
- bin
|
|
48
49
|
- bin/rq
|
|
49
50
|
- bin/rqmailer
|
|
51
|
+
- build
|
|
50
52
|
- doc
|
|
51
53
|
- extconf.rb
|
|
52
54
|
- gemspec.rb
|
|
@@ -100,16 +102,6 @@ files:
|
|
|
100
102
|
- lib/rq/util.rb
|
|
101
103
|
- lib/rq.rb
|
|
102
104
|
- Makefile
|
|
103
|
-
- q
|
|
104
|
-
- q/bin
|
|
105
|
-
- q/bin/rqmailer
|
|
106
|
-
- q/data
|
|
107
|
-
- q/db
|
|
108
|
-
- q/db.schema
|
|
109
|
-
- q/lock
|
|
110
|
-
- q/stderr
|
|
111
|
-
- q/stdin
|
|
112
|
-
- q/stdout
|
|
113
105
|
- rails
|
|
114
106
|
- rails/app
|
|
115
107
|
- rails/app/controllers
|
|
@@ -162,16 +154,6 @@ files:
|
|
|
162
154
|
- rails/public/javascripts/prototype.js
|
|
163
155
|
- rails/public/robots.txt
|
|
164
156
|
- rails/public/stylesheets
|
|
165
|
-
- rails/q
|
|
166
|
-
- rails/q/bin
|
|
167
|
-
- rails/q/bin/rqmailer
|
|
168
|
-
- rails/q/data
|
|
169
|
-
- rails/q/db
|
|
170
|
-
- rails/q/db.schema
|
|
171
|
-
- rails/q/lock
|
|
172
|
-
- rails/q/stderr
|
|
173
|
-
- rails/q/stdin
|
|
174
|
-
- rails/q/stdout
|
|
175
157
|
- rails/q.20070629122840.tgz
|
|
176
158
|
- rails/Rakefile
|
|
177
159
|
- rails/README
|
|
@@ -201,8 +183,11 @@ files:
|
|
|
201
183
|
- rails/test/test_helper.rb
|
|
202
184
|
- rails/test/unit
|
|
203
185
|
- rails/tmp
|
|
186
|
+
- rails/tmp/12344
|
|
187
|
+
- rails/tmp/12532
|
|
204
188
|
- rails/tmp/12565
|
|
205
189
|
- rails/tmp/12589
|
|
190
|
+
- rails/tmp/15392
|
|
206
191
|
- rails/tmp/16694
|
|
207
192
|
- rails/tmp/2311
|
|
208
193
|
- rails/tmp/2312
|
|
@@ -241,6 +226,7 @@ files:
|
|
|
241
226
|
- rails/tmp/4063
|
|
242
227
|
- rails/tmp/4086
|
|
243
228
|
- rails/tmp/4102
|
|
229
|
+
- rails/tmp/5245
|
|
244
230
|
- rails/tmp/8272
|
|
245
231
|
- rails/tmp/8321
|
|
246
232
|
- rails/tmp/8362
|
data/q/bin/rqmailer
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/Applications/Locomotive2/Bundles/standardRailsMar2007.locobundle/i386/bin/ruby
|
|
2
|
-
#
|
|
3
|
-
# This file was generated by RubyGems.
|
|
4
|
-
#
|
|
5
|
-
# The application 'rq' is installed as part of a gem, and
|
|
6
|
-
# this file is here to facilitate running it.
|
|
7
|
-
#
|
|
8
|
-
|
|
9
|
-
require 'rubygems'
|
|
10
|
-
version = "> 0"
|
|
11
|
-
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
|
12
|
-
version = $1
|
|
13
|
-
ARGV.shift
|
|
14
|
-
end
|
|
15
|
-
gem 'rq', version
|
|
16
|
-
load 'rqmailer'
|
data/q/db
DELETED
|
Binary file
|
data/q/db.schema
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
PRAGMA default_synchronous = FULL;
|
|
2
|
-
create table jobs
|
|
3
|
-
(
|
|
4
|
-
jid integer primary key,
|
|
5
|
-
priority,
|
|
6
|
-
state,
|
|
7
|
-
submitted,
|
|
8
|
-
started,
|
|
9
|
-
finished,
|
|
10
|
-
elapsed,
|
|
11
|
-
submitter,
|
|
12
|
-
runner,
|
|
13
|
-
stdin,
|
|
14
|
-
stdout,
|
|
15
|
-
stderr,
|
|
16
|
-
data,
|
|
17
|
-
pid,
|
|
18
|
-
exit_status,
|
|
19
|
-
tag,
|
|
20
|
-
restartable,
|
|
21
|
-
command
|
|
22
|
-
);
|
|
23
|
-
create table attributes
|
|
24
|
-
(
|
|
25
|
-
key,
|
|
26
|
-
value,
|
|
27
|
-
primary key (key)
|
|
28
|
-
);
|
data/q/lock
DELETED
|
File without changes
|
data/rails/q/bin/rqmailer
DELETED
|
@@ -1,847 +0,0 @@
|
|
|
1
|
-
#!/opt/local/bin/ruby
|
|
2
|
-
#! /opt/local/bin/ruby
|
|
3
|
-
|
|
4
|
-
### built-in
|
|
5
|
-
require 'openssl'
|
|
6
|
-
require 'net/smtp'
|
|
7
|
-
require 'io/wait'
|
|
8
|
-
require 'erb'
|
|
9
|
-
require 'socket'
|
|
10
|
-
|
|
11
|
-
### rubyforge
|
|
12
|
-
require 'rubygems'
|
|
13
|
-
require 'main'
|
|
14
|
-
require 'open4'
|
|
15
|
-
#require 'mailfactory' # patched version inlined below
|
|
16
|
-
|
|
17
|
-
Main {
|
|
18
|
-
option('config', 'c'){
|
|
19
|
-
argument_required
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
option('template', 't'){
|
|
23
|
-
argument_required
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
option('belch', 'b'){
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
option('send', 's'){
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
option('queue', 'q'){
|
|
33
|
-
argument_required
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
SMTP = {}
|
|
37
|
-
|
|
38
|
-
def run #--{{{
|
|
39
|
-
indicating_that_rqmailer_failed do
|
|
40
|
-
setup
|
|
41
|
-
load_config
|
|
42
|
-
load_template
|
|
43
|
-
generate_cmd
|
|
44
|
-
run_cmd
|
|
45
|
-
expand_template
|
|
46
|
-
mail_message
|
|
47
|
-
end
|
|
48
|
-
exit @exit_status || 42
|
|
49
|
-
end #--}}}
|
|
50
|
-
|
|
51
|
-
def setup #--{{{
|
|
52
|
-
@config = {}
|
|
53
|
-
@rq = ENV['RQ']
|
|
54
|
-
@rq_data = ENV['RQ_DATA']
|
|
55
|
-
@exit_status = 0
|
|
56
|
-
@exception = nil
|
|
57
|
-
@template_expander = TemplateExpander.instance
|
|
58
|
-
@stdin = @stdout = @stderr = nil
|
|
59
|
-
@belch = params['belch'].given?
|
|
60
|
-
@send = params['send'].given?
|
|
61
|
-
@hostname = Socket.gethostname rescue 'localhost.localdomain'
|
|
62
|
-
@mail = MailFactory.new
|
|
63
|
-
end #--}}}
|
|
64
|
-
|
|
65
|
-
def load_config #--{{{
|
|
66
|
-
if param['config'].given?
|
|
67
|
-
@config = YAML.load IO.read(param['config'].value)
|
|
68
|
-
else
|
|
69
|
-
if @rq_data
|
|
70
|
-
config = File.join @rq_data, 'config'
|
|
71
|
-
@config = YAML.load IO.read(config)
|
|
72
|
-
else
|
|
73
|
-
abort 'no config'
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end #--}}}
|
|
77
|
-
|
|
78
|
-
def load_template #--{{{
|
|
79
|
-
if param['template'].given?
|
|
80
|
-
@template = IO.read param['template'].value
|
|
81
|
-
else
|
|
82
|
-
if @rq_data
|
|
83
|
-
template = File.join @rq_data, 'template'
|
|
84
|
-
@template = IO.read(template)
|
|
85
|
-
else
|
|
86
|
-
@template = DATA.read
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end #--}}}
|
|
90
|
-
|
|
91
|
-
def generate_cmd #--{{{
|
|
92
|
-
stdin = argv.first == '-' && argv.delete('-')
|
|
93
|
-
@cmd =
|
|
94
|
-
if stdin
|
|
95
|
-
STDIN.read
|
|
96
|
-
else
|
|
97
|
-
@config['command'] || @config['cmd'] || argv.join(' ')
|
|
98
|
-
end
|
|
99
|
-
abort 'no cmd' if @cmd.to_s.strip.empty?
|
|
100
|
-
end #--}}}
|
|
101
|
-
|
|
102
|
-
def run_cmd #--{{{
|
|
103
|
-
if @rq
|
|
104
|
-
@stdin = STDIN if STDIN.ready?
|
|
105
|
-
@stdout = STDOUT
|
|
106
|
-
@stderr = STDERR
|
|
107
|
-
STDOUT.flush; STDERR.flush
|
|
108
|
-
@exit_status = Open4.spawn @cmd, 0=>@stdin, 1=>@stdout, 2=>@stderr
|
|
109
|
-
STDOUT.flush; STDERR.flush
|
|
110
|
-
else
|
|
111
|
-
@stdin = STDIN if STDIN.ready?
|
|
112
|
-
@stdin = IO.read(@stdin) if @stdin
|
|
113
|
-
@stdout = ''
|
|
114
|
-
@stderr = ''
|
|
115
|
-
@exit_status = Open4.spawn @cmd, 0=>@stdin, 1=>@stdout, 2=>@stderr
|
|
116
|
-
end
|
|
117
|
-
update_config_with_cmd_info
|
|
118
|
-
end #--}}}
|
|
119
|
-
|
|
120
|
-
def errmsg e #--{{{
|
|
121
|
-
m, c, bt = e.message, e.class, (e.backtrace || []).join("\n")
|
|
122
|
-
"#{ m } (#{ c })\n#{ bt }"
|
|
123
|
-
end #--}}}
|
|
124
|
-
|
|
125
|
-
def indicating_that_rqmailer_failed #--{{{
|
|
126
|
-
begin
|
|
127
|
-
yield
|
|
128
|
-
rescue Exception => e
|
|
129
|
-
@exception = e
|
|
130
|
-
STDERR.puts errmsg(e)
|
|
131
|
-
@exit_status = 42
|
|
132
|
-
end
|
|
133
|
-
end #--}}}
|
|
134
|
-
|
|
135
|
-
def update_config_with_cmd_info #--{{{
|
|
136
|
-
if @rq
|
|
137
|
-
%w( stdin stdout stderr ).each do |iof|
|
|
138
|
-
path = instance_variable_get "@rq_#{ iof }"
|
|
139
|
-
buf = IO.read path rescue ''
|
|
140
|
-
@config[iof] = buf
|
|
141
|
-
@config["#{ iof }_path"] = path
|
|
142
|
-
end
|
|
143
|
-
else
|
|
144
|
-
@config['stdin'] = @stdin
|
|
145
|
-
@config['stdin_path'] = '-'
|
|
146
|
-
@config['stdout'] = @stdout
|
|
147
|
-
@config['stdout_path'] = '-'
|
|
148
|
-
@config['stderr'] = @stderr
|
|
149
|
-
@config['stderr_path'] = '-'
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
@config['cmd'] = @config['command'] = @cmd
|
|
153
|
-
@config['exit_status'] = @config['exitstatus'] = @exit_status
|
|
154
|
-
end #--}}}
|
|
155
|
-
|
|
156
|
-
def expand_template #--{{{
|
|
157
|
-
@template_expander.configure @config
|
|
158
|
-
@template_expander.configure 'mail' => @mail
|
|
159
|
-
mconfig = @config['mail'] || {}
|
|
160
|
-
@template_expander.configure mconfig
|
|
161
|
-
@message = @template_expander.expand @template
|
|
162
|
-
end #--}}}
|
|
163
|
-
|
|
164
|
-
def mail_message #--{{{
|
|
165
|
-
build_mail!
|
|
166
|
-
|
|
167
|
-
hash = @config['smtp'] || SMTP
|
|
168
|
-
server = hash['server']
|
|
169
|
-
port = Integer hash['port']
|
|
170
|
-
hostname = hash['hostname'] || @hostname || 'localhost.localdomain'
|
|
171
|
-
account = hash['account']
|
|
172
|
-
password = hash['password']
|
|
173
|
-
authtype = hash['authtype'] || :plain
|
|
174
|
-
tls = hash['tls'] ? true : false
|
|
175
|
-
|
|
176
|
-
if @belch
|
|
177
|
-
if @send
|
|
178
|
-
smtp = Net::SMTP.new server, port
|
|
179
|
-
smtp.set_debug_output STDERR
|
|
180
|
-
smtp.start hostname, account, password, authtype, tls do |connection|
|
|
181
|
-
connection.send_message @mail, account, @mail.recipients
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
STDOUT.puts @mail
|
|
185
|
-
else
|
|
186
|
-
debug_output = open File.join(@rq_data, 'smtp'), 'w'
|
|
187
|
-
at_exit{ debug_output.close rescue nil }
|
|
188
|
-
|
|
189
|
-
smtp = Net::SMTP.new server, port
|
|
190
|
-
smtp.set_debug_output debug_output
|
|
191
|
-
smtp.start hostname, account, password, authtype, tls do |connection|
|
|
192
|
-
connection.send_message @mail, account, @mail.recipients
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
if @rq
|
|
196
|
-
open(File.join(@rq_data, 'mail'), 'w'){|fd| fd.write @mail}
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
STDERR.puts @mail
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
end #--}}}
|
|
203
|
-
|
|
204
|
-
def build_mail! #--{{{
|
|
205
|
-
mconfig = @config['mail'] || @config
|
|
206
|
-
|
|
207
|
-
attributes = %w(
|
|
208
|
-
to
|
|
209
|
-
from
|
|
210
|
-
cc
|
|
211
|
-
bcc
|
|
212
|
-
subject
|
|
213
|
-
)
|
|
214
|
-
attributes.each do |attribute|
|
|
215
|
-
up, down = attribute.downcase.capitalize, attribute.downcase
|
|
216
|
-
[up, down].each do |attribute|
|
|
217
|
-
if mconfig.has_key?(attribute)
|
|
218
|
-
value = [mconfig[attribute]].flatten.join ','
|
|
219
|
-
@mail.send "#{ up }=", value
|
|
220
|
-
@mail.send "#{ down }=", value
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
methods = %w(
|
|
226
|
-
attach
|
|
227
|
-
attachment
|
|
228
|
-
attachments
|
|
229
|
-
Attach
|
|
230
|
-
Attachment
|
|
231
|
-
Attachments
|
|
232
|
-
)
|
|
233
|
-
methods.each do |method|
|
|
234
|
-
if mconfig.has_key?(method)
|
|
235
|
-
values = [mconfig[method]].flatten
|
|
236
|
-
values.each do |value|
|
|
237
|
-
@mail.attach value
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
end
|
|
241
|
-
|
|
242
|
-
class << @mail
|
|
243
|
-
def recipients
|
|
244
|
-
to.to_s.split %r/,/
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
@mail.subject ||= "rqmailer"
|
|
249
|
-
@mail.text = @message
|
|
250
|
-
@mail
|
|
251
|
-
end #--}}}
|
|
252
|
-
|
|
253
|
-
class TemplateExpander #--{{{
|
|
254
|
-
alias_method "__instance_variable_set__", "instance_variable_set"
|
|
255
|
-
alias_method "__instance_eval__", "instance_eval"
|
|
256
|
-
instance_methods.each{|m| undef_method unless m[%r/__/]}
|
|
257
|
-
alias_method "instance_eval", "__instance_eval__"
|
|
258
|
-
alias_method "instance_variable_set", "__instance_variable_set__"
|
|
259
|
-
|
|
260
|
-
def self.new *a, &b
|
|
261
|
-
@instance ||= super
|
|
262
|
-
end
|
|
263
|
-
def self.instance *a, &b
|
|
264
|
-
new *a, &b
|
|
265
|
-
end
|
|
266
|
-
def self.const_missing c
|
|
267
|
-
msg = c.to_s.downcase
|
|
268
|
-
if @instance.respond_to? msg
|
|
269
|
-
@instance.send msg
|
|
270
|
-
else
|
|
271
|
-
super
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
def singleton_class &b #--{{{
|
|
275
|
-
@sc ||=
|
|
276
|
-
class << self
|
|
277
|
-
self
|
|
278
|
-
end
|
|
279
|
-
b ? @sc.module_eval(&b) : @sc
|
|
280
|
-
end #--}}}
|
|
281
|
-
def set key, value #--{{{
|
|
282
|
-
key = key.to_s.downcase
|
|
283
|
-
instance_variable_set "@#{ key }", value
|
|
284
|
-
singleton_class do
|
|
285
|
-
define_method(key){ instance_variable_get "@#{ key }" }
|
|
286
|
-
define_method(key.capitalize){ instance_variable_get "@#{ key }" }
|
|
287
|
-
end
|
|
288
|
-
end #--}}}
|
|
289
|
-
def configure hash #--{{{
|
|
290
|
-
hash.each{|k,v| set k, v}
|
|
291
|
-
end #--}}}
|
|
292
|
-
def expand message #--{{{
|
|
293
|
-
ERB.new(message).result binding
|
|
294
|
-
end #--}}}
|
|
295
|
-
def lazy #--{{{
|
|
296
|
-
singleton_class{ define_method m, &b }
|
|
297
|
-
end #--}}}
|
|
298
|
-
def method_missing m, *a, &b
|
|
299
|
-
super unless defined? @mail
|
|
300
|
-
@mail.send m, *a, &b
|
|
301
|
-
end
|
|
302
|
-
end #--}}}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
BEGIN {
|
|
307
|
-
|
|
308
|
-
### hacking in smtp tls support
|
|
309
|
-
#--{{{
|
|
310
|
-
# Original code believed public domain from ruby-talk or ruby-core email.
|
|
311
|
-
# Modifications by Kyle Maxwell <kyle@kylemaxwell.com> used under MIT license.
|
|
312
|
-
|
|
313
|
-
require "openssl"
|
|
314
|
-
require "net/smtp"
|
|
315
|
-
|
|
316
|
-
# :stopdoc:
|
|
317
|
-
|
|
318
|
-
class Net::SMTP
|
|
319
|
-
|
|
320
|
-
class << self
|
|
321
|
-
send :remove_method, :start
|
|
322
|
-
end
|
|
323
|
-
|
|
324
|
-
def self.start( address, port = nil,
|
|
325
|
-
helo = 'localhost.localdomain',
|
|
326
|
-
user = nil, secret = nil, authtype = nil, use_tls = false,
|
|
327
|
-
&block) # :yield: smtp
|
|
328
|
-
new(address, port).start(helo, user, secret, authtype, use_tls, &block)
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
alias tls_old_start start
|
|
332
|
-
|
|
333
|
-
def start( helo = 'localhost.localdomain',
|
|
334
|
-
user = nil, secret = nil, authtype = nil, use_tls = false ) # :yield: smtp
|
|
335
|
-
start_method = use_tls ? :do_tls_start : :do_start
|
|
336
|
-
if block_given?
|
|
337
|
-
begin
|
|
338
|
-
send start_method, helo, user, secret, authtype
|
|
339
|
-
return yield(self)
|
|
340
|
-
ensure
|
|
341
|
-
do_finish
|
|
342
|
-
end
|
|
343
|
-
else
|
|
344
|
-
send start_method, helo, user, secret, authtype
|
|
345
|
-
return self
|
|
346
|
-
end
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
private
|
|
350
|
-
|
|
351
|
-
def do_tls_start(helodomain, user, secret, authtype)
|
|
352
|
-
raise IOError, 'SMTP session already started' if @started
|
|
353
|
-
check_auth_args user, secret, authtype if user or secret
|
|
354
|
-
|
|
355
|
-
sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
|
|
356
|
-
@socket = Net::InternetMessageIO.new(sock)
|
|
357
|
-
@socket.read_timeout = 60 #@read_timeout
|
|
358
|
-
@socket.debug_output = @debug_output
|
|
359
|
-
|
|
360
|
-
check_response(critical { recv_response() })
|
|
361
|
-
do_helo(helodomain)
|
|
362
|
-
|
|
363
|
-
raise 'openssl library not installed' unless defined?(OpenSSL)
|
|
364
|
-
starttls
|
|
365
|
-
ssl = OpenSSL::SSL::SSLSocket.new(sock)
|
|
366
|
-
ssl.sync_close = true
|
|
367
|
-
ssl.connect
|
|
368
|
-
@socket = Net::InternetMessageIO.new(ssl)
|
|
369
|
-
@socket.read_timeout = 60 #@read_timeout
|
|
370
|
-
@socket.debug_output = @debug_output
|
|
371
|
-
do_helo(helodomain)
|
|
372
|
-
|
|
373
|
-
authenticate user, secret, authtype if user
|
|
374
|
-
@started = true
|
|
375
|
-
ensure
|
|
376
|
-
unless @started
|
|
377
|
-
# authentication failed, cancel connection.
|
|
378
|
-
@socket.close if not @started and @socket and not @socket.closed?
|
|
379
|
-
@socket = nil
|
|
380
|
-
end
|
|
381
|
-
end
|
|
382
|
-
|
|
383
|
-
def do_helo(helodomain)
|
|
384
|
-
begin
|
|
385
|
-
if @esmtp
|
|
386
|
-
ehlo helodomain
|
|
387
|
-
else
|
|
388
|
-
helo helodomain
|
|
389
|
-
end
|
|
390
|
-
rescue Net::ProtocolError
|
|
391
|
-
if @esmtp
|
|
392
|
-
@esmtp = false
|
|
393
|
-
@error_occured = false
|
|
394
|
-
retry
|
|
395
|
-
end
|
|
396
|
-
raise
|
|
397
|
-
end
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def starttls
|
|
401
|
-
getok('STARTTLS')
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
alias tls_old_quit quit
|
|
405
|
-
|
|
406
|
-
def quit
|
|
407
|
-
begin
|
|
408
|
-
getok('QUIT')
|
|
409
|
-
rescue EOFError
|
|
410
|
-
end
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
end unless Net::SMTP.private_method_defined? :do_tls_start or
|
|
414
|
-
Net::SMTP.method_defined? :tls?
|
|
415
|
-
#--}}}
|
|
416
|
-
|
|
417
|
-
### inlining mailfactory
|
|
418
|
-
#--{{{
|
|
419
|
-
# = Overview:
|
|
420
|
-
# A simple to use module for generating RFC compliant MIME mail
|
|
421
|
-
# ---
|
|
422
|
-
# = License:
|
|
423
|
-
# Author:: David Powers
|
|
424
|
-
# Copyright:: May, 2005
|
|
425
|
-
# License:: Ruby License
|
|
426
|
-
# ---
|
|
427
|
-
# = Usage:
|
|
428
|
-
# require 'net/smtp'
|
|
429
|
-
# require 'rubygems'
|
|
430
|
-
# require 'mailfactory'
|
|
431
|
-
#
|
|
432
|
-
#
|
|
433
|
-
# mail = MailFactory.new()
|
|
434
|
-
# mail.to = "test@test.com"
|
|
435
|
-
# mail.from = "sender@sender.com"
|
|
436
|
-
# mail.subject = "Here are some files for you!"
|
|
437
|
-
# mail.text = "This is what people with plain text mail readers will see"
|
|
438
|
-
# mail.html = "A little something <b>special</b> for people with HTML readers"
|
|
439
|
-
# mail.attach("/etc/fstab")
|
|
440
|
-
# mail.attach("/some/other/file")
|
|
441
|
-
#
|
|
442
|
-
# Net::SMTP.start('smtp1.testmailer.com', 25, 'mail.from.domain', fromaddress, password, :cram_md5) { |smtp|
|
|
443
|
-
# mail.to = toaddress
|
|
444
|
-
# smtp.send_message(mail.to_s(), fromaddress, toaddress)
|
|
445
|
-
# }
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
require 'base64'
|
|
450
|
-
require 'pathname'
|
|
451
|
-
|
|
452
|
-
# try to bring in the mime/types module, make a dummy module if it can't be found
|
|
453
|
-
begin
|
|
454
|
-
begin
|
|
455
|
-
require 'rubygems'
|
|
456
|
-
rescue LoadError
|
|
457
|
-
end
|
|
458
|
-
require 'mime/types'
|
|
459
|
-
rescue LoadError
|
|
460
|
-
module MIME
|
|
461
|
-
class Types
|
|
462
|
-
def Types::type_for(filename)
|
|
463
|
-
return('')
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
# An easy class for creating a mail message
|
|
470
|
-
class MailFactory
|
|
471
|
-
|
|
472
|
-
def initialize()
|
|
473
|
-
@headers = Array.new()
|
|
474
|
-
@attachments = Array.new()
|
|
475
|
-
@attachmentboundary = generate_boundary()
|
|
476
|
-
@bodyboundary = generate_boundary()
|
|
477
|
-
@html = nil
|
|
478
|
-
@text = nil
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
# adds a header to the bottom of the headers
|
|
483
|
-
def add_header(header, value)
|
|
484
|
-
@headers << "#{header}: #{value}"
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
# removes the named header - case insensitive
|
|
489
|
-
def remove_header(header)
|
|
490
|
-
@headers.each_index() { |i|
|
|
491
|
-
if(@headers[i] =~ /^#{Regexp.escape(header)}:/i)
|
|
492
|
-
@headers.delete_at(i)
|
|
493
|
-
end
|
|
494
|
-
}
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
# sets a header (removing any other versions of that header)
|
|
499
|
-
def set_header(header, value)
|
|
500
|
-
remove_header(header)
|
|
501
|
-
add_header(header, value)
|
|
502
|
-
end
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
def replyto=(newreplyto)
|
|
506
|
-
remove_header("Reply-To")
|
|
507
|
-
add_header("Reply-To", newreplyto)
|
|
508
|
-
end
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
def replyto()
|
|
512
|
-
return(get_header("Reply-To")[0])
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
def self.hattr h
|
|
516
|
-
h = h.to_s
|
|
517
|
-
module_eval <<-code
|
|
518
|
-
def #{ h.downcase }=(value)
|
|
519
|
-
remove_header("#{ h.downcase.capitalize }")
|
|
520
|
-
add_header("#{ h.downcase.capitalize }", value)
|
|
521
|
-
end
|
|
522
|
-
def #{ h.downcase }()
|
|
523
|
-
return(get_header("#{ h.downcase.capitalize }")[0])
|
|
524
|
-
end
|
|
525
|
-
code
|
|
526
|
-
end
|
|
527
|
-
%w( to from cc bcc subject ).each{|h| hattr h}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
# sets the plain text body of the message
|
|
531
|
-
def text=(newtext)
|
|
532
|
-
@text = newtext
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
# sets the HTML body of the message. Only the body of the
|
|
537
|
-
# html should be provided
|
|
538
|
-
def html=(newhtml)
|
|
539
|
-
@html = "<html>\n<head>\n<meta content=\"text/html;charset=ISO-8859-1\" http-equiv=\"Content-Type\">\n</head>\n<body bgcolor=\"#ffffff\" text=\"#000000\">\n#{newhtml}\n</body>\n</html>"
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
# sets the HTML body of the message. The entire HTML section should be provided
|
|
544
|
-
def rawhtml=(newhtml)
|
|
545
|
-
@html = newhtml
|
|
546
|
-
end
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
# implement method missing to provide helper methods for setting and getting headers.
|
|
550
|
-
# Headers with '-' characters may be set/gotten as 'x_mailer' or 'XMailer' (splitting
|
|
551
|
-
# will occur between capital letters or on '_' chracters)
|
|
552
|
-
def method_missing(methId, *args)
|
|
553
|
-
name = methId.id2name()
|
|
554
|
-
|
|
555
|
-
# mangle the name if we have to
|
|
556
|
-
if(name =~ /_/)
|
|
557
|
-
name = name.gsub(/_/, '-')
|
|
558
|
-
elsif(name =~ /[A-Z]/)
|
|
559
|
-
name = name.gsub(/([a-zA-Z])([A-Z])/, '\1-\2')
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
# determine if it sets or gets, and do the right thing
|
|
563
|
-
if(name =~ /=$/)
|
|
564
|
-
if(args.length != 1)
|
|
565
|
-
super(methId, args)
|
|
566
|
-
end
|
|
567
|
-
set_header(name[/^(.*)=$/, 1], args[0])
|
|
568
|
-
else
|
|
569
|
-
if(args.length != 0)
|
|
570
|
-
super(methId, args)
|
|
571
|
-
end
|
|
572
|
-
headers = get_header(name)
|
|
573
|
-
return(get_header(name))
|
|
574
|
-
end
|
|
575
|
-
end
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
# returns the value (or values) of the named header in an array
|
|
579
|
-
def get_header(header)
|
|
580
|
-
headers = Array.new()
|
|
581
|
-
headerregex = /^#{Regexp.escape(header)}:/i
|
|
582
|
-
@headers.each() { |h|
|
|
583
|
-
if(headerregex.match(h))
|
|
584
|
-
headers << h[/^[^:]+:(.*)/i, 1].strip()
|
|
585
|
-
end
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
return(headers)
|
|
589
|
-
end
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
# returns true if the email is multipart
|
|
593
|
-
def multipart?()
|
|
594
|
-
if(@attachments.length > 0 or @html != nil)
|
|
595
|
-
return(true)
|
|
596
|
-
else
|
|
597
|
-
return(false)
|
|
598
|
-
end
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
# builds an email and returns it as a string. Takes the following options:
|
|
603
|
-
# <tt>:messageid</tt>:: Adds a message id to the message based on the from header (defaults to false)
|
|
604
|
-
# <tt>:date</tt>:: Adds a date to the message if one is not present (defaults to true)
|
|
605
|
-
def construct(options = Hash.new)
|
|
606
|
-
if(options[:date] == nil)
|
|
607
|
-
options[:date] = true
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
if(options[:messageid])
|
|
611
|
-
# add a unique message-id
|
|
612
|
-
remove_header("Message-ID")
|
|
613
|
-
sendingdomain = get_header('from')[0].to_s()[/@([-a-zA-Z0-9._]+)/,1].to_s()
|
|
614
|
-
add_header("Message-ID", "<#{Time.now.to_f()}.#{Process.euid()}.#{String.new.object_id()}@#{sendingdomain}>")
|
|
615
|
-
end
|
|
616
|
-
|
|
617
|
-
if(options[:date])
|
|
618
|
-
if(get_header("Date").length == 0)
|
|
619
|
-
add_header("Date", Time.now.strftime("%a, %d %b %Y %H:%M:%S %z"))
|
|
620
|
-
end
|
|
621
|
-
end
|
|
622
|
-
|
|
623
|
-
# Add a mime header if we don't already have one and we have multiple parts
|
|
624
|
-
if(multipart?())
|
|
625
|
-
if(get_header("MIME-Version").length == 0)
|
|
626
|
-
add_header("MIME-Version", "1.0")
|
|
627
|
-
end
|
|
628
|
-
|
|
629
|
-
if(get_header("Content-Type").length == 0)
|
|
630
|
-
if(@attachments.length == 0)
|
|
631
|
-
add_header("Content-Type", "multipart/alternative;boundary=\"#{@bodyboundary}\"")
|
|
632
|
-
else
|
|
633
|
-
add_header("Content-Type", "multipart/mixed; boundary=\"#{@attachmentboundary}\"")
|
|
634
|
-
end
|
|
635
|
-
end
|
|
636
|
-
end
|
|
637
|
-
|
|
638
|
-
return("#{headers_to_s()}#{body_to_s()}")
|
|
639
|
-
end
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
# returns a formatted email - equivalent to construct(:messageid => true)
|
|
643
|
-
def to_s()
|
|
644
|
-
return(construct(:messageid => true))
|
|
645
|
-
end
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
# generates a unique boundary string
|
|
649
|
-
def generate_boundary()
|
|
650
|
-
randomstring = Array.new()
|
|
651
|
-
1.upto(25) {
|
|
652
|
-
whichglyph = rand(100)
|
|
653
|
-
if(whichglyph < 40)
|
|
654
|
-
randomstring << (rand(25) + 65).chr()
|
|
655
|
-
elsif(whichglyph < 70)
|
|
656
|
-
randomstring << (rand(25) + 97).chr()
|
|
657
|
-
elsif(whichglyph < 90)
|
|
658
|
-
randomstring << (rand(10) + 48).chr()
|
|
659
|
-
elsif(whichglyph < 95)
|
|
660
|
-
randomstring << '.'
|
|
661
|
-
else
|
|
662
|
-
randomstring << '_'
|
|
663
|
-
end
|
|
664
|
-
}
|
|
665
|
-
return("----=_NextPart_#{randomstring.join()}")
|
|
666
|
-
end
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
# adds an attachment to the mail. Type may be given as a mime type. If it
|
|
670
|
-
# is left off and the MIME::Types module is available it will be determined automagically.
|
|
671
|
-
# If the optional attachemntheaders is given, then they will be added to the attachment
|
|
672
|
-
# boundary in the email, which can be used to produce Content-ID markers. attachmentheaders
|
|
673
|
-
# can be given as an Array or a String.
|
|
674
|
-
def add_attachment(filename, type=nil, attachmentheaders = nil)
|
|
675
|
-
attachment = Hash.new()
|
|
676
|
-
attachment['filename'] = Pathname.new(filename).basename
|
|
677
|
-
if(type == nil)
|
|
678
|
-
attachment['mimetype'] = MIME::Types.type_for(filename).to_s
|
|
679
|
-
else
|
|
680
|
-
attachment['mimetype'] = type
|
|
681
|
-
end
|
|
682
|
-
|
|
683
|
-
# Open in rb mode to handle Windows, which mangles binary files opened in a text mode
|
|
684
|
-
File.open(filename, "rb") { |fp|
|
|
685
|
-
attachment['attachment'] = file_encode(fp.read())
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
if(attachmentheaders != nil)
|
|
689
|
-
if(!attachmentheaders.kind_of?(Array))
|
|
690
|
-
attachmentheaders = attachmentheaders.split(/\r?\n/)
|
|
691
|
-
end
|
|
692
|
-
attachment['headers'] = attachmentheaders
|
|
693
|
-
end
|
|
694
|
-
|
|
695
|
-
@attachments << attachment
|
|
696
|
-
end
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
# adds an attachment to the mail as emailfilename. Type may be given as a mime type. If it
|
|
700
|
-
# is left off and the MIME::Types module is available it will be determined automagically.
|
|
701
|
-
# file may be given as an IO stream (which will be read until the end) or as a filename.
|
|
702
|
-
# If the optional attachemntheaders is given, then they will be added to the attachment
|
|
703
|
-
# boundary in the email, which can be used to produce Content-ID markers. attachmentheaders
|
|
704
|
-
# can be given as an Array of a String.
|
|
705
|
-
def add_attachment_as(file, emailfilename, type=nil, attachmentheaders = nil)
|
|
706
|
-
attachment = Hash.new()
|
|
707
|
-
attachment['filename'] = emailfilename
|
|
708
|
-
|
|
709
|
-
if(type != nil)
|
|
710
|
-
attachment['mimetype'] = type.to_s()
|
|
711
|
-
elsif(file.kind_of?(String) or file.kind_of?(Pathname))
|
|
712
|
-
attachment['mimetype'] = MIME::Types.type_for(file.to_s()).to_s
|
|
713
|
-
else
|
|
714
|
-
attachment['mimetype'] = ''
|
|
715
|
-
end
|
|
716
|
-
|
|
717
|
-
if(file.kind_of?(String) or file.kind_of?(Pathname))
|
|
718
|
-
# Open in rb mode to handle Windows, which mangles binary files opened in a text mode
|
|
719
|
-
File.open(file.to_s(), "rb") { |fp|
|
|
720
|
-
attachment['attachment'] = file_encode(fp.read())
|
|
721
|
-
}
|
|
722
|
-
elsif(file.respond_to?(:read))
|
|
723
|
-
attachment['attachment'] = file_encode(file.read())
|
|
724
|
-
else
|
|
725
|
-
raise(Exception, "file is not a supported type (must be a String, Pathnamem, or support read method)")
|
|
726
|
-
end
|
|
727
|
-
|
|
728
|
-
if(attachmentheaders != nil)
|
|
729
|
-
if(!attachmentheaders.kind_of?(Array))
|
|
730
|
-
attachmentheaders = attachmentheaders.split(/\r?\n/)
|
|
731
|
-
end
|
|
732
|
-
attachment['headers'] = attachmentheaders
|
|
733
|
-
end
|
|
734
|
-
|
|
735
|
-
@attachments << attachment
|
|
736
|
-
end
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
alias attach add_attachment
|
|
740
|
-
alias attach_as add_attachment_as
|
|
741
|
-
|
|
742
|
-
protected
|
|
743
|
-
|
|
744
|
-
# returns the @headers as a properly formatted string
|
|
745
|
-
def headers_to_s()
|
|
746
|
-
return("#{@headers.join("\r\n")}\r\n\r\n")
|
|
747
|
-
end
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
# returns the body as a properly formatted string
|
|
751
|
-
def body_to_s()
|
|
752
|
-
body = Array.new()
|
|
753
|
-
|
|
754
|
-
# simple message with one part
|
|
755
|
-
if(!multipart?())
|
|
756
|
-
return(@text)
|
|
757
|
-
else
|
|
758
|
-
body << "This is a multi-part message in MIME format.\r\n\r\n--#{@attachmentboundary}\r\nContent-Type: multipart/alternative; boundary=\"#{@bodyboundary}\""
|
|
759
|
-
|
|
760
|
-
if(@attachments.length > 0)
|
|
761
|
-
# text part
|
|
762
|
-
body << "#{buildbodyboundary('text/plain; charset=ISO-8859-1; format=flowed', '7bit')}\r\n\r\n#{@text}"
|
|
763
|
-
|
|
764
|
-
# html part if one is provided
|
|
765
|
-
if @html
|
|
766
|
-
body << "#{buildbodyboundary('text/html; charset=ISO-8859-1', '7bit')}\r\n\r\n#{@html}"
|
|
767
|
-
end
|
|
768
|
-
|
|
769
|
-
body << "--#{@bodyboundary}--"
|
|
770
|
-
|
|
771
|
-
# and, the attachments
|
|
772
|
-
if(@attachments.length > 0)
|
|
773
|
-
@attachments.each() { |attachment|
|
|
774
|
-
body << "#{buildattachmentboundary(attachment)}\r\n\r\n#{attachment['attachment']}"
|
|
775
|
-
}
|
|
776
|
-
body << "\r\n--#{@attachmentboundary}--"
|
|
777
|
-
end
|
|
778
|
-
else
|
|
779
|
-
# text part
|
|
780
|
-
body << "#{buildbodyboundary('text/plain; charset=ISO-8859-1; format=flowed', '7bit')}\r\n\r\n#{@text}"
|
|
781
|
-
|
|
782
|
-
# html part
|
|
783
|
-
body << "#{buildbodyboundary('text/html; charset=ISO-8859-1', '7bit')}\r\n\r\n#{@html}"
|
|
784
|
-
|
|
785
|
-
body << "--#{@bodyboundary}--"
|
|
786
|
-
end
|
|
787
|
-
|
|
788
|
-
return(body.join("\r\n\r\n"))
|
|
789
|
-
end
|
|
790
|
-
end
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
# builds a boundary string for including attachments in the body, expects an attachment hash as built by
|
|
794
|
-
# add_attachment and add_attachment_as
|
|
795
|
-
def buildattachmentboundary(attachment)
|
|
796
|
-
disposition = "Content-Disposition: inline; filename=\"#{attachment['filename']}\""
|
|
797
|
-
boundary = "--#{@attachmentboundary}\r\nContent-Type: #{attachment['mimetype']}; name=\"#{attachment['filename']}\"\r\nContent-Transfer-Encoding: base64\r\n#{disposition}"
|
|
798
|
-
if(attachment['headers'])
|
|
799
|
-
boundary = boundary + "\r\n#{attachment['headers'].join("\r\n")}"
|
|
800
|
-
end
|
|
801
|
-
|
|
802
|
-
return(boundary)
|
|
803
|
-
end
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
# builds a boundary string for inclusion in the body of a message
|
|
807
|
-
def buildbodyboundary(type, encoding)
|
|
808
|
-
return("--#{@bodyboundary}\r\nContent-Type: #{type}\r\nContent-Transfer-Encoding: #{encoding}")
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
# returns a base64 encoded version of the contents of str
|
|
813
|
-
def file_encode(str)
|
|
814
|
-
collection = Array.new()
|
|
815
|
-
enc = Base64.encode64(str)
|
|
816
|
-
# while(enc.length > 60)
|
|
817
|
-
# collection << enc.slice!(0..59)
|
|
818
|
-
# end
|
|
819
|
-
# collection << enc
|
|
820
|
-
# return(collection.join("\n"))
|
|
821
|
-
return(enc)
|
|
822
|
-
end
|
|
823
|
-
|
|
824
|
-
end
|
|
825
|
-
|
|
826
|
-
#--}}}
|
|
827
|
-
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
__END__
|
|
832
|
-
### rqmailer
|
|
833
|
-
|
|
834
|
-
CMD:
|
|
835
|
-
<%= cmd %>
|
|
836
|
-
|
|
837
|
-
EXIT_STATUS:
|
|
838
|
-
<%= exit_status %>
|
|
839
|
-
|
|
840
|
-
STDIN:
|
|
841
|
-
<%= stdin %>
|
|
842
|
-
|
|
843
|
-
STDOUT:
|
|
844
|
-
<%= stdout %>
|
|
845
|
-
|
|
846
|
-
STDERR:
|
|
847
|
-
<%= stderr %>
|
data/rails/q/db
DELETED
|
Binary file
|
data/rails/q/db.schema
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
PRAGMA default_synchronous = FULL;
|
|
2
|
-
create table jobs
|
|
3
|
-
(
|
|
4
|
-
jid integer primary key,
|
|
5
|
-
priority,
|
|
6
|
-
state,
|
|
7
|
-
submitted,
|
|
8
|
-
started,
|
|
9
|
-
finished,
|
|
10
|
-
elapsed,
|
|
11
|
-
submitter,
|
|
12
|
-
runner,
|
|
13
|
-
stdin,
|
|
14
|
-
stdout,
|
|
15
|
-
stderr,
|
|
16
|
-
data,
|
|
17
|
-
pid,
|
|
18
|
-
exit_status,
|
|
19
|
-
tag,
|
|
20
|
-
restartable,
|
|
21
|
-
command
|
|
22
|
-
);
|
|
23
|
-
create table attributes
|
|
24
|
-
(
|
|
25
|
-
key,
|
|
26
|
-
value,
|
|
27
|
-
primary key (key)
|
|
28
|
-
);
|
data/rails/q/lock
DELETED
|
File without changes
|