sanitize_email 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|