##// END OF EJS Templates
Adds --status option to rdm-mailhandler....
Jean-Philippe Lang -
r2074:94899e0339f1
parent child
Show More
@@ -1,129 +1,131
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 # -h, --help show this help
18 # -h, --help show this help
19 # -v, --verbose show extra information
19 # -v, --verbose show extra information
20 # -V, --version show version information and exit
20 # -V, --version show version information and exit
21 #
21 #
22 # Issue attributes control options:
22 # Issue attributes control options:
23 # -p, --project=PROJECT identifier of the target project
23 # -p, --project=PROJECT identifier of the target project
24 # -s, --status=STATUS name of the target status
24 # -t, --tracker=TRACKER name of the target tracker
25 # -t, --tracker=TRACKER name of the target tracker
25 # --category=CATEGORY name of the target category
26 # --category=CATEGORY name of the target category
26 # --priority=PRIORITY name of the target priority
27 # --priority=PRIORITY name of the target priority
27 # -o, --allow-override=ATTRS allow email content to override attributes
28 # -o, --allow-override=ATTRS allow email content to override attributes
28 # specified by previous options
29 # specified by previous options
29 # ATTRS is a comma separated list of attributes
30 # ATTRS is a comma separated list of attributes
30 #
31 #
31 # == Examples
32 # == Examples
32 # No project specified. Emails MUST contain the 'Project' keyword:
33 # No project specified. Emails MUST contain the 'Project' keyword:
33 #
34 #
34 # rdm-mailhandler --url http://redmine.domain.foo --key secret
35 # rdm-mailhandler --url http://redmine.domain.foo --key secret
35 #
36 #
36 # Fixed project and default tracker specified, but emails can override
37 # Fixed project and default tracker specified, but emails can override
37 # both tracker and priority attributes using keywords:
38 # both tracker and priority attributes using keywords:
38 #
39 #
39 # rdm-mailhandler --url https://domain.foo/redmine --key secret \\
40 # rdm-mailhandler --url https://domain.foo/redmine --key secret \\
40 # --project foo \\
41 # --project foo \\
41 # --tracker bug \\
42 # --tracker bug \\
42 # --allow-override tracker,priority
43 # --allow-override tracker,priority
43
44
44 require 'net/http'
45 require 'net/http'
45 require 'net/https'
46 require 'net/https'
46 require 'uri'
47 require 'uri'
47 require 'getoptlong'
48 require 'getoptlong'
48 require 'rdoc/usage'
49 require 'rdoc/usage'
49
50
50 module Net
51 module Net
51 class HTTPS < HTTP
52 class HTTPS < HTTP
52 def self.post_form(url, params)
53 def self.post_form(url, params)
53 request = Post.new(url.path)
54 request = Post.new(url.path)
54 request.form_data = params
55 request.form_data = params
55 request.basic_auth url.user, url.password if url.user
56 request.basic_auth url.user, url.password if url.user
56 http = new(url.host, url.port)
57 http = new(url.host, url.port)
57 http.use_ssl = (url.scheme == 'https')
58 http.use_ssl = (url.scheme == 'https')
58 http.start {|h| h.request(request) }
59 http.start {|h| h.request(request) }
59 end
60 end
60 end
61 end
61 end
62 end
62
63
63 class RedmineMailHandler
64 class RedmineMailHandler
64 VERSION = '0.1'
65 VERSION = '0.1'
65
66
66 attr_accessor :verbose, :issue_attributes, :allow_override, :url, :key
67 attr_accessor :verbose, :issue_attributes, :allow_override, :url, :key
67
68
68 def initialize
69 def initialize
69 self.issue_attributes = {}
70 self.issue_attributes = {}
70
71
71 opts = GetoptLong.new(
72 opts = GetoptLong.new(
72 [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
73 [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
73 [ '--version', '-V', GetoptLong::NO_ARGUMENT ],
74 [ '--version', '-V', GetoptLong::NO_ARGUMENT ],
74 [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
75 [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ],
75 [ '--url', '-u', GetoptLong::REQUIRED_ARGUMENT ],
76 [ '--url', '-u', GetoptLong::REQUIRED_ARGUMENT ],
76 [ '--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
77 [ '--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
77 [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
78 [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ],
79 [ '--status', '-s', GetoptLong::REQUIRED_ARGUMENT ],
78 [ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT],
80 [ '--tracker', '-t', GetoptLong::REQUIRED_ARGUMENT],
79 [ '--category', GetoptLong::REQUIRED_ARGUMENT],
81 [ '--category', GetoptLong::REQUIRED_ARGUMENT],
80 [ '--priority', GetoptLong::REQUIRED_ARGUMENT],
82 [ '--priority', GetoptLong::REQUIRED_ARGUMENT],
81 [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT]
83 [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT]
82 )
84 )
83
85
84 opts.each do |opt, arg|
86 opts.each do |opt, arg|
85 case opt
87 case opt
86 when '--url'
88 when '--url'
87 self.url = arg.dup
89 self.url = arg.dup
88 when '--key'
90 when '--key'
89 self.key = arg.dup
91 self.key = arg.dup
90 when '--help'
92 when '--help'
91 usage
93 usage
92 when '--verbose'
94 when '--verbose'
93 self.verbose = true
95 self.verbose = true
94 when '--version'
96 when '--version'
95 puts VERSION; exit
97 puts VERSION; exit
96 when '--project', '--tracker', '--category', '--priority'
98 when '--project', '--status', '--tracker', '--category', '--priority'
97 self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
99 self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
98 when '--allow-override'
100 when '--allow-override'
99 self.allow_override = arg.dup
101 self.allow_override = arg.dup
100 end
102 end
101 end
103 end
102
104
103 RDoc.usage if url.nil?
105 RDoc.usage if url.nil?
104 end
106 end
105
107
106 def submit(email)
108 def submit(email)
107 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
109 uri = url.gsub(%r{/*$}, '') + '/mail_handler'
108
110
109 data = { 'key' => key, 'email' => email, 'allow_override' => allow_override }
111 data = { 'key' => key, 'email' => email, 'allow_override' => allow_override }
110 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
112 issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
111
113
112 debug "Posting to #{uri}..."
114 debug "Posting to #{uri}..."
113 response = Net::HTTPS.post_form(URI.parse(uri), data)
115 response = Net::HTTPS.post_form(URI.parse(uri), data)
114 debug "Response received: #{response.code}"
116 debug "Response received: #{response.code}"
115
117
116 puts "Request was denied by your Redmine server. " +
118 puts "Request was denied by your Redmine server. " +
117 "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'
119 "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'
118 response.code == '201' ? 0 : 1
120 response.code == '201' ? 0 : 1
119 end
121 end
120
122
121 private
123 private
122
124
123 def debug(msg)
125 def debug(msg)
124 puts msg if verbose
126 puts msg if verbose
125 end
127 end
126 end
128 end
127
129
128 handler = RedmineMailHandler.new
130 handler = RedmineMailHandler.new
129 handler.submit(STDIN.read)
131 handler.submit(STDIN.read)
General Comments 0
You need to be logged in to leave comments. Login now