sanitize_email 2.0.2 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data/CHANGELOG.md +82 -12
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +47 -0
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +371 -58
- data/SECURITY.md +15 -0
- data/lib/sanitize_email/bleach.rb +13 -8
- data/lib/sanitize_email/config.rb +20 -20
- data/lib/sanitize_email/deprecation.rb +6 -6
- data/lib/sanitize_email/engine.rb +1 -1
- data/lib/sanitize_email/mail_ext.rb +2 -0
- data/lib/sanitize_email/mail_header_tools.rb +19 -15
- data/lib/sanitize_email/overridden_addresses.rb +77 -19
- data/lib/sanitize_email/railtie.rb +1 -1
- data/lib/sanitize_email/rspec_matchers.rb +55 -31
- data/lib/sanitize_email/test_helpers.rb +6 -6
- data/lib/sanitize_email/version.rb +4 -2
- data/lib/sanitize_email.rb +28 -18
- data.tar.gz.sig +0 -0
- metadata +70 -90
- 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
|
@@ -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
45
|
# e.g. "real@example.com <sanitized@example.com>"
|
46
|
-
:
|
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
49
|
# e.g. "real@example.com rest of subject"
|
50
|
-
:
|
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,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,20 +9,20 @@ 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
|
@@ -30,18 +30,22 @@ module SanitizeEmail
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.prepend_email_to_subject(actual_addresses)
|
33
|
-
"(#{Array(actual_addresses).uniq.join(
|
34
|
-
gsub(/[<>]/,
|
33
|
+
"(#{Array(actual_addresses).uniq.join(",").gsub(/@/, " at ")
|
34
|
+
.gsub(/[<>]/, "~")})"
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.add_original_addresses_as_headers(message)
|
38
38
|
# Add headers by string concat.
|
39
39
|
# Setting hash values on message.headers does nothing, strangely.
|
40
40
|
# See: http://goo.gl/v46GY
|
41
|
+
to_addrs = message[:to]&.addrs
|
42
|
+
cc_addrs = message[:cc]&.addrs
|
43
|
+
to_decoded = Array(to_addrs&.map(&:decoded))
|
44
|
+
cc_decoded = Array(cc_addrs&.map(&:decoded))
|
41
45
|
{
|
42
46
|
# can be an arrays, so casting it as arrays
|
43
|
-
|
44
|
-
|
47
|
+
"X-Sanitize-Email-To" => to_decoded,
|
48
|
+
"X-Sanitize-Email-Cc" => cc_decoded,
|
45
49
|
# Don't write out the BCC, as those addresses should not be visible
|
46
50
|
# in message headers for obvious reasons
|
47
51
|
}.each do |header_key, header_value|
|
@@ -49,13 +53,13 @@ module SanitizeEmail
|
|
49
53
|
SanitizeEmail::MailHeaderTools.update_header(
|
50
54
|
header_key,
|
51
55
|
header_value,
|
52
|
-
message
|
56
|
+
message,
|
53
57
|
)
|
54
58
|
end
|
55
59
|
end
|
56
60
|
|
57
61
|
def self.prepend_custom_subject(message)
|
58
|
-
message.subject =
|
62
|
+
message.subject = "" unless message.subject
|
59
63
|
custom_subject = SanitizeEmail::MailHeaderTools.custom_subject(message)
|
60
64
|
message.subject = custom_subject + message.subject
|
61
65
|
end
|
@@ -63,11 +67,11 @@ module SanitizeEmail
|
|
63
67
|
# According to https://github.com/mikel/mail
|
64
68
|
# this is the correct way to update headers.
|
65
69
|
def self.update_header(header_key, header_value, message)
|
66
|
-
return
|
70
|
+
return unless header_value
|
67
71
|
# For each address, as header_value can be an array of addresses
|
68
72
|
Array(header_value).each_with_index do |elem, index|
|
69
73
|
num = index + 1
|
70
|
-
new_header_key = num > 1 ? "#{header_key}-#{num}" : header_key
|
74
|
+
new_header_key = (num > 1) ? "#{header_key}-#{num}" : header_key
|
71
75
|
message.header[new_header_key] = elem.to_s
|
72
76
|
end
|
73
77
|
end
|
@@ -1,8 +1,11 @@
|
|
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
|
@@ -14,12 +17,18 @@ module SanitizeEmail
|
|
14
17
|
# recognized recipient types are: TO, CC, and BCC
|
15
18
|
class UnknownOverride < StandardError; end
|
16
19
|
|
17
|
-
REPLACE_AT = [/@/,
|
18
|
-
REPLACE_ALLIGATOR = [/[<>]/,
|
19
|
-
attr_accessor :
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
REPLACE_AT = [/@/, " at "].freeze
|
21
|
+
REPLACE_ALLIGATOR = [/[<>]/, "~"].freeze
|
22
|
+
attr_accessor :tempmail,
|
23
|
+
:overridden_to,
|
24
|
+
:overridden_cc,
|
25
|
+
:overridden_bcc,
|
26
|
+
:overridden_personalizations,
|
27
|
+
:good_list, # Allow-listed addresses will not be molested as to, cc, or bcc
|
28
|
+
:bad_list, # Block-listed addresses will be removed from to, cc and bcc when sanitization is engaged
|
29
|
+
:sanitized_to,
|
30
|
+
:sanitized_cc,
|
31
|
+
:sanitized_bcc # Replace non-allow-listed addresses with these sanitized addresses.
|
23
32
|
|
24
33
|
def initialize(message, **args)
|
25
34
|
# Not using extract_options! because non-rails compatibility is a goal
|
@@ -29,9 +38,23 @@ module SanitizeEmail
|
|
29
38
|
@sanitized_bcc = args[:sanitized_bcc]
|
30
39
|
@good_list = args[:good_list] || []
|
31
40
|
@bad_list = args[:bad_list] || []
|
32
|
-
|
33
|
-
@
|
34
|
-
|
41
|
+
# Mail will do the username parsing for us.
|
42
|
+
@tempmail = Mail.new
|
43
|
+
|
44
|
+
tempmail.to = to_override(message.to)
|
45
|
+
tempmail.cc = cc_override(message.cc)
|
46
|
+
tempmail.bcc = bcc_override(message.bcc)
|
47
|
+
|
48
|
+
remove_duplicates
|
49
|
+
|
50
|
+
@overridden_to = tempmail[:to].decoded
|
51
|
+
@overridden_cc = tempmail[:cc].decoded
|
52
|
+
@overridden_bcc = tempmail[:bcc].decoded
|
53
|
+
|
54
|
+
# remove addresses from :cc that are in :to
|
55
|
+
return if message["personalizations"].nil?
|
56
|
+
|
57
|
+
@overridden_personalizations = personalizations_override(message["personalizations"])
|
35
58
|
end
|
36
59
|
|
37
60
|
# Allow good listed email addresses, and then remove the bad listed addresses
|
@@ -44,15 +67,32 @@ module SanitizeEmail
|
|
44
67
|
def to_override(actual_addresses)
|
45
68
|
to = override_email(:to, actual_addresses)
|
46
69
|
raise MissingTo, "after overriding :to (#{actual_addresses}) there are no addresses to send in To: header." if to.empty?
|
47
|
-
|
70
|
+
|
71
|
+
to.join(",")
|
48
72
|
end
|
49
73
|
|
50
74
|
def cc_override(actual_addresses)
|
51
|
-
override_email(:cc, actual_addresses).join(
|
75
|
+
override_email(:cc, actual_addresses).join(",")
|
52
76
|
end
|
53
77
|
|
54
78
|
def bcc_override(actual_addresses)
|
55
|
-
override_email(:bcc, actual_addresses).join(
|
79
|
+
override_email(:bcc, actual_addresses).join(",")
|
80
|
+
end
|
81
|
+
|
82
|
+
def personalizations_override(actual_personalizations)
|
83
|
+
actual_personalizations.unparsed_value.map do |actual_personalization|
|
84
|
+
actual_personalization.merge(
|
85
|
+
to: actual_personalization[:to]&.map do |to|
|
86
|
+
to.merge(email: override_email(:to, to[:email]).join(","))
|
87
|
+
end,
|
88
|
+
cc: actual_personalization[:cc]&.map do |cc|
|
89
|
+
cc.merge(email: override_email(:cc, cc[:email]).join(","))
|
90
|
+
end,
|
91
|
+
bcc: actual_personalization[:bcc]&.map do |bcc|
|
92
|
+
bcc.merge(email: override_email(:bcc, bcc[:email]).join(","))
|
93
|
+
end,
|
94
|
+
)
|
95
|
+
end
|
56
96
|
end
|
57
97
|
|
58
98
|
def override_email(type, actual_addresses)
|
@@ -99,17 +139,19 @@ module SanitizeEmail
|
|
99
139
|
has_address ? address : nil
|
100
140
|
when :bad_list then
|
101
141
|
has_address ? nil : address
|
142
|
+
else
|
143
|
+
raise ArgumentError, "address_list_filter got unknown list_type: #{list_type}"
|
102
144
|
end
|
103
145
|
end
|
104
146
|
|
105
147
|
def inject_user_names(real_addresses, sanitized_addresses)
|
106
148
|
real_addresses.each_with_object([]) do |real_recipient, result|
|
107
149
|
new_recipient = if real_recipient.nil?
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
150
|
+
sanitized_addresses
|
151
|
+
else
|
152
|
+
# puts "SANITIZED: #{sanitized_addresses}"
|
153
|
+
sanitized_addresses.map { |sanitized| "#{real_recipient.gsub(REPLACE_AT[0], REPLACE_AT[1]).gsub(/[<>]/, "~")} <#{sanitized}>" }
|
154
|
+
end
|
113
155
|
result << new_recipient
|
114
156
|
end.flatten
|
115
157
|
end
|
@@ -131,7 +173,23 @@ module SanitizeEmail
|
|
131
173
|
when :bcc then
|
132
174
|
Array(sanitized_bcc)
|
133
175
|
else
|
134
|
-
raise UnknownOverride,
|
176
|
+
raise UnknownOverride, "unknown email override"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
def remove_duplicates
|
183
|
+
dedup_addresses = tempmail[:to].addresses
|
184
|
+
|
185
|
+
tempmail[:cc].addrs.reject! do |addr|
|
186
|
+
# If this email address is already in the :to list, then remove
|
187
|
+
dedup_addresses.include?(addr.address)
|
188
|
+
end
|
189
|
+
dedup_addresses += tempmail[:cc].addresses
|
190
|
+
tempmail[:bcc].addrs.reject! do |addr|
|
191
|
+
# If this email address is already in the :to list, then remove
|
192
|
+
dedup_addresses.include?(addr.address)
|
135
193
|
end
|
136
194
|
end
|
137
195
|
end
|
@@ -1,92 +1,116 @@
|
|
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
|
# Note: the RspecMatchers are composed matchers:
|
6
6
|
# See: http://www.relishapp.com/rspec/rspec-expectations/v/3-5/docs/composing-matchers
|
7
7
|
|
8
|
-
require
|
8
|
+
require "sanitize_email/mail_ext"
|
9
9
|
|
10
10
|
module SanitizeEmail
|
11
11
|
# Provides matchers that can be used in
|
12
12
|
# Rspec tests to assert the behavior of email
|
13
13
|
module RspecMatchers
|
14
14
|
%i[from to cc bcc subject reply_to].each do |attribute|
|
15
|
-
RSpec::Matchers.define
|
15
|
+
RSpec::Matchers.define("have_#{attribute}") do |matcher|
|
16
16
|
match do |actual|
|
17
17
|
@actual = actual.send(attribute)
|
18
|
-
@actual = @actual.join(
|
19
|
-
expect(@actual).to
|
18
|
+
@actual = @actual.join(", ") if @actual.respond_to?(:join)
|
19
|
+
expect(@actual).to(match(matcher))
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
%i[from to cc bcc subject reply_to].each do |attribute|
|
25
|
-
RSpec::Matchers.define
|
25
|
+
RSpec::Matchers.define("match_#{attribute}") do |matcher|
|
26
26
|
match do |actual|
|
27
27
|
@actual = actual.send(attribute)
|
28
|
-
@actual = @actual.join(
|
29
|
-
expect(@actual).to
|
28
|
+
@actual = @actual.join(", ") if @actual.respond_to?(:join)
|
29
|
+
expect(@actual).to(match(matcher))
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
%i[from to cc bcc subject reply_to].each do |attribute|
|
35
|
-
RSpec::Matchers.define
|
35
|
+
RSpec::Matchers.define("be_#{attribute}") do |matcher|
|
36
36
|
match do |actual|
|
37
37
|
@actual = actual.send(attribute)
|
38
|
-
@actual = @actual.join(
|
39
|
-
expect(@actual).to
|
38
|
+
@actual = @actual.join(", ") if @actual.respond_to?(:join)
|
39
|
+
expect(@actual).to(be(matcher))
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
RSpec::Matchers.define
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
email_message.header.fields[3].value
|
44
|
+
RSpec::Matchers.define("have_to_username") do |matcher|
|
45
|
+
def get_to_usernames(email_message)
|
46
|
+
to_addrs = email_message[:to].addrs
|
47
|
+
to_addrs.map(&:name)
|
49
48
|
end
|
50
49
|
match do |actual|
|
51
|
-
@actual =
|
52
|
-
expect(@actual).to
|
50
|
+
@actual = get_to_usernames(actual)
|
51
|
+
expect(@actual).to(include(match(matcher)))
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
RSpec::Matchers.define
|
57
|
-
def
|
58
|
-
|
59
|
-
return
|
60
|
-
|
55
|
+
RSpec::Matchers.define("have_sanitized_to_header") do |matcher|
|
56
|
+
def get_sanitized_to_header(email_message)
|
57
|
+
sanitized_to_header = email_message.header["X-Sanitize-Email-To"]
|
58
|
+
return sanitized_to_header.value if sanitized_to_header.is_a?(Mail::Field)
|
59
|
+
|
60
|
+
"no header found at 'X-Sanitize-Email-To'"
|
61
|
+
end
|
62
|
+
match do |actual|
|
63
|
+
@actual = get_sanitized_to_header(actual)
|
64
|
+
expect(@actual).to(match(matcher))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
RSpec::Matchers.define("have_cc_username") do |matcher|
|
69
|
+
def get_cc_usernames(email_message)
|
70
|
+
to_addrs = email_message[:cc].addrs
|
71
|
+
to_addrs.map(&:name)
|
72
|
+
end
|
73
|
+
match do |actual|
|
74
|
+
@actual = get_cc_usernames(actual)
|
75
|
+
expect(@actual).to(include(match(matcher)))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
RSpec::Matchers.define("have_sanitized_cc_header") do |matcher|
|
80
|
+
def get_sanitized_cc_header(email_message)
|
81
|
+
sanitized_cc_header = email_message.header["X-Sanitize-Email-Cc"]
|
82
|
+
return sanitized_cc_header.value if sanitized_cc_header.is_a?(Mail::Field)
|
83
|
+
|
84
|
+
"no header found at 'X-Sanitize-Email-Cc'"
|
61
85
|
end
|
62
86
|
match do |actual|
|
63
|
-
@actual =
|
64
|
-
expect(@actual).to
|
87
|
+
@actual = get_sanitized_cc_header(actual)
|
88
|
+
expect(@actual).to(match(matcher))
|
65
89
|
end
|
66
90
|
end
|
67
91
|
|
68
92
|
# Cribbed from email_spec gem
|
69
|
-
RSpec::Matchers.define
|
93
|
+
RSpec::Matchers.define("have_body_text") do |matcher|
|
70
94
|
def get_fuzzy_body(email_message)
|
71
|
-
email_message.default_part_body.to_s.gsub(/\s+/,
|
95
|
+
email_message.default_part_body.to_s.gsub(/\s+/, " ")
|
72
96
|
end
|
73
97
|
|
74
98
|
def get_fuzzy_matcher(to_fuzz)
|
75
|
-
to_fuzz.gsub(/\s+/,
|
99
|
+
to_fuzz.gsub(/\s+/, " ")
|
76
100
|
end
|
77
101
|
match do |actual|
|
78
102
|
@actual = get_fuzzy_body(actual)
|
79
103
|
fuzzy_matcher = get_fuzzy_matcher(matcher)
|
80
|
-
expect(@actual).to
|
104
|
+
expect(@actual).to(match(fuzzy_matcher))
|
81
105
|
end
|
82
106
|
end
|
83
107
|
|
84
108
|
# Cribbed from email_spec gem
|
85
|
-
RSpec::Matchers.define
|
109
|
+
RSpec::Matchers.define("have_header") do |name, matcher|
|
86
110
|
match do |actual|
|
87
111
|
@actual = actual.header[name]
|
88
112
|
@actual = @actual.value unless @actual.nil?
|
89
|
-
expect(@actual).to
|
113
|
+
expect(@actual).to(match(matcher))
|
90
114
|
end
|
91
115
|
end
|
92
116
|
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
|
# Note: the RspecMatchers no longer use these methods. Instead they are composed matchers:
|
6
6
|
# See: http://www.relishapp.com/rspec/rspec-expectations/v/3-5/docs/composing-matchers
|
@@ -19,15 +19,15 @@ module SanitizeEmail
|
|
19
19
|
# Can we match a regex against it?
|
20
20
|
raise UnexpectedMailType, "Cannot match #{matcher} for #{part}" unless attribute.respond_to?(:=~)
|
21
21
|
attribute =~ if matcher.is_a?(Regexp)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
matcher
|
23
|
+
else
|
24
|
+
Regexp.new(Regexp.escape(matcher))
|
25
|
+
end
|
26
26
|
end
|
27
27
|
|
28
28
|
# Normalize arrays to strings
|
29
29
|
def array_matching(matcher, part, attribute)
|
30
|
-
attribute = attribute.join(
|
30
|
+
attribute = attribute.join(", ") if attribute.respond_to?(:join)
|
31
31
|
string_matching(matcher, part, attribute)
|
32
32
|
end
|
33
33
|
|
@@ -1,8 +1,10 @@
|
|
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
|
-
|
7
|
+
module Version
|
8
|
+
VERSION = "2.0.4"
|
9
|
+
end
|
8
10
|
end
|