gitlab-mail-receiver 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +37 -10
- data/bin/gitlab-mail-receiver +2 -24
- data/lib/gitlab-mail-receiver.rb +6 -0
- data/lib/mail-receiver/cli.rb +55 -0
- data/lib/mail-receiver/daemon.rb +162 -0
- data/lib/mail-receiver/encoder.rb +16 -0
- data/lib/mail-receiver/receiver.rb +27 -13
- data/lib/mail-receiver/reply_to.rb +18 -26
- data/lib/mail-receiver/version.rb +7 -0
- metadata +37 -5
- data/lib/gitlab-mail-receiver/railtie.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 685533be718d29db08f1ba52b4b3118a166bc7d8
|
4
|
+
data.tar.gz: 85d33b4ce3c0ddbaaf1118ba95a7a82e211e6210
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29173d1720d26e9a9ca378e67c5b6fff0825b51e223093533b56eb56f5298602246ef9f3ecf6d336d9706c787ec17fab90275736ce05d678283e969ce4050390
|
7
|
+
data.tar.gz: a4583f133dd241987ec5cd66b108c567a306c433321d3e027843a4ac497a5e71f4e2bb2e312662ca7b4afe7fb6fde549a7b6ac7beca9774c38610c96a092135e
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# GitLab Mail Receiver
|
2
2
|
|
3
|
-
|
3
|
+
[](http://badge.fury.io/rb/gitlab-mail-receiver) [](https://travis-ci.org/huacnlee/gitlab-mail-receiver)
|
4
|
+
|
5
|
+
The way of allow your GitLab support Email receive and parse the email content, and find Issue/MergeRequest to create reply.
|
4
6
|
|
5
7
|
[中文介绍](https://ruby-china.org/topics/27143)
|
6
8
|
|
@@ -44,27 +46,52 @@ MailReceiver.configure do
|
|
44
46
|
self.sender = 'xxx@your-mail-host.com'
|
45
47
|
self.poll_interval = 5
|
46
48
|
self.imap = {
|
47
|
-
server: 'imap.your-mail-host.com'
|
48
|
-
port: 993
|
49
|
-
ssl: true
|
50
|
-
username: 'xxx@your-mail-host.com'
|
49
|
+
server: 'imap.your-mail-host.com',
|
50
|
+
port: 993,
|
51
|
+
ssl: true,
|
52
|
+
username: 'xxx@your-mail-host.com',
|
51
53
|
password: 'your-password'
|
52
54
|
}
|
53
55
|
end
|
54
56
|
```
|
55
57
|
|
56
|
-
## Run
|
58
|
+
## Run commands
|
57
59
|
|
58
60
|
```
|
59
61
|
$ cd gitlab
|
60
|
-
$ bundle exec gitlab-mail-receiver
|
62
|
+
$ bundle exec gitlab-mail-receiver -h
|
63
|
+
Commands:
|
64
|
+
gitlab-mail-receiver help [COMMAND] # Describe available commands or one specific command
|
65
|
+
gitlab-mail-receiver restart # Restart Daemon
|
66
|
+
gitlab-mail-receiver start # Start Daemon
|
67
|
+
gitlab-mail-receiver stop # Stop Daemon
|
68
|
+
gitlab-mail-receiver version # Show version
|
69
|
+
|
70
|
+
Options:
|
71
|
+
[--root=ROOT]
|
72
|
+
# Default: ./
|
73
|
+
$ bundle exec gitlab-mail-receiver start
|
74
|
+
Started gitlab-mail-receiver on pid: 59386
|
75
|
+
I, [2015-09-01T13:36:50.813124 #59387] INFO -- : Celluloid 0.17.1.2 is running in BACKPORTED mode. [ http://git.io/vJf3J ]
|
76
|
+
...
|
61
77
|
```
|
62
78
|
|
63
|
-
> NOTE: The daemon log will write to `$rails_root/log/gitlab-mail-receiver.log`
|
64
|
-
|
65
79
|
## Run in production
|
66
80
|
|
67
81
|
```
|
68
82
|
$ cd gitlab
|
69
|
-
$ RAILS_ENV=production
|
83
|
+
$ RAILS_ENV=production bundle exec gitlab-mail-receiver start -d
|
84
|
+
pid_file: ./tmp/pids/gitlab-mail-receiver.pid
|
85
|
+
log_file: ./log/gitlab-mail-receiver.log
|
86
|
+
Started gitlab-mail-receiver on pid: 58861
|
87
|
+
```
|
88
|
+
|
89
|
+
> NOTE: The daemon log will write to `$rails_root/log/gitlab-mail-receiver.log`
|
90
|
+
|
91
|
+
Stop daemon
|
92
|
+
|
93
|
+
```bash
|
94
|
+
$ bundle exec gitlab-mail-receiver stop
|
95
|
+
Stoping gitlab-mail-receiver... [OK]
|
96
|
+
```
|
70
97
|
```
|
data/bin/gitlab-mail-receiver
CHANGED
@@ -1,26 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require_relative '../lib/gitlab-mail-receiver'
|
2
|
+
require_relative '../lib/mail-receiver/cli'
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
begin
|
9
|
-
rails_env = ::File.expand_path('./config/environment', app_root)
|
10
|
-
require rails_env
|
11
|
-
rescue => e
|
12
|
-
puts "You need run this command under GitLab root."
|
13
|
-
return
|
14
|
-
end
|
15
|
-
|
16
|
-
logger = Logger.new(File.join(app_root, 'log/gitlab-mail-receiver.log'))
|
17
|
-
Mailman.config.logger = logger
|
18
|
-
Mailman.config.rails_root = app_root
|
19
|
-
|
20
|
-
logger.info "Starting Mailman ..."
|
21
|
-
Mailman::Application.run do
|
22
|
-
to '%user%+%suffix%@%host%' do
|
23
|
-
@receiver = MailReceiver::Receiver.new(message, logger: logger)
|
24
|
-
@receiver.process!
|
25
|
-
end
|
26
|
-
end
|
4
|
+
MailReceiver::CLI.start(ARGV)
|
data/lib/gitlab-mail-receiver.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require_relative './mail-receiver/encoder'
|
1
2
|
require_relative './mail-receiver/body_parser'
|
2
3
|
require_relative './mail-receiver/receiver'
|
3
4
|
require_relative './mail-receiver/reply_to'
|
5
|
+
|
4
6
|
require "mailman"
|
5
7
|
require 'active_support/core_ext'
|
6
8
|
|
@@ -15,6 +17,10 @@ end
|
|
15
17
|
Mailman::Configuration.send(:include, MailmanConfig)
|
16
18
|
|
17
19
|
module MailReceiver
|
20
|
+
def self.config
|
21
|
+
Mailman.config
|
22
|
+
end
|
23
|
+
|
18
24
|
def self.configure(&block)
|
19
25
|
Mailman.config.instance_exec(&block)
|
20
26
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative './daemon'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
module MailReceiver
|
5
|
+
class CLI < Thor
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
map '-v' => :version
|
9
|
+
map "s" => :start
|
10
|
+
class_option :root, type: :string, default: './'
|
11
|
+
|
12
|
+
option :daemon, type: :boolean, aliases: ['d'], default: false
|
13
|
+
desc "start", "Start Daemon"
|
14
|
+
def start
|
15
|
+
MailReceiver::Daemon.init(options) do
|
16
|
+
begin
|
17
|
+
rails_env = ::File.expand_path('./config/environment', options[:root])
|
18
|
+
require rails_env
|
19
|
+
rescue => e
|
20
|
+
puts "You need run this command under GitLab root."
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
Mailman.config.logger = Logger.new($stdout)
|
25
|
+
Mailman.config.rails_root = options[:root]
|
26
|
+
|
27
|
+
Mailman.config.logger.info "Starting gitlab-mail-receiver..."
|
28
|
+
Mailman::Application.run do
|
29
|
+
to '%user%+%suffix%@%host%' do
|
30
|
+
@receiver = MailReceiver::Receiver.new(message, logger: Mailman.config.logger)
|
31
|
+
@receiver.process!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
MailReceiver::Daemon.start_process
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "stop", "Stop Daemon"
|
39
|
+
def stop
|
40
|
+
MailReceiver::Daemon.init(options)
|
41
|
+
MailReceiver::Daemon.stop_process
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "restart", "Restart Daemon"
|
45
|
+
def restart
|
46
|
+
MailReceiver::Daemon.init(options)
|
47
|
+
MailReceiver::Daemon.restart_process
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "version", "Show version"
|
51
|
+
def version
|
52
|
+
puts "gitlab-mail-receiver #{MailReceiver.version}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# Daemon code from: https://github.com/huacnlee/sails
|
2
|
+
module MailReceiver
|
3
|
+
class Daemon
|
4
|
+
class << self
|
5
|
+
attr_accessor :options, :daemon, :mode, :app_name, :pid_file, :log_file, :runblock
|
6
|
+
|
7
|
+
def init(opts = {}, &block)
|
8
|
+
self.app_name = 'gitlab-mail-receiver'
|
9
|
+
self.pid_file = File.join(opts[:root], "tmp/pids/gitlab-mail-receiver.pid")
|
10
|
+
self.log_file = File.join(opts[:root], 'log/gitlab-mail-receiver.log')
|
11
|
+
self.daemon = opts[:daemon]
|
12
|
+
self.options = opts
|
13
|
+
self.runblock = block
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_pid
|
17
|
+
if !File.exist?(pid_file)
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
pid = File.open(pid_file).read.to_i
|
22
|
+
begin
|
23
|
+
Process.getpgid(pid)
|
24
|
+
rescue
|
25
|
+
pid = nil
|
26
|
+
end
|
27
|
+
pid
|
28
|
+
end
|
29
|
+
|
30
|
+
def start_process
|
31
|
+
old_pid = read_pid
|
32
|
+
if !old_pid.nil?
|
33
|
+
puts colorize("Current have #{app_name} process in running on pid #{old_pid}", :red)
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
# start master process
|
38
|
+
@master_pid = fork_master_process!
|
39
|
+
File.open(pid_file, "w+") do |f|
|
40
|
+
f.puts @master_pid
|
41
|
+
end
|
42
|
+
|
43
|
+
if self.daemon
|
44
|
+
puts "pid_file: #{self.pid_file}"
|
45
|
+
puts "log_file: #{self.log_file}"
|
46
|
+
end
|
47
|
+
puts "Started #{app_name} on pid: #{@master_pid}"
|
48
|
+
# puts "in init: #{Sails.service.object_id}"
|
49
|
+
|
50
|
+
if not self.daemon
|
51
|
+
Process.waitpid(@master_pid)
|
52
|
+
else
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def restart_process(options = {})
|
58
|
+
old_pid = read_pid
|
59
|
+
if old_pid == nil
|
60
|
+
puts colorize("#{app_name} process not found on pid #{old_pid}", :red)
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
print "Restarting #{app_name}..."
|
65
|
+
Process.kill("USR2", old_pid)
|
66
|
+
puts colorize(" [OK]", :green)
|
67
|
+
end
|
68
|
+
|
69
|
+
def fork_master_process!
|
70
|
+
fork do
|
71
|
+
# WARN: DO NOT CALL Sails IN THIS BLOCK!
|
72
|
+
$PROGRAM_NAME = self.app_name + " [master]"
|
73
|
+
@child_pid = fork_child_process!
|
74
|
+
|
75
|
+
Signal.trap("QUIT") do
|
76
|
+
Process.kill("QUIT", @child_pid)
|
77
|
+
exit
|
78
|
+
end
|
79
|
+
|
80
|
+
Signal.trap("USR2") do
|
81
|
+
Process.kill("USR2", @child_pid)
|
82
|
+
end
|
83
|
+
|
84
|
+
loop do
|
85
|
+
sleep 1
|
86
|
+
begin
|
87
|
+
Process.getpgid(@child_pid)
|
88
|
+
rescue Errno::ESRCH
|
89
|
+
@child_pid = fork_child_process!
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def fork_child_process!
|
96
|
+
pid = fork do
|
97
|
+
$PROGRAM_NAME = self.app_name + " [worker]"
|
98
|
+
Signal.trap("QUIT") do
|
99
|
+
exit
|
100
|
+
end
|
101
|
+
|
102
|
+
Signal.trap("USR2") do
|
103
|
+
# TODO: reload Sails in current process
|
104
|
+
exit
|
105
|
+
end
|
106
|
+
|
107
|
+
if self.daemon == true
|
108
|
+
redirect_stdout
|
109
|
+
end
|
110
|
+
|
111
|
+
# puts "in child: #{Sails.service.object_id}"
|
112
|
+
self.runblock.call
|
113
|
+
end
|
114
|
+
# http://ruby-doc.org/core-1.9.3/Process.html#detach-method
|
115
|
+
Process.detach(pid)
|
116
|
+
pid
|
117
|
+
end
|
118
|
+
|
119
|
+
def stop_process
|
120
|
+
pid = read_pid
|
121
|
+
if pid.nil?
|
122
|
+
puts colorize("#{app_name} process not found, pid #{pid}", :red)
|
123
|
+
return
|
124
|
+
end
|
125
|
+
|
126
|
+
print "Stoping #{app_name}..."
|
127
|
+
begin
|
128
|
+
Process.kill("QUIT", pid)
|
129
|
+
ensure
|
130
|
+
File.delete(pid_file)
|
131
|
+
end
|
132
|
+
puts colorize(" [OK]", :green)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
# Redirect stdout, stderr to log file,
|
137
|
+
# If we not do this, stdout will block sails daemon, for example `puts`.
|
138
|
+
def redirect_stdout
|
139
|
+
redirect_io($stdout, self.log_file)
|
140
|
+
redirect_io($stderr, self.log_file)
|
141
|
+
end
|
142
|
+
|
143
|
+
def redirect_io(io, path)
|
144
|
+
File.open(path, 'ab') { |fp| io.reopen(fp) } if path
|
145
|
+
io.sync = true
|
146
|
+
end
|
147
|
+
|
148
|
+
def colorize(text, c)
|
149
|
+
case c
|
150
|
+
when :red
|
151
|
+
return ["\033[31m",text,"\033[0m"].join("")
|
152
|
+
when :green
|
153
|
+
return ["\033[32m",text,"\033[0m"].join("")
|
154
|
+
when :blue
|
155
|
+
return ["\033[34m",text,"\033[0m"].join("")
|
156
|
+
else
|
157
|
+
return text
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
module MailReceiver
|
5
|
+
module Encoder
|
6
|
+
class << self
|
7
|
+
def encode(hash)
|
8
|
+
hash.to_query
|
9
|
+
end
|
10
|
+
|
11
|
+
def decode(query)
|
12
|
+
Rack::Utils.parse_query(query).deep_symbolize_keys
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -12,15 +12,19 @@ module MailReceiver
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def project_slug
|
15
|
-
|
15
|
+
hash_data[:p]
|
16
16
|
end
|
17
17
|
|
18
18
|
def issue_id
|
19
|
-
|
19
|
+
hash_data[:id]
|
20
|
+
end
|
21
|
+
|
22
|
+
def target_id
|
23
|
+
hash_data[:n]
|
20
24
|
end
|
21
25
|
|
22
26
|
def merge_request?
|
23
|
-
@merge_request ||=
|
27
|
+
@merge_request ||= hash_data[:t].downcase == 'm'
|
24
28
|
end
|
25
29
|
|
26
30
|
def body
|
@@ -42,14 +46,23 @@ module MailReceiver
|
|
42
46
|
@prefix ||= to.split('@').first
|
43
47
|
end
|
44
48
|
|
49
|
+
# foo+p=chair/chair&id=123 => { p: chair/chair, id: 123 }
|
50
|
+
def hash_data
|
51
|
+
return @hash_data if defined?(@hash_data)
|
52
|
+
return {} if not prefix.include?('+')
|
53
|
+
@hash_data = Encoder.decode(prefix.split('+').last)
|
54
|
+
return @hash_data
|
55
|
+
end
|
56
|
+
|
45
57
|
def inspect
|
46
|
-
{ project_slug: project_slug, issue_id: issue_id, merge_request: merge_request?, to: to, body: body}
|
58
|
+
{ project_slug: project_slug, issue_id: issue_id, target_id: target_id, merge_request: merge_request?, to: to, body: body}
|
47
59
|
end
|
48
60
|
|
49
61
|
def project
|
50
62
|
@project ||= Project.find_with_namespace(project_slug)
|
51
63
|
rescue => e
|
52
64
|
logger.warn "Project: #{project_slug} record not found."
|
65
|
+
nil
|
53
66
|
end
|
54
67
|
|
55
68
|
def process!
|
@@ -67,6 +80,16 @@ module MailReceiver
|
|
67
80
|
return if note_params.blank?
|
68
81
|
|
69
82
|
note_params[:project_id] = project.id
|
83
|
+
|
84
|
+
# relation to target Note
|
85
|
+
if target_id
|
86
|
+
target_note = project.notes.find_by_id(target_id)
|
87
|
+
if target_note
|
88
|
+
note_params[:commit_id] = target_note.commit_id
|
89
|
+
note_params[:line_code] = target_note.line_code
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
70
93
|
note_params[:note] = body
|
71
94
|
|
72
95
|
@note = Notes::CreateService.new(project, current_user, note_params).execute
|
@@ -99,17 +122,8 @@ module MailReceiver
|
|
99
122
|
@current_user ||= User.find_by_any_email(from)
|
100
123
|
end
|
101
124
|
|
102
|
-
private
|
103
|
-
|
104
125
|
def logger
|
105
126
|
@logger ||= Logger.new($stdout)
|
106
127
|
end
|
107
|
-
|
108
|
-
# foo+chair/chair!123 => chair/chair!123
|
109
|
-
def id_prefix
|
110
|
-
return @id_prefix if defined?(@id_prefix)
|
111
|
-
@id_prefix = prefix.split('+').last
|
112
|
-
return @id_prefix
|
113
|
-
end
|
114
128
|
end
|
115
129
|
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'mailman'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module MailReceiver
|
4
5
|
module ReplyTo
|
5
6
|
def mail_new_thread(model, headers = {}, &block)
|
6
|
-
headers['Message-ID'] = message_id(model)
|
7
|
-
headers['X-GitLab-Project'] = "#{@project.name} | " if @project
|
8
|
-
|
9
7
|
# Mail receiver
|
10
8
|
headers[:reply_to] = reply_to_address(model)
|
11
9
|
|
@@ -13,10 +11,6 @@ module MailReceiver
|
|
13
11
|
end
|
14
12
|
|
15
13
|
def mail_answer_thread(model, headers = {}, &block)
|
16
|
-
headers['In-Reply-To'] = message_id(model)
|
17
|
-
headers['References'] = message_id(model)
|
18
|
-
headers['X-GitLab-Project'] = "#{@project.name} | " if @project
|
19
|
-
|
20
14
|
if headers[:subject]
|
21
15
|
headers[:subject].prepend('Re: ')
|
22
16
|
end
|
@@ -29,39 +23,37 @@ module MailReceiver
|
|
29
23
|
|
30
24
|
protected
|
31
25
|
def reply_to_address(model)
|
32
|
-
|
33
|
-
return default_email_reply_to if
|
26
|
+
hash = convert_able(model)
|
27
|
+
return default_email_reply_to if hash.blank?
|
34
28
|
return default_email_reply_to if @project.blank?
|
35
29
|
|
36
|
-
slug = "#{@project.path_with_namespace}#{able_path}"
|
37
30
|
|
38
|
-
|
39
|
-
end
|
31
|
+
hash.merge!({ p: @project.path_with_namespace })
|
40
32
|
|
33
|
+
suffix = Encoder.encode(hash)
|
41
34
|
|
35
|
+
Mailman.config.sender.sub('@', "+#{suffix}@")
|
36
|
+
end
|
42
37
|
|
43
38
|
def default_email_reply_to
|
44
39
|
Gitlab.config.gitlab.email_reply_to
|
45
40
|
end
|
46
41
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
42
|
+
def convert_able(model)
|
43
|
+
res = { id: model.iid }
|
44
|
+
if defined?(@note)
|
45
|
+
# gitlab/app/mailers/emails/notes.rb 里面会声明 @note
|
46
|
+
res.merge!({ n: @note.id })
|
50
47
|
end
|
51
48
|
|
52
|
-
if model.class.name == '
|
53
|
-
|
49
|
+
if model.class.name == 'Issue'
|
50
|
+
res.merge({ t: 'i' })
|
51
|
+
return res
|
54
52
|
end
|
55
53
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
return "##{model.noteable.iid}"
|
60
|
-
end
|
61
|
-
|
62
|
-
if model.noteable_type == 'MergeRequest' && model.noteable
|
63
|
-
return "!#{model.noteable.iid}"
|
64
|
-
end
|
54
|
+
if model.class.name == 'MergeRequest'
|
55
|
+
res.merge({ t: 't' })
|
56
|
+
return res
|
65
57
|
end
|
66
58
|
|
67
59
|
return nil
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-mail-receiver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mailman
|
@@ -38,7 +38,36 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '4.0'
|
41
|
-
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rack
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.17.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.17.0
|
69
|
+
description: The way of allow your GitLab support Email receive and parse the email
|
70
|
+
content, and find Issue/MergeRequest to create reply.
|
42
71
|
email:
|
43
72
|
- huacnlee@gmail.com
|
44
73
|
executables:
|
@@ -50,10 +79,13 @@ files:
|
|
50
79
|
- README.md
|
51
80
|
- bin/gitlab-mail-receiver
|
52
81
|
- lib/gitlab-mail-receiver.rb
|
53
|
-
- lib/gitlab-mail-receiver/railtie.rb
|
54
82
|
- lib/mail-receiver/body_parser.rb
|
83
|
+
- lib/mail-receiver/cli.rb
|
84
|
+
- lib/mail-receiver/daemon.rb
|
85
|
+
- lib/mail-receiver/encoder.rb
|
55
86
|
- lib/mail-receiver/receiver.rb
|
56
87
|
- lib/mail-receiver/reply_to.rb
|
88
|
+
- lib/mail-receiver/version.rb
|
57
89
|
homepage: http://github.com/huacnlee/gitlab-mail-receiver
|
58
90
|
licenses:
|
59
91
|
- MIT
|
@@ -77,6 +109,6 @@ rubyforge_project:
|
|
77
109
|
rubygems_version: 2.4.7
|
78
110
|
signing_key:
|
79
111
|
specification_version: 4
|
80
|
-
summary: Allow your GitLab
|
112
|
+
summary: Allow your GitLab receive mails to create Issue comment
|
81
113
|
test_files: []
|
82
114
|
has_rdoc:
|