sanitize_email 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2008-16 Peter H. Boling of RailsBling.com
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
- :sanitized_bcc => nil,
19
+ sanitized_bcc: nil,
20
20
 
21
21
  # Specify the CC addresses for the messages
22
22
  # that go out in "local" environments
23
- :sanitized_cc => nil,
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
- :sanitized_to => nil,
29
+ sanitized_to: nil,
30
30
 
31
- # a white list
32
- :good_list => nil,
31
+ # an allow list
32
+ good_list: nil,
33
33
 
34
- # a black list
35
- :bad_list => nil,
34
+ # a block list
35
+ bad_list: nil,
36
36
 
37
- :environment => if defined?(Rails) && Rails.env.present?
38
- "[#{Rails.env}]"
39
- else
40
- '[UNKNOWN ENVIRONMENT]'
41
- end,
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
- :use_actual_email_as_sanitized_user_name => false,
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
- :use_actual_email_prepended_to_subject => false,
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
- :use_actual_environment_prepended_to_subject => false,
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
- :engage => nil,
58
+ engage: nil,
59
59
 
60
- :activation_proc => proc { false },
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 nil if @config[:force_sanitize].nil?
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-16 Peter H. Boling of RailsBling.com
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 "SanitizeEmail: ##{name} deprecated (please use ##{replacement})" unless SanitizeEmail::Deprecation.deprecate_in_silence
23
- send replacement, *args, &block
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 old_name, name
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 old_name, *args, &block
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 message unless SanitizeEmail::Deprecation.deprecate_in_silence
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-16 Peter H. Boling of RailsBling.com
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
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "mail"
4
+
3
5
  # Cribbed from email_spec gem
4
6
  module SanitizeEmail::MailExt
5
7
  def default_part
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2008-16 Peter H. Boling of RailsBling.com
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
- prepend_email_to_subject(Array(message.to))
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
- prepend_environment_to_subject
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 << '' unless prepend.empty?
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(',').gsub(/@/, ' at ').
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
- 'X-Sanitize-Email-To' => Array(message.to).uniq,
44
- 'X-Sanitize-Email-Cc' => Array(message.cc).uniq
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 = '' unless 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 nil unless header_value
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-16 Peter H. Boling of RailsBling.com
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 = [/@/, ' at '].freeze
18
- REPLACE_ALLIGATOR = [/[<>]/, '~'].freeze
19
- attr_accessor :overridden_to, :overridden_cc, :overridden_bcc,
20
- :good_list, # White-listed addresses will not be molested as to, cc, or bcc
21
- :bad_list, # Black-listed addresses will be removed from to, cc and bcc when sanitization is engaged
22
- :sanitized_to, :sanitized_cc, :sanitized_bcc # Replace non-white-listed addresses with these sanitized addresses.
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
- @overridden_to = to_override(message.to)
33
- @overridden_cc = cc_override(message.cc)
34
- @overridden_bcc = bcc_override(message.bcc)
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
- to.join(',')
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
- sanitized_addresses
109
- else
110
- # puts "SANITIZED: #{sanitized_addresses}"
111
- sanitized_addresses.map { |sanitized| "#{real_recipient.gsub(REPLACE_AT[0], REPLACE_AT[1]).gsub(/[<>]/, '~')} <#{sanitized}>" }
112
- end
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, 'unknown email override'
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,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2008-16 Peter H. Boling of RailsBling.com
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
@@ -1,92 +1,116 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Copyright (c) 2008-16 Peter H. Boling of RailsBling.com
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 'sanitize_email/mail_ext'
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 "have_#{attribute}" do |matcher|
15
+ RSpec::Matchers.define("have_#{attribute}") do |matcher|
16
16
  match do |actual|
17
17
  @actual = actual.send(attribute)
18
- @actual = @actual.join(', ') if @actual.respond_to?(:join)
19
- expect(@actual).to match(matcher)
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 "match_#{attribute}" do |matcher|
25
+ RSpec::Matchers.define("match_#{attribute}") do |matcher|
26
26
  match do |actual|
27
27
  @actual = actual.send(attribute)
28
- @actual = @actual.join(', ') if @actual.respond_to?(:join)
29
- expect(@actual).to match(matcher)
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 "be_#{attribute}" do |matcher|
35
+ RSpec::Matchers.define("be_#{attribute}") do |matcher|
36
36
  match do |actual|
37
37
  @actual = actual.send(attribute)
38
- @actual = @actual.join(', ') if @actual.respond_to?(:join)
39
- expect(@actual).to be(matcher)
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 'have_to_username' do |matcher|
45
- def get_to_username(email_message)
46
- username_header = email_message.header['X-Sanitize-Email-To']
47
- return username_header unless username_header.is_a?(Mail::Field)
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 = get_to_username(actual)
52
- expect(@actual).to match(matcher)
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 'have_cc_username' do |matcher|
57
- def get_cc_username(email_message)
58
- username_header = email_message.header['X-Sanitize-Email-Cc']
59
- return username_header unless username_header.is_a?(Mail::Field)
60
- email_message.header.fields[3].value
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 = get_cc_username(actual)
64
- expect(@actual).to match(matcher)
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 'have_body_text' do |matcher|
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 match(fuzzy_matcher)
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 'have_header' do |name, matcher|
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 match(matcher)
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-16 Peter H. Boling of RailsBling.com
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
- matcher
23
- else
24
- Regexp.new(Regexp.escape(matcher))
25
- end
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(', ') if attribute.respond_to?(: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-16 Peter H. Boling of RailsBling.com
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
- VERSION = '2.0.3'
7
+ module Version
8
+ VERSION = "2.0.4"
9
+ end
8
10
  end