sanitize_email 1.0.7 → 1.0.8
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.
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/REEK +16 -15
- data/lib/sanitize_email.rb +7 -0
- data/lib/sanitize_email/bleach.rb +9 -165
- data/lib/sanitize_email/mail_header_tools.rb +52 -0
- data/lib/sanitize_email/overridden_addresses.rb +129 -0
- data/lib/sanitize_email/version.rb +1 -1
- data/sanitize_email.gemspec +1 -1
- data/spec/sanitize_email_spec.rb +66 -0
- metadata +4 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
Version 1.0.8 - AUG.30.2013
|
2
|
+
* \[Bug Fix\] Fixes #12 - Streange repeating headers by Peter Boling
|
3
|
+
* Lots of refactoring by Peter Boling
|
4
|
+
* Properly supports when a to/cc field has multiple recipients sanitized and adds all to mail headers
|
5
|
+
* Improved specs by Peter Boling
|
6
|
+
|
1
7
|
Version 1.0.7 - AUG.06.2012
|
2
8
|
|
3
9
|
* \[Bug Fix\] Stripping the message headers before appending new headers.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -146,7 +146,7 @@ dependency on this gem using the [Pessimistic Version Constraint][pvc] with two
|
|
146
146
|
|
147
147
|
For example:
|
148
148
|
|
149
|
-
spec.add_dependency 'sanitize_email', '~>
|
149
|
+
spec.add_dependency 'sanitize_email', '~> 1.0.8'
|
150
150
|
|
151
151
|
[semver]: http://semver.org/
|
152
152
|
[pvc]: http://docs.rubygems.org/read/chapter/16#page74
|
data/REEK
CHANGED
@@ -1,16 +1,4 @@
|
|
1
|
-
lib/sanitize_email.rb --
|
2
|
-
SanitizeEmail#self.sanitary calls SanitizeEmail::Config.config twice (DuplicateMethodCall)
|
3
|
-
lib/sanitize_email/bleach.rb -- 14 warnings:
|
4
|
-
SanitizeEmail::Bleach has no descriptive comment (IrresponsibleModule)
|
5
|
-
SanitizeEmail::Bleach#activate? calls SanitizeEmail.activation_proc twice (DuplicateMethodCall)
|
6
|
-
SanitizeEmail::Bleach#activate? doesn't depend on instance state (UtilityFunction)
|
7
|
-
SanitizeEmail::Bleach#delivering_email calls message.to twice (DuplicateMethodCall)
|
8
|
-
SanitizeEmail::Bleach#inject_user_names contains iterators nested 2 deep (NestedIterators)
|
9
|
-
SanitizeEmail::Bleach#inject_user_names doesn't depend on instance state (UtilityFunction)
|
10
|
-
SanitizeEmail::Bleach#inject_user_names refers to real_recipient more than self (FeatureEnvy)
|
11
|
-
SanitizeEmail::Bleach#override_email has approx 10 statements (TooManyStatements)
|
12
|
-
SanitizeEmail::Bleach#subject_override doesn't depend on instance state (UtilityFunction)
|
13
|
-
SanitizeEmail::Bleach#subject_override refers to actual_addresses more than self (FeatureEnvy)
|
1
|
+
lib/sanitize_email/bleach.rb -- 2 warnings:
|
14
2
|
SanitizeEmail::Bleach::MissingTo has no descriptive comment (IrresponsibleModule)
|
15
3
|
SanitizeEmail::Bleach::UnknownOverride has no descriptive comment (IrresponsibleModule)
|
16
4
|
lib/sanitize_email/config.rb -- 4 warnings:
|
@@ -18,12 +6,25 @@ lib/sanitize_email/config.rb -- 4 warnings:
|
|
18
6
|
SanitizeEmail::Config#self.configure calls @config[:force_sanitize] twice (DuplicateMethodCall)
|
19
7
|
SanitizeEmail::Config#self.configure calls @config[:sanitized_recipients] twice (DuplicateMethodCall)
|
20
8
|
SanitizeEmail::Config#self.configure has approx 7 statements (TooManyStatements)
|
21
|
-
lib/sanitize_email/deprecation.rb --
|
22
|
-
SanitizeEmail::Deprecation declares the class variable @@deprecate_in_silence (ClassVariable)
|
9
|
+
lib/sanitize_email/deprecation.rb -- 2 warnings:
|
23
10
|
SanitizeEmail::Deprecation takes parameters [name, replacement] to 3 methods (DataClump)
|
24
11
|
SanitizeEmail::Deprecation#deprecation is controlled by argument replacement (ControlParameter)
|
25
12
|
lib/sanitize_email/engine.rb -- 1 warning:
|
26
13
|
SanitizeEmail::Engine has no descriptive comment (IrresponsibleModule)
|
14
|
+
lib/sanitize_email/mail_header_tools.rb -- 7 warnings:
|
15
|
+
SanitizeEmail::MailHeaderTools#self.add_original_addresses_as_headers has the variable name 'k' (UncommunicativeVariableName)
|
16
|
+
SanitizeEmail::MailHeaderTools#self.add_original_addresses_as_headers has the variable name 'v' (UncommunicativeVariableName)
|
17
|
+
SanitizeEmail::MailHeaderTools#self.prepend_environment_to_subject calls Rails.env twice (DuplicateMethodCall)
|
18
|
+
SanitizeEmail::MailHeaderTools#self.update_header has the parameter name 'k' (UncommunicativeParameterName)
|
19
|
+
SanitizeEmail::MailHeaderTools#self.update_header has the parameter name 'v' (UncommunicativeParameterName)
|
20
|
+
SanitizeEmail::MailHeaderTools#self.update_header has the variable name 'a' (UncommunicativeVariableName)
|
21
|
+
SanitizeEmail::MailHeaderTools#self.update_header is controlled by argument v (ControlParameter)
|
22
|
+
lib/sanitize_email/overridden_addresses.rb -- 5 warnings:
|
23
|
+
SanitizeEmail::OverriddenAddresses has no descriptive comment (IrresponsibleModule)
|
24
|
+
SanitizeEmail::OverriddenAddresses#inject_user_names contains iterators nested 2 deep (NestedIterators)
|
25
|
+
SanitizeEmail::OverriddenAddresses#inject_user_names doesn't depend on instance state (UtilityFunction)
|
26
|
+
SanitizeEmail::OverriddenAddresses#inject_user_names refers to real_recipient more than self (FeatureEnvy)
|
27
|
+
SanitizeEmail::OverriddenAddresses#override_email has approx 10 statements (TooManyStatements)
|
27
28
|
lib/sanitize_email/railtie.rb -- 1 warning:
|
28
29
|
SanitizeEmail::Railtie has no descriptive comment (IrresponsibleModule)
|
29
30
|
lib/sanitize_email/rspec_matchers.rb -- 2 warnings:
|
data/lib/sanitize_email.rb
CHANGED
@@ -5,6 +5,8 @@ module SanitizeEmail
|
|
5
5
|
require 'sanitize_email/version'
|
6
6
|
require 'sanitize_email/deprecation'
|
7
7
|
require 'sanitize_email/config'
|
8
|
+
require 'sanitize_email/mail_header_tools'
|
9
|
+
require 'sanitize_email/overridden_addresses'
|
8
10
|
require 'sanitize_email/bleach'
|
9
11
|
|
10
12
|
class MissingBlockParameter < StandardError; end
|
@@ -44,6 +46,11 @@ module SanitizeEmail
|
|
44
46
|
SanitizeEmail[:local_environments]
|
45
47
|
end
|
46
48
|
|
49
|
+
def self.activate?(message)
|
50
|
+
proc = SanitizeEmail.activation_proc
|
51
|
+
proc.call(message) if proc.respond_to?(:call)
|
52
|
+
end
|
53
|
+
|
47
54
|
class << self
|
48
55
|
attr_accessor :force_sanitize
|
49
56
|
end
|
@@ -2,69 +2,32 @@
|
|
2
2
|
#Released under the MIT license
|
3
3
|
|
4
4
|
module SanitizeEmail
|
5
|
+
# SanitizeEmail::Bleach determines whether to sanitize the headers of an email, and does so when appropriate.
|
5
6
|
class Bleach
|
6
7
|
|
7
|
-
class MissingTo < StandardError;
|
8
|
-
end
|
9
|
-
class UnknownOverride < StandardError;
|
10
|
-
end
|
11
|
-
|
12
8
|
# Can override global configs at the instance level.
|
13
9
|
attr_accessor :engage, # Turn sanitization on or off just for this instance
|
14
|
-
:
|
15
|
-
:good_list, # White-listed addresses will not be molested as to, cc, or bcc
|
16
|
-
:bad_list, # Black-listed addresses will be removed from to, cc and bcc when sanitization is engaged
|
17
|
-
:injected # Track whether or not the subject has been injected with usernames
|
10
|
+
:overridden_addresses
|
18
11
|
|
19
12
|
def initialize(args = {})
|
20
13
|
# Not using extract_options! because non-rails compatibility is a goal
|
21
|
-
@sanitized_to = args[:sanitized_to] || SanitizeEmail[:sanitized_to]
|
22
|
-
@sanitized_cc = args[:sanitized_cc] || SanitizeEmail[:sanitized_cc]
|
23
|
-
@sanitized_bcc = args[:sanitized_bcc] || SanitizeEmail[:sanitized_bcc]
|
24
|
-
@good_list = args[:good_list] || SanitizeEmail[:good_list] || []
|
25
|
-
@bad_list = args[:bad_list] || SanitizeEmail[:bad_list] || []
|
26
14
|
@engage = args[:engage] || SanitizeEmail[:engage]
|
27
|
-
@injected = false
|
28
15
|
end
|
29
16
|
|
30
17
|
# If all recipient addresses are white-listed the field is left alone.
|
31
18
|
def delivering_email(message)
|
32
19
|
if self.sanitize_engaged?(message)
|
33
|
-
|
34
|
-
|
35
|
-
cache_cc = self.cc_override(message.cc)
|
36
|
-
cache_bcc = self.bcc_override(message.bcc)
|
20
|
+
SanitizeEmail::MailHeaderTools.add_original_addresses_as_headers(message)
|
21
|
+
SanitizeEmail::MailHeaderTools.prepend_custom_subject(message)
|
37
22
|
|
38
|
-
|
23
|
+
o = SanitizeEmail::OverriddenAddresses.new(message)
|
39
24
|
|
40
|
-
message.
|
41
|
-
message.
|
42
|
-
|
43
|
-
message.to = cache_to
|
44
|
-
message.cc = cache_cc
|
45
|
-
message.bcc = cache_bcc
|
25
|
+
message.to = o.overridden_to
|
26
|
+
message.cc = o.overridden_cc
|
27
|
+
message.bcc = o.overridden_bcc
|
46
28
|
end
|
47
29
|
end
|
48
30
|
|
49
|
-
def add_original_addresses_as_headers(message)
|
50
|
-
## Add headers by string concat. Setting hash values on message.headers does nothing, strangely. http://goo.gl/v46GY
|
51
|
-
{
|
52
|
-
'X-Sanitize-Email-To' => message.to,
|
53
|
-
'X-Sanitize-Email-Cc' => message.cc
|
54
|
-
# Don't write out the BCC, as those addresses should not be visible in message headers for obvious reasons
|
55
|
-
}.each { |k, v|
|
56
|
-
# For each type of address line
|
57
|
-
v.each { |a|
|
58
|
-
# For each address
|
59
|
-
message.header = message.header.to_s.strip + "\n#{k}: #{a}"
|
60
|
-
} if v
|
61
|
-
}
|
62
|
-
end
|
63
|
-
|
64
|
-
def activate?(message)
|
65
|
-
SanitizeEmail.activation_proc.call(message) if SanitizeEmail.activation_proc.respond_to?(:call)
|
66
|
-
end
|
67
|
-
|
68
31
|
# This method will be called by the Hook to determine if an override should occur
|
69
32
|
# There are three ways SanitizeEmail can be turned on; in order of precedence they are:
|
70
33
|
#
|
@@ -86,127 +49,8 @@ module SanitizeEmail
|
|
86
49
|
return engaged unless engaged.nil?
|
87
50
|
|
88
51
|
# Should we sanitize due to the activation_proc?
|
89
|
-
return
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
def prepend_email_to_subject(real_subject, actual_addresses)
|
94
|
-
if !actual_addresses.respond_to?(:join)
|
95
|
-
real_subject
|
96
|
-
else
|
97
|
-
"(#{actual_addresses.join(',').gsub(/@/, ' at ').gsub(/[<>]/, '~')}) #{real_subject}"
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def prepend_environment_to_subject(real_subject)
|
102
|
-
if defined?(Rails) && Rails.env.present?
|
103
|
-
"[#{Rails.env}] #{real_subject}"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def to_override(actual_addresses)
|
108
|
-
to = override_email(:to, actual_addresses)
|
109
|
-
raise MissingTo, 'after overriding :to there are no addresses to send in To: header.' if to.empty?
|
110
|
-
to.join(',')
|
111
|
-
end
|
112
|
-
|
113
|
-
def cc_override(actual_addresses)
|
114
|
-
override_email(:cc, actual_addresses).join(',')
|
115
|
-
end
|
116
|
-
|
117
|
-
def bcc_override(actual_addresses)
|
118
|
-
override_email(:bcc, actual_addresses).join(',')
|
119
|
-
end
|
120
|
-
|
121
|
-
#######
|
122
|
-
protected
|
123
|
-
#######
|
124
|
-
|
125
|
-
def address_list_filter(list_type, address)
|
126
|
-
# TODO: How does this handle email addresses with user names like "Foo Example <foo@example.org>"
|
127
|
-
has_address = self.send(list_type).include?(address)
|
128
|
-
case list_type
|
129
|
-
when :good_list then
|
130
|
-
has_address ? address : nil
|
131
|
-
when :bad_list then
|
132
|
-
has_address ? nil : address
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def inject_user_names(real_addresses, sanitized_addresses)
|
137
|
-
real_addresses.inject([]) do |result, real_recipient|
|
138
|
-
if real_recipient.nil?
|
139
|
-
new_recipient = sanitized_addresses
|
140
|
-
else
|
141
|
-
new_recipient = sanitized_addresses.map { |sanitized| "#{real_recipient.gsub(/@/, ' at ').gsub(/[<>]/, '~')} <#{sanitized}>" }
|
142
|
-
end
|
143
|
-
result << new_recipient
|
144
|
-
result
|
145
|
-
end.flatten
|
146
|
-
end
|
147
|
-
|
148
|
-
def clean_addresses(addresses, list_type)
|
149
|
-
# Normalize addresses just in case it isn't an array yet
|
150
|
-
addresses.map { |address|
|
151
|
-
# If this address is on the good list then let it pass
|
152
|
-
self.address_list_filter(list_type, address)
|
153
|
-
}.compact
|
154
|
-
end
|
155
|
-
|
156
|
-
def sanitize_addresses(type)
|
157
|
-
case type
|
158
|
-
when :to then
|
159
|
-
Array(self.sanitized_to)
|
160
|
-
when :cc then
|
161
|
-
Array(self.sanitized_cc)
|
162
|
-
when :bcc then
|
163
|
-
Array(self.sanitized_bcc)
|
164
|
-
else
|
165
|
-
raise UnknownOverride, "unknown email override"
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# Allow good listed email addresses, and then remove the bad listed addresses
|
170
|
-
def good_listize(real_addresses)
|
171
|
-
good_listed = self.clean_addresses(real_addresses, :good_list)
|
172
|
-
good_listed = self.clean_addresses(good_listed, :bad_list) unless good_listed.empty?
|
173
|
-
good_listed
|
174
|
-
end
|
175
|
-
|
176
|
-
def override_email(type, actual_addresses)
|
177
|
-
# Normalized to an arrays
|
178
|
-
#puts "override_email 1: #{type} - #{actual_addresses}"
|
179
|
-
real_addresses = Array(actual_addresses)
|
180
|
-
|
181
|
-
#puts "override_email 2: #{type} - #{real_addresses}"
|
182
|
-
# If there were no original recipients, then we DO NOT override the nil with the sanitized recipients
|
183
|
-
return [] if real_addresses.empty?
|
184
|
-
|
185
|
-
good_listed = good_listize(real_addresses)
|
186
|
-
#puts "override_email 3: #{type} - #{good_listed}"
|
187
|
-
# If there are good_list addresses to send to then use them as is, no mods needed
|
188
|
-
return good_listed unless good_listed.empty?
|
189
|
-
|
190
|
-
# TODO: Allow overriding if an addressed email is on the good list?
|
191
|
-
# If there are no sanitized addresses we can't override!
|
192
|
-
sanitized_addresses = sanitize_addresses(type)
|
193
|
-
#puts "override_email 3: #{type} - #{sanitized_addresses}"
|
194
|
-
return [] if sanitized_addresses.empty?
|
195
|
-
|
196
|
-
# At this point it is assured that the address list will need to be sanitized
|
197
|
-
# One more check to ensure none of the configured sanitized email addresses are on the bad_list
|
198
|
-
sanitized_addresses = self.clean_addresses(sanitized_addresses, :bad_list)
|
199
|
-
#puts "override_email 4: #{type} - #{sanitized_addresses}"
|
200
|
-
|
201
|
-
# If we don't want to inject the 'email' in the 'user name' section of the sanitized recipients,
|
202
|
-
# then just return the default sanitized recipients
|
203
|
-
return sanitized_addresses unless SanitizeEmail.use_actual_email_as_sanitized_user_name
|
52
|
+
return SanitizeEmail.activate?(message)
|
204
53
|
|
205
|
-
with_user_names = self.inject_user_names(real_addresses, sanitized_addresses)
|
206
|
-
#puts "real_addresses 2: #{real_addresses}"
|
207
|
-
#puts "override_email 5: #{type} - #{with_user_names}"
|
208
|
-
# Otherwise inject the email as the 'user name'
|
209
|
-
return with_user_names
|
210
54
|
end
|
211
55
|
|
212
56
|
end # end Class Bleach
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SanitizeEmail
|
2
|
+
module MailHeaderTools
|
3
|
+
|
4
|
+
def self.prepend_subject_array(message)
|
5
|
+
prepend = []
|
6
|
+
prepend << SanitizeEmail::MailHeaderTools.prepend_email_to_subject(message.to) if SanitizeEmail.use_actual_email_prepended_to_subject
|
7
|
+
prepend << SanitizeEmail::MailHeaderTools.prepend_environment_to_subject if SanitizeEmail.use_actual_environment_prepended_to_subject
|
8
|
+
prepend
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.prepend_environment_to_subject
|
12
|
+
"[#{Rails.env}]" if defined?(Rails) && Rails.env.present?
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.prepend_email_to_subject(actual_addresses)
|
16
|
+
"(#{actual_addresses.join(',').gsub(/@/, ' at ').gsub(/[<>]/, '~')})" if actual_addresses.respond_to?(:join)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.add_original_addresses_as_headers(message)
|
20
|
+
## Add headers by string concat. Setting hash values on message.headers does nothing, strangely. http://goo.gl/v46GY
|
21
|
+
{
|
22
|
+
'X-Sanitize-Email-To' => message.to, # can be an array
|
23
|
+
'X-Sanitize-Email-Cc' => message.cc # can be an array
|
24
|
+
# Don't write out the BCC, as those addresses should not be visible in message headers for obvious reasons
|
25
|
+
}.each { |k, v|
|
26
|
+
# For each type of address line
|
27
|
+
SanitizeEmail::MailHeaderTools.update_header(k, v, message)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.prepend_custom_subject(message)
|
32
|
+
message.subject.insert(0, SanitizeEmail::MailHeaderTools.prepend_subject_array(message).join(' ') + ' ')
|
33
|
+
end
|
34
|
+
|
35
|
+
# Add headers by string concat. Setting hash values on message.headers does nothing, strangely. http://goo.gl/v46GY
|
36
|
+
def self.update_header(k, v, message)
|
37
|
+
# For each address, as v can be an array of addresses
|
38
|
+
Array(v).each_with_index { |a, index|
|
39
|
+
num = index + 1
|
40
|
+
header_key = num > 1 ?
|
41
|
+
"#{k}-#{index+1}" :
|
42
|
+
k
|
43
|
+
#puts "for #{num}: #{header_key}"
|
44
|
+
message.header[header_key] = a.to_s
|
45
|
+
# Old way
|
46
|
+
#message.header = message.header.to_s.strip + "\n#{k}: #{a}"
|
47
|
+
} if v
|
48
|
+
#puts "\nafter message.header:\n #{message.header}\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module SanitizeEmail
|
2
|
+
class OverriddenAddresses
|
3
|
+
|
4
|
+
class MissingTo < StandardError;
|
5
|
+
end
|
6
|
+
class UnknownOverride < StandardError;
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :overridden_to, :overridden_cc, :overridden_bcc,
|
10
|
+
:good_list, # White-listed addresses will not be molested as to, cc, or bcc
|
11
|
+
:bad_list, # Black-listed addresses will be removed from to, cc and bcc when sanitization is engaged
|
12
|
+
:sanitized_to, :sanitized_cc, :sanitized_bcc # Replace non-white-listed addresses with these sanitized addresses.
|
13
|
+
|
14
|
+
def initialize(message, args = {})
|
15
|
+
# Not using extract_options! because non-rails compatibility is a goal
|
16
|
+
@sanitized_to = args[:sanitized_to] || SanitizeEmail[:sanitized_to]
|
17
|
+
@sanitized_cc = args[:sanitized_cc] || SanitizeEmail[:sanitized_cc]
|
18
|
+
@sanitized_bcc = args[:sanitized_bcc] || SanitizeEmail[:sanitized_bcc]
|
19
|
+
@good_list = args[:good_list] || SanitizeEmail[:good_list] || []
|
20
|
+
@bad_list = args[:bad_list] || SanitizeEmail[:bad_list] || []
|
21
|
+
@overridden_to = self.to_override(message.to)
|
22
|
+
@overridden_cc = self.cc_override(message.cc)
|
23
|
+
@overridden_bcc = self.bcc_override(message.bcc)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Allow good listed email addresses, and then remove the bad listed addresses
|
27
|
+
def good_listize(real_addresses)
|
28
|
+
good_listed = self.clean_addresses(real_addresses, :good_list)
|
29
|
+
good_listed = self.clean_addresses(good_listed, :bad_list) unless good_listed.empty?
|
30
|
+
good_listed
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_override(actual_addresses)
|
34
|
+
to = override_email(:to, actual_addresses)
|
35
|
+
raise MissingTo, "after overriding :to (#{actual_addresses}) there are no addresses to send in To: header." if to.empty?
|
36
|
+
to.join(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
def cc_override(actual_addresses)
|
40
|
+
override_email(:cc, actual_addresses).join(',')
|
41
|
+
end
|
42
|
+
|
43
|
+
def bcc_override(actual_addresses)
|
44
|
+
override_email(:bcc, actual_addresses).join(',')
|
45
|
+
end
|
46
|
+
|
47
|
+
def override_email(type, actual_addresses)
|
48
|
+
# Normalized to an arrays
|
49
|
+
#puts "override_email 1: #{type} - #{actual_addresses}"
|
50
|
+
real_addresses = Array(actual_addresses)
|
51
|
+
|
52
|
+
#puts "override_email 2: #{type} - #{real_addresses}"
|
53
|
+
# If there were no original recipients, then we DO NOT override the nil with the sanitized recipients
|
54
|
+
return [] if real_addresses.empty?
|
55
|
+
|
56
|
+
good_listed = good_listize(real_addresses)
|
57
|
+
#puts "override_email 3: #{type} - #{good_listed}"
|
58
|
+
# If there are good_list addresses to send to then use them as is, no mods needed
|
59
|
+
return good_listed unless good_listed.empty?
|
60
|
+
|
61
|
+
# TODO: Allow overriding if an addressed email is on the good list?
|
62
|
+
# If there are no sanitized addresses we can't override!
|
63
|
+
sanitized_addresses = sanitize_addresses(type)
|
64
|
+
#puts "override_email 4: #{type} - #{sanitized_addresses}"
|
65
|
+
return [] if sanitized_addresses.empty?
|
66
|
+
|
67
|
+
# At this point it is assured that the address list will need to be sanitized
|
68
|
+
# One more check to ensure none of the configured sanitized email addresses are on the bad_list
|
69
|
+
sanitized_addresses = self.clean_addresses(sanitized_addresses, :bad_list)
|
70
|
+
#puts "override_email 5: #{type} - #{sanitized_addresses}"
|
71
|
+
|
72
|
+
# If we don't want to inject the 'email' in the 'user name' section of the sanitized recipients,
|
73
|
+
# then just return the default sanitized recipients
|
74
|
+
return sanitized_addresses unless SanitizeEmail.use_actual_email_as_sanitized_user_name
|
75
|
+
|
76
|
+
with_user_names = self.inject_user_names(real_addresses, sanitized_addresses)
|
77
|
+
#puts "real_addresses 2: #{real_addresses}"
|
78
|
+
#puts "override_email 6: #{type} - #{with_user_names}"
|
79
|
+
# Otherwise inject the email as the 'user name'
|
80
|
+
return with_user_names
|
81
|
+
end
|
82
|
+
|
83
|
+
def address_list_filter(list_type, address)
|
84
|
+
# TODO: How does this handle email addresses with user names like "Foo Example <foo@example.org>"
|
85
|
+
has_address = self.send(list_type).include?(address)
|
86
|
+
case list_type
|
87
|
+
when :good_list then
|
88
|
+
has_address ? address : nil
|
89
|
+
when :bad_list then
|
90
|
+
has_address ? nil : address
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def inject_user_names(real_addresses, sanitized_addresses)
|
95
|
+
real_addresses.inject([]) do |result, real_recipient|
|
96
|
+
if real_recipient.nil?
|
97
|
+
new_recipient = sanitized_addresses
|
98
|
+
else
|
99
|
+
#puts "SANITIZED: #{sanitized_addresses}"
|
100
|
+
new_recipient = sanitized_addresses.map { |sanitized| "#{real_recipient.gsub(/@/, ' at ').gsub(/[<>]/, '~')} <#{sanitized}>" }
|
101
|
+
end
|
102
|
+
result << new_recipient
|
103
|
+
result
|
104
|
+
end.flatten
|
105
|
+
end
|
106
|
+
|
107
|
+
def clean_addresses(addresses, list_type)
|
108
|
+
# Normalize addresses just in case it isn't an array yet
|
109
|
+
addresses.map { |address|
|
110
|
+
# If this address is on the good list then let it pass
|
111
|
+
self.address_list_filter(list_type, address)
|
112
|
+
}.compact
|
113
|
+
end
|
114
|
+
|
115
|
+
def sanitize_addresses(type)
|
116
|
+
case type
|
117
|
+
when :to then
|
118
|
+
Array(self.sanitized_to)
|
119
|
+
when :cc then
|
120
|
+
Array(self.sanitized_cc)
|
121
|
+
when :bcc then
|
122
|
+
Array(self.sanitized_bcc)
|
123
|
+
else
|
124
|
+
raise UnknownOverride, "unknown email override"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
data/sanitize_email.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Peter Boling", "John Trupiano", "George Anderson"]
|
9
9
|
s.summary = "Rails/Sinatra/Mail gem: Test email abilities without ever sending a message to actual live addresses"
|
10
10
|
s.description = "In Rails, Sinatra, or simply the mail gem: Aids in development, testing, qa, and production troubleshooting of email issues without worrying that emails will get sent to actual live addresses."
|
11
|
-
s.email = ["peter.boling@gmail.com"
|
11
|
+
s.email = ["peter.boling@gmail.com"]
|
12
12
|
s.extra_rdoc_files = [
|
13
13
|
"CHANGELOG.md",
|
14
14
|
"LICENSE",
|
data/spec/sanitize_email_spec.rb
CHANGED
@@ -60,6 +60,12 @@ describe SanitizeEmail do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
def sanitary_mail_delivery_multiple_recipients(config_options = {})
|
64
|
+
SanitizeEmail.sanitary(config_options) do
|
65
|
+
mail_delivery_multiple_recipients
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
63
69
|
def unsanitary_mail_delivery
|
64
70
|
SanitizeEmail.unsanitary do
|
65
71
|
mail_delivery
|
@@ -77,6 +83,17 @@ describe SanitizeEmail do
|
|
77
83
|
end
|
78
84
|
end
|
79
85
|
|
86
|
+
def mail_delivery_multiple_recipients
|
87
|
+
@email_message = Mail.deliver do
|
88
|
+
from 'from@example.org'
|
89
|
+
to %w( to1@example.org to2@example.org to3@example.org )
|
90
|
+
cc %w( cc1@example.org cc2@example.org cc3@example.org )
|
91
|
+
bcc %w( bcc1@example.org bcc2@example.org bcc3@example.org )
|
92
|
+
reply_to 'reply_to@example.org'
|
93
|
+
subject 'original subject'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
80
97
|
context "module methods" do
|
81
98
|
before(:each) do
|
82
99
|
sanitize_spec_dryer
|
@@ -124,6 +141,8 @@ describe SanitizeEmail do
|
|
124
141
|
@email_message.should have_to("to@sanitize_email.org")
|
125
142
|
@email_message.should have_cc("cc@sanitize_email.org")
|
126
143
|
@email_message.should have_bcc("bcc@sanitize_email.org")
|
144
|
+
end
|
145
|
+
it "should set headers" do
|
127
146
|
@email_message.should have_header("X-Sanitize-Email-To", "to@example.org")
|
128
147
|
@email_message.should have_header("X-Sanitize-Email-Cc", "cc@example.org")
|
129
148
|
@email_message.should_not have_header("X-Sanitize-Email-Bcc", "bcc@sanitize_email.org")
|
@@ -134,6 +153,51 @@ describe SanitizeEmail do
|
|
134
153
|
end
|
135
154
|
end
|
136
155
|
|
156
|
+
context "sanitary with multiple recipients" do
|
157
|
+
before(:each) do
|
158
|
+
configure_sanitize_email
|
159
|
+
sanitary_mail_delivery_multiple_recipients
|
160
|
+
end
|
161
|
+
it "should not alter non-sanitized attributes" do
|
162
|
+
@email_message.should have_from('from@example.org')
|
163
|
+
@email_message.should have_reply_to('reply_to@example.org')
|
164
|
+
end
|
165
|
+
it "should not prepend overrides" do
|
166
|
+
@email_message.should_not have_to_username("to at sanitize_email.org")
|
167
|
+
@email_message.should_not have_subject("(to at sanitize_email.org)")
|
168
|
+
end
|
169
|
+
it "should override" do
|
170
|
+
@email_message.should have_to("to@sanitize_email.org")
|
171
|
+
@email_message.should have_cc("cc@sanitize_email.org")
|
172
|
+
@email_message.should have_bcc("bcc@sanitize_email.org")
|
173
|
+
end
|
174
|
+
it "should set headers for sanitized :to recipients" do
|
175
|
+
@email_message.should have_header("X-Sanitize-Email-To", "to1@example.org")
|
176
|
+
@email_message.should_not have_header("X-Sanitize-Email-To-0", "to1@example.org")
|
177
|
+
@email_message.should_not have_header("X-Sanitize-Email-To-1", "to1@example.org")
|
178
|
+
@email_message.should have_header("X-Sanitize-Email-To-2", "to2@example.org")
|
179
|
+
@email_message.should have_header("X-Sanitize-Email-To-3", "to3@example.org")
|
180
|
+
end
|
181
|
+
it "should set headers for sanitized :cc recipients" do
|
182
|
+
@email_message.should have_header("X-Sanitize-Email-Cc", "cc1@example.org")
|
183
|
+
@email_message.should_not have_header("X-Sanitize-Email-Cc-0", "cc1@example.org")
|
184
|
+
@email_message.should_not have_header("X-Sanitize-Email-Cc-1", "cc1@example.org")
|
185
|
+
@email_message.should have_header("X-Sanitize-Email-Cc-2", "cc2@example.org")
|
186
|
+
@email_message.should have_header("X-Sanitize-Email-Cc-3", "cc3@example.org")
|
187
|
+
end
|
188
|
+
it "should not set headers for sanitized :bcc recipients" do
|
189
|
+
@email_message.should_not have_header("X-Sanitize-Email-Bcc", "bcc1@sanitize_email.org")
|
190
|
+
@email_message.should_not have_header("X-Sanitize-Email-Bcc-0", "bcc1@sanitize_email.org")
|
191
|
+
@email_message.should_not have_header("X-Sanitize-Email-Bcc-1", "bcc1@sanitize_email.org")
|
192
|
+
@email_message.should_not have_header("X-Sanitize-Email-Bcc-2", "bcc2@sanitize_email.org")
|
193
|
+
@email_message.should_not have_header("X-Sanitize-Email-Bcc-3", "bcc3@sanitize_email.org")
|
194
|
+
end
|
195
|
+
it "should not prepend originals by default" do
|
196
|
+
@email_message.should_not have_to_username("to at example.org <to@sanitize_email.org>")
|
197
|
+
@email_message.should_not have_subject("(to at example.org) original subject")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
137
201
|
context "force_sanitize" do
|
138
202
|
context "true" do
|
139
203
|
before(:each) do
|
@@ -150,6 +214,8 @@ describe SanitizeEmail do
|
|
150
214
|
@email_message.should have_to("to@sanitize_email.org")
|
151
215
|
@email_message.should have_cc("cc@sanitize_email.org")
|
152
216
|
@email_message.should have_bcc("bcc@sanitize_email.org")
|
217
|
+
end
|
218
|
+
it "should set headers" do
|
153
219
|
@email_message.should have_header("X-Sanitize-Email-To", "to@example.org")
|
154
220
|
@email_message.should have_header("X-Sanitize-Email-Cc", "cc@example.org")
|
155
221
|
@email_message.should_not have_header("X-Sanitize-Email-Bcc", "bcc@sanitize_email.org")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sanitize_email
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-08-
|
14
|
+
date: 2013-08-30 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rails
|
@@ -216,6 +216,8 @@ files:
|
|
216
216
|
- lib/sanitize_email/config.rb
|
217
217
|
- lib/sanitize_email/deprecation.rb
|
218
218
|
- lib/sanitize_email/engine.rb
|
219
|
+
- lib/sanitize_email/mail_header_tools.rb
|
220
|
+
- lib/sanitize_email/overridden_addresses.rb
|
219
221
|
- lib/sanitize_email/railtie.rb
|
220
222
|
- lib/sanitize_email/rspec_matchers.rb
|
221
223
|
- lib/sanitize_email/test_helpers.rb
|