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 / extra / mail_handler / rdm-mailhandler.rb @ 441:cbce1fd3b1b7

History | View | Annotate | Download (5.78 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
#   -h, --help                     show this help
26
#   -v, --verbose                  show extra information
27
#   -V, --version                  show version information and exit
28
# 
29
# Issue attributes control options:
30
#   -p, --project=PROJECT          identifier of the target project
31
#   -s, --status=STATUS            name of the target status
32
#   -t, --tracker=TRACKER          name of the target tracker
33
#       --category=CATEGORY        name of the target category
34
#       --priority=PRIORITY        name of the target priority
35
#   -o, --allow-override=ATTRS     allow email content to override attributes
36
#                                  specified by previous options
37
#                                  ATTRS is a comma separated list of attributes
38
#       
39
# == Examples
40
# No project specified. Emails MUST contain the 'Project' keyword:
41
# 
42
#   rdm-mailhandler --url http://redmine.domain.foo --key secret
43
#   
44
# Fixed project and default tracker specified, but emails can override
45
# both tracker and priority attributes using keywords:
46
# 
47
#   rdm-mailhandler --url https://domain.foo/redmine --key secret \\
48
#                   --project foo \\
49
#                   --tracker bug \\
50
#                   --allow-override tracker,priority
51

    
52
require 'net/http'
53
require 'net/https'
54
require 'uri'
55
require 'getoptlong'
56
require 'rdoc/usage'
57

    
58
module Net
59
  class HTTPS < HTTP
60
    def self.post_form(url, params, headers)
61
      request = Post.new(url.path)
62
      request.form_data = params
63
      request.basic_auth url.user, url.password if url.user
64
      request.initialize_http_header(headers)
65
      http = new(url.host, url.port)
66
      http.use_ssl = (url.scheme == 'https')
67
      http.start {|h| h.request(request) }
68
    end
69
  end
70
end
71

    
72
class RedmineMailHandler
73
  VERSION = '0.1'
74
  
75
  attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :no_permission_check, :url, :key
76

    
77
  def initialize
78
    self.issue_attributes = {}
79
    
80
    opts = GetoptLong.new(
81
      [ '--help',           '-h', GetoptLong::NO_ARGUMENT ],
82
      [ '--version',        '-V', GetoptLong::NO_ARGUMENT ],
83
      [ '--verbose',        '-v', GetoptLong::NO_ARGUMENT ],
84
      [ '--url',            '-u', GetoptLong::REQUIRED_ARGUMENT ],
85
      [ '--key',            '-k', GetoptLong::REQUIRED_ARGUMENT],
86
      [ '--project',        '-p', GetoptLong::REQUIRED_ARGUMENT ],
87
      [ '--status',         '-s', GetoptLong::REQUIRED_ARGUMENT ],
88
      [ '--tracker',        '-t', GetoptLong::REQUIRED_ARGUMENT],
89
      [ '--category',             GetoptLong::REQUIRED_ARGUMENT],
90
      [ '--priority',             GetoptLong::REQUIRED_ARGUMENT],
91
      [ '--allow-override', '-o', GetoptLong::REQUIRED_ARGUMENT],
92
      [ '--unknown-user',         GetoptLong::REQUIRED_ARGUMENT],
93
      [ '--no-permission-check',  GetoptLong::NO_ARGUMENT]
94
    )
95

    
96
    opts.each do |opt, arg|
97
      case opt
98
      when '--url'
99
        self.url = arg.dup
100
      when '--key'
101
        self.key = arg.dup
102
      when '--help'
103
        usage
104
      when '--verbose'
105
        self.verbose = true
106
      when '--version'
107
        puts VERSION; exit
108
      when '--project', '--status', '--tracker', '--category', '--priority'
109
        self.issue_attributes[opt.gsub(%r{^\-\-}, '')] = arg.dup
110
      when '--allow-override'
111
        self.allow_override = arg.dup
112
      when '--unknown-user'
113
        self.unknown_user = arg.dup
114
      when '--no-permission-check'
115
        self.no_permission_check = '1'
116
      end
117
    end
118
    
119
    RDoc.usage if url.nil?
120
  end
121
  
122
  def submit(email)
123
    uri = url.gsub(%r{/*$}, '') + '/mail_handler'
124
    
125
    headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
126
    
127
    data = { 'key' => key, 'email' => email, 
128
                           'allow_override' => allow_override,
129
                           'unknown_user' => unknown_user,
130
                           'no_permission_check' => no_permission_check}
131
    issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
132
             
133
    debug "Posting to #{uri}..."
134
    response = Net::HTTPS.post_form(URI.parse(uri), data, headers)
135
    debug "Response received: #{response.code}"
136
    
137
    case response.code.to_i
138
      when 403
139
        warn "Request was denied by your Redmine server. " + 
140
             "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
141
        return 77
142
      when 422
143
        warn "Request was denied by your Redmine server. " +
144
             "Possible reasons: email is sent from an invalid email address or is missing some information."
145
        return 77
146
      when 400..499
147
        warn "Request was denied by your Redmine server (#{response.code})."
148
        return 77
149
      when 500..599
150
        warn "Failed to contact your Redmine server (#{response.code})."
151
        return 75
152
      when 201
153
        debug "Proccessed successfully"
154
        return 0
155
      else
156
        return 1
157
    end
158
  end
159
  
160
  private
161
  
162
  def debug(msg)
163
    puts msg if verbose
164
  end
165
end
166

    
167
handler = RedmineMailHandler.new
168
exit(handler.submit(STDIN.read))