gitlab-mail-receiver 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/gitlab-mail-receiver.svg)](http://badge.fury.io/rb/gitlab-mail-receiver) [![CI Status](https://travis-ci.org/huacnlee/gitlab-mail-receiver.svg)](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:
|