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