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