##// END OF EJS Templates
Fixed thatinitialize_http_header overrides basic auth in rdm-mailhandler.rb (#13165)....
Jean-Philippe Lang -
r11141:f77edce621c6
parent child
Show More
@@ -1,150 +1,150
1 #!/usr/bin/env ruby
1 #!/usr/bin/env ruby
2
2
3 require 'net/http'
3 require 'net/http'
4 require 'net/https'
4 require 'net/https'
5 require 'uri'
5 require 'uri'
6 require 'optparse'
6 require 'optparse'
7
7
8 module Net
8 module Net
9 class HTTPS < HTTP
9 class HTTPS < HTTP
10 def self.post_form(url, params, headers, options={})
10 def self.post_form(url, params, headers, options={})
11 request = Post.new(url.path)
11 request = Post.new(url.path)
12 request.form_data = params
12 request.form_data = params
13 request.basic_auth url.user, url.password if url.user
14 request.initialize_http_header(headers)
13 request.initialize_http_header(headers)
14 request.basic_auth url.user, url.password if url.user
15 http = new(url.host, url.port)
15 http = new(url.host, url.port)
16 http.use_ssl = (url.scheme == 'https')
16 http.use_ssl = (url.scheme == 'https')
17 if options[:no_check_certificate]
17 if options[:no_check_certificate]
18 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
18 http.verify_mode = OpenSSL::SSL::VERIFY_NONE
19 end
19 end
20 http.start {|h| h.request(request) }
20 http.start {|h| h.request(request) }
21 end
21 end
22 end
22 end
23 end
23 end
24
24
25 class RedmineMailHandler
25 class RedmineMailHandler
26 VERSION = '0.2'
26 VERSION = '0.2.1'
27
27
28 attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :no_permission_check, :url, :key, :no_check_certificate
28 attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :no_permission_check, :url, :key, :no_check_certificate
29
29
30 def initialize
30 def initialize
31 self.issue_attributes = {}
31 self.issue_attributes = {}
32
32
33 optparse = OptionParser.new do |opts|
33 optparse = OptionParser.new do |opts|
34 opts.banner = "Usage: rdm-mailhandler.rb [options] --url=<Redmine URL> --key=<API key>"
34 opts.banner = "Usage: rdm-mailhandler.rb [options] --url=<Redmine URL> --key=<API key>"
35 opts.separator("")
35 opts.separator("")
36 opts.separator("Reads an email from standard input and forward it to a Redmine server through a HTTP request.")
36 opts.separator("Reads an email from standard input and forward it to a Redmine server through a HTTP request.")
37 opts.separator("")
37 opts.separator("")
38 opts.separator("Required arguments:")
38 opts.separator("Required arguments:")
39 opts.on("-u", "--url URL", "URL of the Redmine server") {|v| self.url = v}
39 opts.on("-u", "--url URL", "URL of the Redmine server") {|v| self.url = v}
40 opts.on("-k", "--key KEY", "Redmine API key") {|v| self.key = v}
40 opts.on("-k", "--key KEY", "Redmine API key") {|v| self.key = v}
41 opts.separator("")
41 opts.separator("")
42 opts.separator("General options:")
42 opts.separator("General options:")
43 opts.on("--unknown-user ACTION", "how to handle emails from an unknown user",
43 opts.on("--unknown-user ACTION", "how to handle emails from an unknown user",
44 "ACTION can be one of the following values:",
44 "ACTION can be one of the following values:",
45 "* ignore: email is ignored (default)",
45 "* ignore: email is ignored (default)",
46 "* accept: accept as anonymous user",
46 "* accept: accept as anonymous user",
47 "* create: create a user account") {|v| self.unknown_user = v}
47 "* create: create a user account") {|v| self.unknown_user = v}
48 opts.on("--no-permission-check", "disable permission checking when receiving",
48 opts.on("--no-permission-check", "disable permission checking when receiving",
49 "the email") {self.no_permission_check = '1'}
49 "the email") {self.no_permission_check = '1'}
50 opts.on("--key-file FILE", "path to a file that contains the Redmine",
50 opts.on("--key-file FILE", "path to a file that contains the Redmine",
51 "API key (use this option instead of --key",
51 "API key (use this option instead of --key",
52 "if you don't the key to appear in the",
52 "if you don't the key to appear in the",
53 "command line)") {|v| read_key_from_file(v)}
53 "command line)") {|v| read_key_from_file(v)}
54 opts.on("--no-check-certificate", "do not check server certificate") {self.no_check_certificate = true}
54 opts.on("--no-check-certificate", "do not check server certificate") {self.no_check_certificate = true}
55 opts.on("-h", "--help", "show this help") {puts opts; exit 1}
55 opts.on("-h", "--help", "show this help") {puts opts; exit 1}
56 opts.on("-v", "--verbose", "show extra information") {self.verbose = true}
56 opts.on("-v", "--verbose", "show extra information") {self.verbose = true}
57 opts.on("-V", "--version", "show version information and exit") {puts VERSION; exit}
57 opts.on("-V", "--version", "show version information and exit") {puts VERSION; exit}
58 opts.separator("")
58 opts.separator("")
59 opts.separator("Issue attributes control options:")
59 opts.separator("Issue attributes control options:")
60 opts.on("-p", "--project PROJECT", "identifier of the target project") {|v| self.issue_attributes['project'] = v}
60 opts.on("-p", "--project PROJECT", "identifier of the target project") {|v| self.issue_attributes['project'] = v}
61 opts.on("-s", "--status STATUS", "name of the target status") {|v| self.issue_attributes['status'] = v}
61 opts.on("-s", "--status STATUS", "name of the target status") {|v| self.issue_attributes['status'] = v}
62 opts.on("-t", "--tracker TRACKER", "name of the target tracker") {|v| self.issue_attributes['tracker'] = v}
62 opts.on("-t", "--tracker TRACKER", "name of the target tracker") {|v| self.issue_attributes['tracker'] = v}
63 opts.on( "--category CATEGORY", "name of the target category") {|v| self.issue_attributes['category'] = v}
63 opts.on( "--category CATEGORY", "name of the target category") {|v| self.issue_attributes['category'] = v}
64 opts.on( "--priority PRIORITY", "name of the target priority") {|v| self.issue_attributes['priority'] = v}
64 opts.on( "--priority PRIORITY", "name of the target priority") {|v| self.issue_attributes['priority'] = v}
65 opts.on("-o", "--allow-override ATTRS", "allow email content to override attributes",
65 opts.on("-o", "--allow-override ATTRS", "allow email content to override attributes",
66 "specified by previous options",
66 "specified by previous options",
67 "ATTRS is a comma separated list of attributes") {|v| self.allow_override = v}
67 "ATTRS is a comma separated list of attributes") {|v| self.allow_override = v}
68 opts.separator("")
68 opts.separator("")
69 opts.separator("Examples:")
69 opts.separator("Examples:")
70 opts.separator("No project specified. Emails MUST contain the 'Project' keyword:")
70 opts.separator("No project specified. Emails MUST contain the 'Project' keyword:")
71 opts.separator(" rdm-mailhandler.rb --url http://redmine.domain.foo --key secret")
71 opts.separator(" rdm-mailhandler.rb --url http://redmine.domain.foo --key secret")
72 opts.separator("")
72 opts.separator("")
73 opts.separator("Fixed project and default tracker specified, but emails can override")
73 opts.separator("Fixed project and default tracker specified, but emails can override")
74 opts.separator("both tracker and priority attributes using keywords:")
74 opts.separator("both tracker and priority attributes using keywords:")
75 opts.separator(" rdm-mailhandler.rb --url https://domain.foo/redmine --key secret \\")
75 opts.separator(" rdm-mailhandler.rb --url https://domain.foo/redmine --key secret \\")
76 opts.separator(" --project foo \\")
76 opts.separator(" --project foo \\")
77 opts.separator(" --tracker bug \\")
77 opts.separator(" --tracker bug \\")
78 opts.separator(" --allow-override tracker,priority")
78 opts.separator(" --allow-override tracker,priority")
79
79
80 opts.summary_width = 27
80 opts.summary_width = 27
81 end
81 end
82 optparse.parse!
82 optparse.parse!
83
83
84 unless url && key
84 unless url && key
85 puts "Some arguments are missing. Use `rdm-mailhandler.rb --help` for getting help."
85 puts "Some arguments are missing. Use `rdm-mailhandler.rb --help` for getting help."
86 exit 1
86 exit 1
87 end
87 end
88 end
88 end
89
89
90 def submit(email)
90 def submit(email)
91 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
91 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
92
92
93 headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
93 headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
94
94
95 data = { 'key' => key, 'email' => email,
95 data = { 'key' => key, 'email' => email,
96 'allow_override' => allow_override,
96 'allow_override' => allow_override,
97 'unknown_user' => unknown_user,
97 'unknown_user' => unknown_user,
98 'no_permission_check' => no_permission_check}
98 'no_permission_check' => no_permission_check}
99 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
99 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
100
100
101 debug "Posting to #{uri}..."
101 debug "Posting to #{uri}..."
102 begin
102 begin
103 response = Net::HTTPS.post_form(URI.parse(uri), data, headers, :no_check_certificate => no_check_certificate)
103 response = Net::HTTPS.post_form(URI.parse(uri), data, headers, :no_check_certificate => no_check_certificate)
104 rescue SystemCallError => e # connection refused, etc.
104 rescue SystemCallError => e # connection refused, etc.
105 warn "An error occured while contacting your Redmine server: #{e.message}"
105 warn "An error occured while contacting your Redmine server: #{e.message}"
106 return 75 # temporary failure
106 return 75 # temporary failure
107 end
107 end
108 debug "Response received: #{response.code}"
108 debug "Response received: #{response.code}"
109
109
110 case response.code.to_i
110 case response.code.to_i
111 when 403
111 when 403
112 warn "Request was denied by your Redmine server. " +
112 warn "Request was denied by your Redmine server. " +
113 "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
113 "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
114 return 77
114 return 77
115 when 422
115 when 422
116 warn "Request was denied by your Redmine server. " +
116 warn "Request was denied by your Redmine server. " +
117 "Possible reasons: email is sent from an invalid email address or is missing some information."
117 "Possible reasons: email is sent from an invalid email address or is missing some information."
118 return 77
118 return 77
119 when 400..499
119 when 400..499
120 warn "Request was denied by your Redmine server (#{response.code})."
120 warn "Request was denied by your Redmine server (#{response.code})."
121 return 77
121 return 77
122 when 500..599
122 when 500..599
123 warn "Failed to contact your Redmine server (#{response.code})."
123 warn "Failed to contact your Redmine server (#{response.code})."
124 return 75
124 return 75
125 when 201
125 when 201
126 debug "Proccessed successfully"
126 debug "Proccessed successfully"
127 return 0
127 return 0
128 else
128 else
129 return 1
129 return 1
130 end
130 end
131 end
131 end
132
132
133 private
133 private
134
134
135 def debug(msg)
135 def debug(msg)
136 puts msg if verbose
136 puts msg if verbose
137 end
137 end
138
138
139 def read_key_from_file(filename)
139 def read_key_from_file(filename)
140 begin
140 begin
141 self.key = File.read(filename).strip
141 self.key = File.read(filename).strip
142 rescue Exception => e
142 rescue Exception => e
143 $stderr.puts "Unable to read the key from #{filename}:\n#{e.message}"
143 $stderr.puts "Unable to read the key from #{filename}:\n#{e.message}"
144 exit 1
144 exit 1
145 end
145 end
146 end
146 end
147 end
147 end
148
148
149 handler = RedmineMailHandler.new
149 handler = RedmineMailHandler.new
150 exit(handler.submit(STDIN.read))
150 exit(handler.submit(STDIN.read))
General Comments 0
You need to be logged in to leave comments. Login now