discourse_mail_receiver 4.0.6 → 4.1.0
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 621926d0206bd4c21fc7e1c138ca3674154abba678c2e12f340391821c3232f3
|
4
|
+
data.tar.gz: 746ba23e178eb0b46f88827c6da15819a956576ff4fa91d344dcd429473a04e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85da9c1a37912f5962c9ca3b7f3f297818a4f95cba651855427c67007fa1f18b70ee52a43bc301ebfc4d5d2e7f37cf33cd1624ecd14fa0615dadd688c37e8ef6
|
7
|
+
data.tar.gz: 9dfae7da9939d77675cfad66aff9f3b732d09d3d5db3b9260b0093fbaedbb7cb7c59cf7ffaef5c43f336af083887a7b425dea3a604793aabc1c255d388afca8a
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "syslog"
|
3
|
+
require "json"
|
3
4
|
require "uri"
|
4
5
|
require "net/http"
|
5
|
-
require_relative
|
6
|
+
require_relative "mail_receiver_base"
|
6
7
|
|
7
8
|
class DiscourseMailReceiver < MailReceiverBase
|
8
|
-
|
9
9
|
def initialize(env_file = nil, recipient = nil, mail = nil)
|
10
10
|
super(env_file)
|
11
11
|
|
@@ -22,8 +22,8 @@ class DiscourseMailReceiver < MailReceiverBase
|
|
22
22
|
|
23
23
|
@endpoint = @env["DISCOURSE_MAIL_ENDPOINT"]
|
24
24
|
|
25
|
-
if @env[
|
26
|
-
@endpoint = "#{@env[
|
25
|
+
if @env["DISCOURSE_BASE_URL"]
|
26
|
+
@endpoint = "#{@env["DISCOURSE_BASE_URL"]}/admin/email/handle_mail"
|
27
27
|
end
|
28
28
|
@endpoint
|
29
29
|
end
|
@@ -54,5 +54,4 @@ class DiscourseMailReceiver < MailReceiverBase
|
|
54
54
|
logger.err "Failed to POST the e-mail to %s: %s", endpoint, response.code
|
55
55
|
:failure
|
56
56
|
end
|
57
|
-
|
58
57
|
end
|
@@ -1,21 +1,25 @@
|
|
1
|
-
|
2
|
-
require 'syslog'
|
3
|
-
require 'json'
|
4
|
-
require 'uri'
|
5
|
-
require 'cgi'
|
6
|
-
require 'net/http'
|
1
|
+
# frozen_string_literal: true
|
7
2
|
|
8
|
-
|
9
|
-
|
3
|
+
# rubocop:disable Lint/RedundantRequireStatement
|
4
|
+
# require "set" is needed for Set
|
5
|
+
require "set"
|
6
|
+
require "syslog"
|
7
|
+
require "json"
|
8
|
+
require "uri"
|
9
|
+
require "cgi"
|
10
|
+
require "net/http"
|
10
11
|
|
11
|
-
|
12
|
+
require_relative "mail"
|
13
|
+
require_relative "mail_receiver_base"
|
12
14
|
|
15
|
+
class FastRejection < MailReceiverBase
|
13
16
|
def initialize(env_file)
|
14
17
|
super(env_file)
|
15
18
|
|
16
|
-
@disabled = @env[
|
19
|
+
@disabled = @env["DISCOURSE_FAST_REJECTION_DISABLED"] || !@env["DISCOURSE_BASE_URL"]
|
17
20
|
|
18
|
-
@blacklisted_sender_domains =
|
21
|
+
@blacklisted_sender_domains =
|
22
|
+
Set.new(@env.fetch("BLACKLISTED_SENDER_DOMAINS", "").split(" ").map(&:downcase))
|
19
23
|
end
|
20
24
|
|
21
25
|
def disabled?
|
@@ -23,7 +27,7 @@ class FastRejection < MailReceiverBase
|
|
23
27
|
end
|
24
28
|
|
25
29
|
def process
|
26
|
-
$stdout.sync = true
|
30
|
+
$stdout.sync = true # unbuffered output
|
27
31
|
|
28
32
|
args = {}
|
29
33
|
while line = gets
|
@@ -31,29 +35,29 @@ class FastRejection < MailReceiverBase
|
|
31
35
|
line = line.chomp
|
32
36
|
if line.empty?
|
33
37
|
puts "action=#{process_single_request(args)}"
|
34
|
-
puts
|
38
|
+
puts ""
|
35
39
|
|
36
|
-
args = {}
|
40
|
+
args = {} # reset for next request.
|
37
41
|
else
|
38
|
-
k, v = line.chomp.split(
|
42
|
+
k, v = line.chomp.split("=", 2)
|
39
43
|
args[k] = v
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
43
47
|
|
44
48
|
def process_single_request(args)
|
45
|
-
return
|
49
|
+
return "dunno" if disabled?
|
46
50
|
|
47
|
-
if args[
|
48
|
-
return
|
49
|
-
elsif args[
|
50
|
-
return
|
51
|
-
elsif args[
|
51
|
+
if args["request"] != "smtpd_access_policy"
|
52
|
+
return "defer_if_permit Internal error, Request type invalid"
|
53
|
+
elsif args["protocol_state"] != "RCPT"
|
54
|
+
return "dunno"
|
55
|
+
elsif args["sender"].nil?
|
52
56
|
# Note that while this key should always exist, its value may be the empty
|
53
57
|
# string. Postfix will convert the "<>" null sender to "".
|
54
|
-
return
|
55
|
-
elsif args[
|
56
|
-
return
|
58
|
+
return "defer_if_permit No sender specified"
|
59
|
+
elsif args["recipient"].nil?
|
60
|
+
return "defer_if_permit No recipient specified"
|
57
61
|
end
|
58
62
|
|
59
63
|
run_filters(args)
|
@@ -61,8 +65,8 @@ class FastRejection < MailReceiverBase
|
|
61
65
|
|
62
66
|
def maybe_reject_email(from, to)
|
63
67
|
uri = URI.parse(endpoint)
|
64
|
-
fromarg = CGI
|
65
|
-
toarg = CGI
|
68
|
+
fromarg = CGI.escape(from)
|
69
|
+
toarg = CGI.escape(to)
|
66
70
|
|
67
71
|
qs = "from=#{fromarg}&to=#{toarg}"
|
68
72
|
if uri.query && !uri.query.empty?
|
@@ -79,7 +83,10 @@ class FastRejection < MailReceiverBase
|
|
79
83
|
get["Api-Key"] = key
|
80
84
|
response = http.request(get)
|
81
85
|
rescue StandardError => ex
|
82
|
-
logger.err "Failed to GET smtp_should_reject answer from %s: %s (%s)",
|
86
|
+
logger.err "Failed to GET smtp_should_reject answer from %s: %s (%s)",
|
87
|
+
endpoint,
|
88
|
+
ex.message,
|
89
|
+
ex.class
|
83
90
|
logger.err ex.backtrace.map { |l| " #{l}" }.join("\n")
|
84
91
|
return "defer_if_permit Internal error, API request preparation failed"
|
85
92
|
ensure
|
@@ -88,28 +95,23 @@ class FastRejection < MailReceiverBase
|
|
88
95
|
|
89
96
|
if Net::HTTPSuccess === response
|
90
97
|
reply = JSON.parse(response.body)
|
91
|
-
if reply[
|
92
|
-
return "reject #{reply['reason']}"
|
93
|
-
end
|
98
|
+
return "reject #{reply["reason"]}" if reply["reject"]
|
94
99
|
else
|
95
100
|
logger.err "Failed to GET smtp_should_reject answer from %s: %s", endpoint, response.code
|
96
101
|
return "defer_if_permit Internal error, API request failed"
|
97
102
|
end
|
98
103
|
|
99
|
-
"dunno"
|
104
|
+
"dunno" # let future tests also be allowed to reject this one.
|
100
105
|
end
|
101
106
|
|
102
107
|
def endpoint
|
103
|
-
"#{@env[
|
108
|
+
"#{@env["DISCOURSE_BASE_URL"]}/admin/email/smtp_should_reject.json"
|
104
109
|
end
|
105
110
|
|
106
111
|
private
|
107
112
|
|
108
113
|
def run_filters(args)
|
109
|
-
filters = [
|
110
|
-
:maybe_reject_by_sender_domain,
|
111
|
-
:maybe_reject_by_api,
|
112
|
-
]
|
114
|
+
filters = %i[maybe_reject_by_sender_domain maybe_reject_by_api]
|
113
115
|
|
114
116
|
filters.each do |f|
|
115
117
|
action = send(f, args)
|
@@ -120,25 +122,24 @@ class FastRejection < MailReceiverBase
|
|
120
122
|
end
|
121
123
|
|
122
124
|
def maybe_reject_by_sender_domain(args)
|
123
|
-
sender = args[
|
125
|
+
sender = args["sender"]
|
124
126
|
|
125
127
|
return "dunno" if sender.empty?
|
126
128
|
|
127
129
|
domain = domain_from_addrspec(sender)
|
128
130
|
if domain.empty?
|
129
131
|
logger.info("deferred mail with domainless sender #{sender}")
|
130
|
-
return
|
132
|
+
return "defer_if_permit Invalid sender"
|
131
133
|
end
|
132
134
|
if @blacklisted_sender_domains.include? domain
|
133
135
|
logger.info("rejected mail from blacklisted sender domain #{domain} (from #{sender})")
|
134
|
-
return
|
136
|
+
return "reject Invalid sender"
|
135
137
|
end
|
136
138
|
|
137
139
|
"dunno"
|
138
140
|
end
|
139
141
|
|
140
142
|
def maybe_reject_by_api(args)
|
141
|
-
maybe_reject_email(args[
|
143
|
+
maybe_reject_email(args["sender"], args["recipient"])
|
142
144
|
end
|
143
|
-
|
144
145
|
end
|
data/lib/mail_receiver/mail.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class MailReceiverBase
|
2
|
-
class ReceiverException < StandardError
|
3
|
+
class ReceiverException < StandardError
|
4
|
+
end
|
3
5
|
|
4
6
|
attr_reader :env
|
5
7
|
|
6
8
|
def initialize(env_file)
|
7
|
-
unless File.
|
8
|
-
fatal "Config file %s does not exist. Aborting.", env_file
|
9
|
-
end
|
9
|
+
fatal "Config file %s does not exist. Aborting.", env_file unless File.exist?(env_file)
|
10
10
|
|
11
11
|
@env = JSON.parse(File.read(env_file))
|
12
12
|
|
13
|
-
%w
|
13
|
+
%w[DISCOURSE_API_KEY DISCOURSE_API_USERNAME].each do |kw|
|
14
14
|
fatal "env var %s is required", kw unless @env[kw]
|
15
15
|
end
|
16
16
|
|
17
|
-
if @env[
|
17
|
+
if @env["DISCOURSE_MAIL_ENDPOINT"].nil? && @env["DISCOURSE_BASE_URL"].nil?
|
18
18
|
fatal "DISCOURSE_MAIL_ENDPOINT and DISCOURSE_BASE_URL env var missing"
|
19
19
|
end
|
20
20
|
end
|
@@ -28,11 +28,11 @@ class MailReceiverBase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def key
|
31
|
-
@env[
|
31
|
+
@env["DISCOURSE_API_KEY"]
|
32
32
|
end
|
33
33
|
|
34
34
|
def username
|
35
|
-
@env[
|
35
|
+
@env["DISCOURSE_API_USERNAME"]
|
36
36
|
end
|
37
37
|
|
38
38
|
def fatal(*args)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: discourse_mail_receiver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Discourse Team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mail
|
@@ -25,33 +25,89 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 2.7.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: net-smtp
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
33
|
+
version: 0.3.3
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-discourse
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: syntax_tree
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: syntax_tree-disable_ternary
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
53
109
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
110
|
+
version: '0'
|
55
111
|
description: A gem used to package the core .rb files of the mail-receiver.
|
56
112
|
email:
|
57
113
|
- team@discourse.org
|
@@ -67,7 +123,7 @@ homepage: https://github.com/discourse/mail-receiver
|
|
67
123
|
licenses:
|
68
124
|
- MIT
|
69
125
|
metadata: {}
|
70
|
-
post_install_message:
|
126
|
+
post_install_message:
|
71
127
|
rdoc_options: []
|
72
128
|
require_paths:
|
73
129
|
- lib
|
@@ -75,15 +131,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
131
|
requirements:
|
76
132
|
- - ">="
|
77
133
|
- !ruby/object:Gem::Version
|
78
|
-
version:
|
134
|
+
version: 3.0.0
|
79
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
136
|
requirements:
|
81
137
|
- - ">="
|
82
138
|
- !ruby/object:Gem::Version
|
83
139
|
version: '0'
|
84
140
|
requirements: []
|
85
|
-
rubygems_version: 3.
|
86
|
-
signing_key:
|
141
|
+
rubygems_version: 3.5.11
|
142
|
+
signing_key:
|
87
143
|
specification_version: 4
|
88
144
|
summary: A gem used to package the core .rb files of the mail-receiver.
|
89
145
|
test_files: []
|