sanitize_email 2.0.3 → 2.0.5
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +97 -12
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +47 -0
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +415 -59
- data/SECURITY.md +15 -0
- data/lib/sanitize_email/bleach.rb +75 -68
- data/lib/sanitize_email/config.rb +22 -22
- data/lib/sanitize_email/deprecation.rb +6 -6
- data/lib/sanitize_email/{engine.rb → engine_v5.rb} +4 -3
- data/lib/sanitize_email/engine_v6.rb +15 -0
- data/lib/sanitize_email/mail_ext.rb +2 -0
- data/lib/sanitize_email/mail_header_tools.rb +24 -16
- data/lib/sanitize_email/overridden_addresses.rb +84 -22
- data/lib/sanitize_email/railtie.rb +1 -1
- data/lib/sanitize_email/rspec_matchers.rb +66 -31
- data/lib/sanitize_email/test_helpers.rb +6 -6
- data/lib/sanitize_email/version.rb +4 -2
- data/lib/sanitize_email.rb +35 -19
- data.tar.gz.sig +0 -0
- metadata +108 -93
- metadata.gz.sig +0 -0
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -12
- data/.pryrc +0 -11
- data/.reek +0 -9
- data/.rspec +0 -2
- data/.rubocop.yml +0 -73
- data/.rubocop_rspec.yml +0 -35
- data/.rubocop_todo.yml +0 -21
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/.travis.yml +0 -71
- data/Appraisals +0 -29
- data/Gemfile +0 -22
- data/REEK +0 -2
- data/Rakefile +0 -52
- data/gemfiles/rails_4_2.gemfile +0 -17
- data/gemfiles/rails_5_0.gemfile +0 -17
- data/gemfiles/rails_5_1.gemfile +0 -17
- data/gemfiles/rails_5_2.gemfile +0 -17
- data/init.rb +0 -3
- data/sanitize_email.gemspec +0 -49
- data/spec/sanitize_email_spec.rb +0 -944
- data/spec/spec_helper.rb +0 -28
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
6
|
module SanitizeEmail
|
@@ -10,82 +10,89 @@ module SanitizeEmail
|
|
10
10
|
extend SanitizeEmail::Deprecation
|
11
11
|
attr_accessor :overridden_addresses # TODO: Just a stub, not implemented
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
class << self
|
14
|
+
# If all recipient addresses are allow-listed the field is left alone.
|
15
|
+
def delivering_email(message)
|
16
|
+
return unless sanitize_engaged?(message)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
add_original_addresses_as_headers(message)
|
22
|
-
SanitizeEmail::MailHeaderTools.
|
23
|
-
prepend_custom_subject(message)
|
18
|
+
SanitizeEmail::MailHeaderTools
|
19
|
+
.add_original_addresses_as_headers(message)
|
20
|
+
SanitizeEmail::MailHeaderTools
|
21
|
+
.prepend_custom_subject(message)
|
24
22
|
|
25
|
-
|
23
|
+
overridden = SanitizeEmail::OverriddenAddresses.new(message)
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
message.to = overridden.overridden_to
|
26
|
+
message.cc = overridden.overridden_cc
|
27
|
+
message.bcc = overridden.overridden_bcc
|
28
|
+
|
29
|
+
return if message["personalizations"].nil?
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
# in order of precedence they are:
|
35
|
-
#
|
36
|
-
# 1. SanitizeEmail.force_sanitize = true # by default it is nil
|
37
|
-
# Only useful for local context.
|
38
|
-
# Inside a method where you will be sending an email, set
|
39
|
-
#
|
40
|
-
# SanitizeEmail.force_sanitize = true
|
41
|
-
#
|
42
|
-
# just prior to delivering it. Also useful in the console.
|
43
|
-
#
|
44
|
-
# 2. If SanitizeEmail seems to not be sanitizing,
|
45
|
-
# you have probably not registered the interceptor.
|
46
|
-
# SanitizeEmail tries to do this for you.
|
47
|
-
# *Note*: If you are working in an environment that has
|
48
|
-
# a Mail or Mailer class that uses the register_interceptor API,
|
49
|
-
# the interceptor will already have been registered.
|
50
|
-
# The gem will probably have already done this for you,
|
51
|
-
# but some really old versions of Rails may need you to do this manually:
|
52
|
-
#
|
53
|
-
# Mail.register_interceptor(SanitizeEmail::Bleach)
|
54
|
-
#
|
55
|
-
# Once registered, SanitizeEmail needs to be engaged:
|
56
|
-
#
|
57
|
-
# # in config/initializers/sanitize_email.rb
|
58
|
-
# SanitizeEmail::Config.configure {|config| config[:engage] = true }
|
59
|
-
#
|
60
|
-
# 3. SanitizeEmail::Config.configure do |config|
|
61
|
-
# config[:activation_proc] = Proc.new { true }
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# If you don't need to compute anything,
|
65
|
-
# then don't use the Proc, go with the previous option.
|
66
|
-
#
|
67
|
-
# Note: Number 1 is the method used by the SanitizeEmail.sanitary block
|
68
|
-
# Note: Number 2 You may need to setup your own register_interceptor
|
69
|
-
#
|
70
|
-
# If installed but not configured, sanitize_email DOES NOTHING.
|
71
|
-
# Until configured the defaults leave it turned off.
|
72
|
-
def self.sanitize_engaged?(message)
|
73
|
-
# Don't sanitize the message if it will not be delivered
|
74
|
-
return false unless message.perform_deliveries
|
31
|
+
message["personalizations"].value = overridden.overridden_personalizations
|
32
|
+
end
|
75
33
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
34
|
+
# Will be called by the Hook to determine if an override should occur
|
35
|
+
# There are three ways SanitizeEmail can be turned on;
|
36
|
+
# in order of precedence they are:
|
37
|
+
#
|
38
|
+
# 1. SanitizeEmail.force_sanitize = true # by default it is nil
|
39
|
+
# Only useful for local context.
|
40
|
+
# Inside a method where you will be sending an email, set
|
41
|
+
#
|
42
|
+
# SanitizeEmail.force_sanitize = true
|
43
|
+
#
|
44
|
+
# just prior to delivering it. Also useful in the console.
|
45
|
+
#
|
46
|
+
# 2. If SanitizeEmail seems to not be sanitizing,
|
47
|
+
# you have probably not registered the interceptor.
|
48
|
+
# SanitizeEmail tries to do this for you.
|
49
|
+
# *Note*: If you are working in an environment that has
|
50
|
+
# a Mail or Mailer class that uses the register_interceptor API,
|
51
|
+
# the interceptor will already have been registered.
|
52
|
+
# The gem will probably have already done this for you,
|
53
|
+
# but some really old versions of Rails may need you to do this manually:
|
54
|
+
#
|
55
|
+
# Mail.register_interceptor(SanitizeEmail::Bleach)
|
56
|
+
#
|
57
|
+
# Once registered, SanitizeEmail needs to be engaged:
|
58
|
+
#
|
59
|
+
# # in config/initializers/sanitize_email.rb
|
60
|
+
# SanitizeEmail::Config.configure {|config| config[:engage] = true }
|
61
|
+
#
|
62
|
+
# 3. SanitizeEmail::Config.configure do |config|
|
63
|
+
# config[:activation_proc] = Proc.new { true }
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# If you don't need to compute anything,
|
67
|
+
# then don't use the Proc, go with the previous option.
|
68
|
+
#
|
69
|
+
# Note: Number 1 is the method used by the SanitizeEmail.sanitary block
|
70
|
+
# Note: Number 2 You may need to setup your own register_interceptor
|
71
|
+
#
|
72
|
+
# If installed but not configured, sanitize_email DOES NOTHING.
|
73
|
+
# Until configured the defaults leave it turned off.
|
74
|
+
def sanitize_engaged?(message)
|
75
|
+
# Don't sanitize the message if it will not be delivered
|
76
|
+
return false unless message.perform_deliveries
|
79
77
|
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
# Has it been forced via the force_sanitize mattr?
|
79
|
+
forced = SanitizeEmail.force_sanitize
|
80
|
+
return forced unless forced.nil?
|
83
81
|
|
84
|
-
|
85
|
-
|
82
|
+
# Is this particular instance of Bleach engaged
|
83
|
+
engaged = SanitizeEmail::Config.config[:engage]
|
84
|
+
return engaged unless engaged.nil?
|
85
|
+
|
86
|
+
# Should we sanitize due to the activation_proc?
|
87
|
+
SanitizeEmail.activate?(message)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def initialize(*args)
|
92
|
+
deprecation_message unless args.empty?
|
86
93
|
end
|
87
94
|
|
88
|
-
|
95
|
+
private
|
89
96
|
|
90
97
|
def deprecation_message
|
91
98
|
deprecation = <<~DEPRECATION
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
6
|
module SanitizeEmail
|
@@ -16,48 +16,48 @@ module SanitizeEmail
|
|
16
16
|
DEFAULTS = {
|
17
17
|
# Specify the BCC addresses for the messages
|
18
18
|
# that go out in "local" environments
|
19
|
-
:
|
19
|
+
sanitized_bcc: nil,
|
20
20
|
|
21
21
|
# Specify the CC addresses for the messages
|
22
22
|
# that go out in "local" environments
|
23
|
-
:
|
23
|
+
sanitized_cc: nil,
|
24
24
|
|
25
25
|
# The recipient addresses for the messages,
|
26
26
|
# either as a string (for a single address)
|
27
27
|
# or an array (for multiple addresses)
|
28
28
|
# that go out in "local" environments
|
29
|
-
:
|
29
|
+
sanitized_to: nil,
|
30
30
|
|
31
|
-
#
|
32
|
-
:
|
31
|
+
# an allow list
|
32
|
+
good_list: nil,
|
33
33
|
|
34
|
-
# a
|
35
|
-
:
|
34
|
+
# a block list
|
35
|
+
bad_list: nil,
|
36
36
|
|
37
|
-
:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
environment: if defined?(Rails) && Rails.env.present?
|
38
|
+
"[#{Rails.env}]"
|
39
|
+
else
|
40
|
+
"[UNKNOWN ENVIRONMENT]"
|
41
|
+
end,
|
42
42
|
|
43
43
|
# Use the "real" email address as the username
|
44
44
|
# for the sanitized email address
|
45
|
-
# e.g. "real
|
46
|
-
:
|
45
|
+
# e.g. "real at example.com <sanitized@example.com>"
|
46
|
+
use_actual_email_as_sanitized_user_name: false,
|
47
47
|
|
48
48
|
# Prepend the "real" email address onto the Subject line of the message
|
49
|
-
# e.g. "real
|
50
|
-
:
|
49
|
+
# e.g. "real at example.com rest of subject"
|
50
|
+
use_actual_email_prepended_to_subject: false,
|
51
51
|
|
52
52
|
# Prepend the Rails environment onto the Subject line of the message
|
53
53
|
# e.g. "[development] rest of subject"
|
54
|
-
:
|
54
|
+
use_actual_environment_prepended_to_subject: false,
|
55
55
|
|
56
56
|
# True / False turns on or off sanitization,
|
57
57
|
# while nil ignores this setting and checks activation_proc
|
58
|
-
:
|
58
|
+
engage: nil,
|
59
59
|
|
60
|
-
:
|
60
|
+
activation_proc: proc { false },
|
61
61
|
}.freeze
|
62
62
|
|
63
63
|
@config ||= DEFAULTS.dup
|
@@ -83,9 +83,9 @@ module SanitizeEmail
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def self.config_force_sanitize_deprecation_warning
|
86
|
-
return
|
86
|
+
return if @config[:force_sanitize].nil?
|
87
87
|
deprecation_warning_message(
|
88
|
-
<<-DEPRECATION
|
88
|
+
<<-DEPRECATION,
|
89
89
|
SanitizeEmail::Config.config[:force_sanitize] is deprecated.
|
90
90
|
Please use SanitizeEmail.force_sanitize or SanitizeEmail.sanitary instead.
|
91
91
|
Refer to https://github.com/pboling/sanitize_email/wiki for examples.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
6
|
module SanitizeEmail
|
@@ -19,8 +19,8 @@ module SanitizeEmail
|
|
19
19
|
def deprecated_alias(name, replacement)
|
20
20
|
# Create a wrapped version
|
21
21
|
define_method(name) do |*args, &block|
|
22
|
-
warn
|
23
|
-
send
|
22
|
+
warn("SanitizeEmail: ##{name} deprecated (please use ##{replacement})") unless SanitizeEmail::Deprecation.deprecate_in_silence
|
23
|
+
send(replacement, *args, &block)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -30,11 +30,11 @@ module SanitizeEmail
|
|
30
30
|
def deprecated(name, replacement = nil)
|
31
31
|
# Replace old method
|
32
32
|
old_name = :"#{name}_without_deprecation"
|
33
|
-
alias_method
|
33
|
+
alias_method(old_name, name)
|
34
34
|
# And replace it with a wrapped version
|
35
35
|
define_method(name) do |*args, &block|
|
36
36
|
deprecation(name, " (please use ##{replacement})")
|
37
|
-
send
|
37
|
+
send(old_name, *args, &block)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -47,7 +47,7 @@ module SanitizeEmail
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def deprecation_warning_message(message)
|
50
|
-
warn
|
50
|
+
warn(message) unless SanitizeEmail::Deprecation.deprecate_in_silence
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
6
|
module SanitizeEmail
|
7
|
-
# For Rails >= 3.1
|
8
|
-
|
7
|
+
# For Rails >= 3.1, < 6.0
|
8
|
+
# TODO: Remove when support for Rails < 6 is dropped
|
9
|
+
class EngineV5 < ::Rails::Engine
|
9
10
|
config.to_prepare do
|
10
11
|
ActionMailer::Base.register_interceptor(SanitizeEmail::Bleach)
|
11
12
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
|
+
# Released under the MIT license
|
5
|
+
|
6
|
+
module SanitizeEmail
|
7
|
+
# For Rails >= 6.0
|
8
|
+
class EngineV5 < ::Rails::Engine
|
9
|
+
config.to_prepare do
|
10
|
+
# For the reasoning behind the difference between v5 and v6 engines,
|
11
|
+
# - see: https://github.com/rails/rails/issues/36546#issuecomment-850888284
|
12
|
+
config.action_mailer.register_interceptor(SanitizeEmail::Bleach)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
6
|
module SanitizeEmail
|
@@ -9,39 +9,47 @@ module SanitizeEmail
|
|
9
9
|
def self.prepend_subject_array(message)
|
10
10
|
prepend = []
|
11
11
|
if SanitizeEmail.use_actual_email_prepended_to_subject
|
12
|
-
prepend << SanitizeEmail::MailHeaderTools
|
13
|
-
|
12
|
+
prepend << SanitizeEmail::MailHeaderTools
|
13
|
+
.prepend_email_to_subject(Array(message.to))
|
14
14
|
end
|
15
15
|
if SanitizeEmail.use_actual_environment_prepended_to_subject
|
16
|
-
prepend << SanitizeEmail::MailHeaderTools
|
17
|
-
|
16
|
+
prepend << SanitizeEmail::MailHeaderTools
|
17
|
+
.prepend_environment_to_subject
|
18
18
|
end
|
19
19
|
# this will force later joins to add an extra space
|
20
|
-
prepend <<
|
20
|
+
prepend << "" unless prepend.empty?
|
21
21
|
prepend
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.custom_subject(message)
|
25
|
-
prepend_subject_array(message).join(
|
25
|
+
prepend_subject_array(message).join(" ")
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.prepend_environment_to_subject
|
29
|
-
SanitizeEmail::Config.config[:environment]
|
29
|
+
if SanitizeEmail::Config.config[:environment].respond_to?(:call)
|
30
|
+
SanitizeEmail::Config.config[:environment].call.to_s
|
31
|
+
else
|
32
|
+
SanitizeEmail::Config.config[:environment].to_s
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
32
36
|
def self.prepend_email_to_subject(actual_addresses)
|
33
|
-
"(#{Array(actual_addresses).uniq.join(
|
34
|
-
gsub(/[<>]/,
|
37
|
+
"(#{Array(actual_addresses).uniq.join(",").gsub(/@/, " at ")
|
38
|
+
.gsub(/[<>]/, "~")})"
|
35
39
|
end
|
36
40
|
|
37
41
|
def self.add_original_addresses_as_headers(message)
|
38
42
|
# Add headers by string concat.
|
39
43
|
# Setting hash values on message.headers does nothing, strangely.
|
40
44
|
# See: http://goo.gl/v46GY
|
45
|
+
to_addrs = message[:to]&.addrs
|
46
|
+
cc_addrs = message[:cc]&.addrs
|
47
|
+
to_decoded = Array(to_addrs&.map(&:decoded))
|
48
|
+
cc_decoded = Array(cc_addrs&.map(&:decoded))
|
41
49
|
{
|
42
50
|
# can be an arrays, so casting it as arrays
|
43
|
-
|
44
|
-
|
51
|
+
"X-Sanitize-Email-To" => to_decoded,
|
52
|
+
"X-Sanitize-Email-Cc" => cc_decoded,
|
45
53
|
# Don't write out the BCC, as those addresses should not be visible
|
46
54
|
# in message headers for obvious reasons
|
47
55
|
}.each do |header_key, header_value|
|
@@ -49,13 +57,13 @@ module SanitizeEmail
|
|
49
57
|
SanitizeEmail::MailHeaderTools.update_header(
|
50
58
|
header_key,
|
51
59
|
header_value,
|
52
|
-
message
|
60
|
+
message,
|
53
61
|
)
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
57
65
|
def self.prepend_custom_subject(message)
|
58
|
-
message.subject =
|
66
|
+
message.subject = "" unless message.subject
|
59
67
|
custom_subject = SanitizeEmail::MailHeaderTools.custom_subject(message)
|
60
68
|
message.subject = custom_subject + message.subject
|
61
69
|
end
|
@@ -63,11 +71,11 @@ module SanitizeEmail
|
|
63
71
|
# According to https://github.com/mikel/mail
|
64
72
|
# this is the correct way to update headers.
|
65
73
|
def self.update_header(header_key, header_value, message)
|
66
|
-
return
|
74
|
+
return unless header_value
|
67
75
|
# For each address, as header_value can be an array of addresses
|
68
76
|
Array(header_value).each_with_index do |elem, index|
|
69
77
|
num = index + 1
|
70
|
-
new_header_key = num > 1 ? "#{header_key}-#{num}" : header_key
|
78
|
+
new_header_key = (num > 1) ? "#{header_key}-#{num}" : header_key
|
71
79
|
message.header[new_header_key] = elem.to_s
|
72
80
|
end
|
73
81
|
end
|
@@ -1,25 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# Copyright (c) 2008-
|
3
|
+
# Copyright (c) 2008 - 2018, 2020, 2022, 2024 Peter H. Boling of RailsBling.com
|
4
4
|
# Released under the MIT license
|
5
5
|
|
6
|
+
# External Libraries
|
7
|
+
require "mail"
|
8
|
+
|
6
9
|
module SanitizeEmail
|
7
10
|
# Tools for overriding addresses
|
8
11
|
class OverriddenAddresses
|
9
|
-
# Raised when
|
10
|
-
class
|
12
|
+
# Raised when there are no recipients after sanitization
|
13
|
+
class MissingRecipients < StandardError; end
|
14
|
+
|
15
|
+
# MissingTo is Deprecated
|
16
|
+
class MissingTo < MissingRecipients; end
|
11
17
|
|
12
18
|
# Raised if there is a recipient type that sanitize_email doesn't recognize.
|
13
19
|
# If you get this error please report it.
|
14
20
|
# recognized recipient types are: TO, CC, and BCC
|
15
21
|
class UnknownOverride < StandardError; end
|
16
22
|
|
17
|
-
REPLACE_AT = [/@/,
|
18
|
-
REPLACE_ALLIGATOR = [/[<>]/,
|
19
|
-
attr_accessor :
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
REPLACE_AT = [/@/, " at "].freeze
|
24
|
+
REPLACE_ALLIGATOR = [/[<>]/, "~"].freeze
|
25
|
+
attr_accessor :tempmail,
|
26
|
+
:overridden_to,
|
27
|
+
:overridden_cc,
|
28
|
+
:overridden_bcc,
|
29
|
+
:overridden_personalizations,
|
30
|
+
:good_list, # Allow-listed addresses will not be molested as to, cc, or bcc
|
31
|
+
:bad_list, # Block-listed addresses will be removed from to, cc and bcc when sanitization is engaged
|
32
|
+
:sanitized_to,
|
33
|
+
:sanitized_cc,
|
34
|
+
:sanitized_bcc # Replace non-allow-listed addresses with these sanitized addresses.
|
23
35
|
|
24
36
|
def initialize(message, **args)
|
25
37
|
# Not using extract_options! because non-rails compatibility is a goal
|
@@ -29,9 +41,25 @@ module SanitizeEmail
|
|
29
41
|
@sanitized_bcc = args[:sanitized_bcc]
|
30
42
|
@good_list = args[:good_list] || []
|
31
43
|
@bad_list = args[:bad_list] || []
|
32
|
-
|
33
|
-
@
|
34
|
-
|
44
|
+
# Mail will do the username parsing for us.
|
45
|
+
@tempmail = Mail.new
|
46
|
+
|
47
|
+
tempmail.to = to_override(message.to)
|
48
|
+
tempmail.cc = cc_override(message.cc)
|
49
|
+
tempmail.bcc = bcc_override(message.bcc)
|
50
|
+
|
51
|
+
# remove addresses from :cc / :bcc that are also in :to
|
52
|
+
remove_duplicates
|
53
|
+
|
54
|
+
@overridden_to = tempmail[:to].decoded
|
55
|
+
@overridden_cc = tempmail[:cc].decoded
|
56
|
+
@overridden_bcc = tempmail[:bcc].decoded
|
57
|
+
|
58
|
+
if message["personalizations"].nil?
|
59
|
+
raise MissingRecipients, "No recipients left post-sanitization" if (tempmail.to + tempmail.cc + tempmail.bcc).empty?
|
60
|
+
else
|
61
|
+
@overridden_personalizations = personalizations_override(message["personalizations"])
|
62
|
+
end
|
35
63
|
end
|
36
64
|
|
37
65
|
# Allow good listed email addresses, and then remove the bad listed addresses
|
@@ -43,16 +71,32 @@ module SanitizeEmail
|
|
43
71
|
|
44
72
|
def to_override(actual_addresses)
|
45
73
|
to = override_email(:to, actual_addresses)
|
46
|
-
|
47
|
-
to.join(',')
|
74
|
+
to.join(",")
|
48
75
|
end
|
49
76
|
|
50
77
|
def cc_override(actual_addresses)
|
51
|
-
override_email(:cc, actual_addresses).join(
|
78
|
+
override_email(:cc, actual_addresses).join(",")
|
52
79
|
end
|
53
80
|
|
54
81
|
def bcc_override(actual_addresses)
|
55
|
-
override_email(:bcc, actual_addresses).join(
|
82
|
+
override_email(:bcc, actual_addresses).join(",")
|
83
|
+
end
|
84
|
+
|
85
|
+
# Intended to result in compatibility with https://github.com/eddiezane/sendgrid-actionmailer
|
86
|
+
def personalizations_override(actual_personalizations)
|
87
|
+
actual_personalizations.unparsed_value.map do |actual_personalization|
|
88
|
+
actual_personalization.merge(
|
89
|
+
to: actual_personalization[:to]&.map do |to|
|
90
|
+
to.merge(email: override_email(:to, to[:email]).join(","))
|
91
|
+
end,
|
92
|
+
cc: actual_personalization[:cc]&.map do |cc|
|
93
|
+
cc.merge(email: override_email(:cc, cc[:email]).join(","))
|
94
|
+
end,
|
95
|
+
bcc: actual_personalization[:bcc]&.map do |bcc|
|
96
|
+
bcc.merge(email: override_email(:bcc, bcc[:email]).join(","))
|
97
|
+
end,
|
98
|
+
)
|
99
|
+
end
|
56
100
|
end
|
57
101
|
|
58
102
|
def override_email(type, actual_addresses)
|
@@ -99,17 +143,19 @@ module SanitizeEmail
|
|
99
143
|
has_address ? address : nil
|
100
144
|
when :bad_list then
|
101
145
|
has_address ? nil : address
|
146
|
+
else
|
147
|
+
raise ArgumentError, "address_list_filter got unknown list_type: #{list_type}"
|
102
148
|
end
|
103
149
|
end
|
104
150
|
|
105
151
|
def inject_user_names(real_addresses, sanitized_addresses)
|
106
152
|
real_addresses.each_with_object([]) do |real_recipient, result|
|
107
153
|
new_recipient = if real_recipient.nil?
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
154
|
+
sanitized_addresses
|
155
|
+
else
|
156
|
+
# puts "SANITIZED: #{sanitized_addresses}"
|
157
|
+
sanitized_addresses.map { |sanitized| "#{real_recipient.gsub(REPLACE_AT[0], REPLACE_AT[1]).gsub(/[<>]/, "~")} <#{sanitized}>" }
|
158
|
+
end
|
113
159
|
result << new_recipient
|
114
160
|
end.flatten
|
115
161
|
end
|
@@ -131,7 +177,23 @@ module SanitizeEmail
|
|
131
177
|
when :bcc then
|
132
178
|
Array(sanitized_bcc)
|
133
179
|
else
|
134
|
-
raise UnknownOverride,
|
180
|
+
raise UnknownOverride, "unknown email override"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
def remove_duplicates
|
187
|
+
dedup_addresses = tempmail[:to].addresses
|
188
|
+
|
189
|
+
tempmail[:cc].addrs.reject! do |addr|
|
190
|
+
# If this email address is already in the :to list, then remove
|
191
|
+
dedup_addresses.include?(addr.address)
|
192
|
+
end
|
193
|
+
dedup_addresses += tempmail[:cc].addresses
|
194
|
+
tempmail[:bcc].addrs.reject! do |addr|
|
195
|
+
# If this email address is already in the :to list, then remove
|
196
|
+
dedup_addresses.include?(addr.address)
|
135
197
|
end
|
136
198
|
end
|
137
199
|
end
|