To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 73 / 734f23aed8fb2921f077702e98029d9edca35572.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (6.7 KB)

1
#!/usr/bin/env ruby
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'
58
require 'net/https'
59
require 'uri'
60
require 'getoptlong'
61
require 'rdoc/usage'
62

    
63
module Net
64
  class HTTPS < HTTP
65
    def self.post_form(url, params, headers, options={})
66
      request = Post.new(url.path)
67
      request.form_data = params
68
      request.basic_auth url.user, url.password if url.user
69
      request.initialize_http_header(headers)
70
      http = new(url.host, url.port)
71
      http.use_ssl = (url.scheme == 'https')
72
      if options[:no_check_certificate]
73
        http.verify_mode = OpenSSL::SSL::VERIFY_NONE
74
      end
75
      http.start {|h| h.request(request) }
76
    end
77
  end
78
end
79

    
80
class RedmineMailHandler
81
  VERSION = '0.1'
82
  
83
  attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :no_permission_check, :url, :key, :no_check_certificate
84

    
85
  def initialize
86
    self.issue_attributes = {}
87
    
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
136
    end
137
    
138
    RDoc.usage if url.nil?
139
  end
140
  
141
  def submit(email)
142
    uri = url.gsub(%r{/*$}, '') + '/mail_handler'
143
    
144
    headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
145
    
146
    data = { 'key' => key, 'email' => email, 
147
                           'allow_override' => allow_override,
148
                           'unknown_user' => unknown_user,
149
                           'no_permission_check' => no_permission_check}
150
    issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
151
             
152
    debug "Posting to #{uri}..."
153
    response = Net::HTTPS.post_form(URI.parse(uri), data, headers, :no_check_certificate => no_check_certificate)
154
    debug "Response received: #{response.code}"
155
    
156
    case response.code.to_i
157
      when 403
158
        warn "Request was denied by your Redmine server. " + 
159
             "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
160
        return 77
161
      when 422
162
        warn "Request was denied by your Redmine server. " +
163
             "Possible reasons: email is sent from an invalid email address or is missing some information."
164
        return 77
165
      when 400..499
166
        warn "Request was denied by your Redmine server (#{response.code})."
167
        return 77
168
      when 500..599
169
        warn "Failed to contact your Redmine server (#{response.code})."
170
        return 75
171
      when 201
172
        debug "Proccessed successfully"
173
        return 0
174
      else
175
        return 1
176
    end
177
  end
178
  
179
  private
180
  
181
  def debug(msg)
182
    puts msg if verbose
183
  end
184
end
185

    
186
handler = RedmineMailHandler.new
187
exit(handler.submit(STDIN.read))