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