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