##// END OF EJS Templates
Improve rdm-mailhandler exit status (#4368)....
Jean-Philippe Lang -
r3029:84abeac304a9
parent child
Show More
@@ -1,141 +1,159
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 # -h, --help show this help
23 # -h, --help show this help
24 # -v, --verbose show extra information
24 # -v, --verbose show extra information
25 # -V, --version show version information and exit
25 # -V, --version show version information and exit
26 #
26 #
27 # Issue attributes control options:
27 # Issue attributes control options:
28 # -p, --project=PROJECT identifier of the target project
28 # -p, --project=PROJECT identifier of the target project
29 # -s, --status=STATUS name of the target status
29 # -s, --status=STATUS name of the target status
30 # -t, --tracker=TRACKER name of the target tracker
30 # -t, --tracker=TRACKER name of the target tracker
31 # --category=CATEGORY name of the target category
31 # --category=CATEGORY name of the target category
32 # --priority=PRIORITY name of the target priority
32 # --priority=PRIORITY name of the target priority
33 # -o, --allow-override=ATTRS allow email content to override attributes
33 # -o, --allow-override=ATTRS allow email content to override attributes
34 # specified by previous options
34 # specified by previous options
35 # ATTRS is a comma separated list of attributes
35 # ATTRS is a comma separated list of attributes
36 #
36 #
37 # == Examples
37 # == Examples
38 # No project specified. Emails MUST contain the 'Project' keyword:
38 # No project specified. Emails MUST contain the 'Project' keyword:
39 #
39 #
40 # rdm-mailhandler --url http://redmine.domain.foo --key secret
40 # rdm-mailhandler --url http://redmine.domain.foo --key secret
41 #
41 #
42 # Fixed project and default tracker specified, but emails can override
42 # Fixed project and default tracker specified, but emails can override
43 # both tracker and priority attributes using keywords:
43 # both tracker and priority attributes using keywords:
44 #
44 #
45 # rdm-mailhandler --url https://domain.foo/redmine --key secret \\
45 # rdm-mailhandler --url https://domain.foo/redmine --key secret \\
46 # --project foo \\
46 # --project foo \\
47 # --tracker bug \\
47 # --tracker bug \\
48 # --allow-override tracker,priority
48 # --allow-override tracker,priority
49
49
50 require 'net/http'
50 require 'net/http'
51 require 'net/https'
51 require 'net/https'
52 require 'uri'
52 require 'uri'
53 require 'getoptlong'
53 require 'getoptlong'
54 require 'rdoc/usage'
54 require 'rdoc/usage'
55
55
56 module Net
56 module Net
57 class HTTPS < HTTP
57 class HTTPS < HTTP
58 def self.post_form(url, params)
58 def self.post_form(url, params)
59 request = Post.new(url.path)
59 request = Post.new(url.path)
60 request.form_data = params
60 request.form_data = params
61 request.basic_auth url.user, url.password if url.user
61 request.basic_auth url.user, url.password if url.user
62 http = new(url.host, url.port)
62 http = new(url.host, url.port)
63 http.use_ssl = (url.scheme == 'https')
63 http.use_ssl = (url.scheme == 'https')
64 http.start {|h| h.request(request) }
64 http.start {|h| h.request(request) }
65 end
65 end
66 end
66 end
67 end
67 end
68
68
69 class RedmineMailHandler
69 class RedmineMailHandler
70 VERSION = '0.1'
70 VERSION = '0.1'
71
71
72 attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :url, :key
72 attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :url, :key
73
73
74 def initialize
74 def initialize
75 self.issue_attributes = {}
75 self.issue_attributes = {}
76
76
77 opts = GetoptLong.new(
77 opts = GetoptLong.new(
78 [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
78 [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
79 [ '--version', '-V', GetoptLong::NO_ARGUMENT ],
79 [ '--version', '-V', GetoptLong::NO_ARGUMENT ],
80 [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
80 [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
81 [ '--url', '-u', GetoptLong::REQUIRED_ARGUMENT ],
81 [ '--url', '-u', GetoptLong::REQUIRED_ARGUMENT ],
82 [ '--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
82 [ '--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
83 [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
83 [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
84 [ '--status', '-s', GetoptLong::REQUIRED_ARGUMENT ],
84 [ '--status', '-s', GetoptLong::REQUIRED_ARGUMENT ],
85 [ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT],
85 [ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT],
86 [ '--category', GetoptLong::REQUIRED_ARGUMENT],
86 [ '--category', GetoptLong::REQUIRED_ARGUMENT],
87 [ '--priority', GetoptLong::REQUIRED_ARGUMENT],
87 [ '--priority', GetoptLong::REQUIRED_ARGUMENT],
88 [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT],
88 [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT],
89 [ '--unknown-user', GetoptLong::REQUIRED_ARGUMENT]
89 [ '--unknown-user', GetoptLong::REQUIRED_ARGUMENT]
90 )
90 )
91
91
92 opts.each do |opt, arg|
92 opts.each do |opt, arg|
93 case opt
93 case opt
94 when '--url'
94 when '--url'
95 self.url = arg.dup
95 self.url = arg.dup
96 when '--key'
96 when '--key'
97 self.key = arg.dup
97 self.key = arg.dup
98 when '--help'
98 when '--help'
99 usage
99 usage
100 when '--verbose'
100 when '--verbose'
101 self.verbose = true
101 self.verbose = true
102 when '--version'
102 when '--version'
103 puts VERSION; exit
103 puts VERSION; exit
104 when '--project', '--status', '--tracker', '--category', '--priority'
104 when '--project', '--status', '--tracker', '--category', '--priority'
105 self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
105 self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
106 when '--allow-override'
106 when '--allow-override'
107 self.allow_override = arg.dup
107 self.allow_override = arg.dup
108 when '--unknown-user'
108 when '--unknown-user'
109 self.unknown_user = arg.dup
109 self.unknown_user = arg.dup
110 end
110 end
111 end
111 end
112
112
113 RDoc.usage if url.nil?
113 RDoc.usage if url.nil?
114 end
114 end
115
115
116 def submit(email)
116 def submit(email)
117 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
117 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
118
118
119 data = { 'key' => key, 'email' => email,
119 data = { 'key' => key, 'email' => email,
120 'allow_override' => allow_override,
120 'allow_override' => allow_override,
121 'unknown_user' => unknown_user }
121 'unknown_user' => unknown_user }
122 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
122 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
123
123
124 debug "Posting to #{uri}..."
124 debug "Posting to #{uri}..."
125 response = Net::HTTPS.post_form(URI.parse(uri), data)
125 response = Net::HTTPS.post_form(URI.parse(uri), data)
126 debug "Response received: #{response.code}"
126 debug "Response received: #{response.code}"
127
127
128 puts "Request was denied by your Redmine server. " +
128 case response.code.to_i
129 "Please, make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key." if response.code == '403'
129 when 403
130 response.code == '201' ? 0 : 1
130 warn "Request was denied by your Redmine server. " +
131 "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
132 return 77
133 when 422
134 warn "Request was denied by your Redmine server. " +
135 "Possible reasons: email is sent from an invalid email address or is missing some information."
136 return 77
137 when 400..499
138 warn "Request was denied by your Redmine server (#{response.code})."
139 return 77
140 when 500..599
141 warn "Failed to contact your Redmine server (#{response.code})."
142 return 75
143 when 201
144 debug "Proccessed successfully"
145 return 0
146 else
147 return 1
148 end
131 end
149 end
132
150
133 private
151 private
134
152
135 def debug(msg)
153 def debug(msg)
136 puts msg if verbose
154 puts msg if verbose
137 end
155 end
138 end
156 end
139
157
140 handler = RedmineMailHandler.new
158 handler = RedmineMailHandler.new
141 handler.submit(STDIN.read)
159 exit(handler.submit(STDIN.read))
General Comments 0
You need to be logged in to leave comments. Login now