sanitize_email 0.3.9 → 1.0.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/CHANGELOG +23 -0
- data/Gemfile +11 -11
- data/Gemfile.lock +129 -0
- data/{LICENSE.txt → MIT-LICENSE} +1 -3
- data/README.rdoc +28 -71
- data/Rakefile +54 -9
- data/VERSION.yml +4 -4
- data/lib/sanitize_email.rb +28 -9
- data/lib/sanitize_email/config.rb +34 -0
- data/lib/sanitize_email/engine.rb +12 -0
- data/lib/sanitize_email/hook.rb +30 -0
- data/lib/sanitize_email/railtie.rb +12 -0
- data/lib/sanitize_email/sanitizer.rb +73 -0
- data/lib/sanitize_email/version.rb +3 -1
- data/sanitize_email.gemspec +80 -21
- data/spec/sanitize_email_spec.rb +68 -0
- data/spec/spec_helper.rb +40 -0
- data/spec/tmp/mail_dump/1343461037_3f3edd7/plain.html +76 -0
- metadata +201 -68
- checksums.yaml +0 -7
- data/.gitignore +0 -20
- data/CHANGELOG.md +0 -27
- data/lib/sanitize_email/custom_environments.rb +0 -21
- data/lib/sanitize_email/sanitize_email.rb +0 -114
- data/test/sample_mailer.rb +0 -24
- data/test/sanitize_email_test.rb +0 -76
- data/test/test_helper.rb +0 -25
@@ -0,0 +1,34 @@
|
|
1
|
+
module SanitizeEmail
|
2
|
+
class Config
|
3
|
+
cattr_accessor :config
|
4
|
+
self.config ||= {
|
5
|
+
# Adds the following class attributes to the classes that include NinthBit::SanitizeEmail
|
6
|
+
:force_sanitize => nil,
|
7
|
+
|
8
|
+
# Specify the BCC addresses for the messages that go out in 'local' environments
|
9
|
+
:sanitized_bcc => nil,
|
10
|
+
|
11
|
+
# Specify the CC addresses for the messages that go out in 'local' environments
|
12
|
+
:sanitized_cc => nil,
|
13
|
+
|
14
|
+
# The recipient addresses for the messages, either as a string (for a single
|
15
|
+
# address) or an array (for multiple addresses) that go out in 'local' environments
|
16
|
+
:sanitized_recipients => nil,
|
17
|
+
|
18
|
+
# Use the 'real' email address as the username for the sanitized email address
|
19
|
+
# e.g. "real@example.com <sanitized@example.com>"
|
20
|
+
:use_actual_email_as_sanitized_user_name => false,
|
21
|
+
|
22
|
+
# Prepend the 'real' email address onto the Subject line of the message
|
23
|
+
# e.g. "real@example.com rest of subject"
|
24
|
+
:use_actual_email_prepended_to_subject => false,
|
25
|
+
|
26
|
+
:local_environments => %w( development test )
|
27
|
+
}
|
28
|
+
|
29
|
+
def self.configure &block
|
30
|
+
yield self.config
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#Copyright (c) 2008-12 Peter H. Boling of 9thBit LLC
|
2
|
+
#Released under the MIT license
|
3
|
+
# For Rails >= 3.1
|
4
|
+
module SanitizeEmail
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
|
7
|
+
config.to_prepare do
|
8
|
+
ActionMailer::Base.register_interceptor(SanitizeEmail::Hook)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#Copyright (c) 2008-12 Peter H. Boling of 9thBit LLC
|
2
|
+
#Released under the MIT license
|
3
|
+
|
4
|
+
module SanitizeEmail
|
5
|
+
class Hook
|
6
|
+
|
7
|
+
include SanitizeEmail::Sanitizer
|
8
|
+
|
9
|
+
def self.delivering_email(message)
|
10
|
+
if self.localish?
|
11
|
+
message.subject = self.subject_override(message.subject, message.to)
|
12
|
+
message.to = self.recipients_override(message.to)
|
13
|
+
message.cc = self.cc_override(message.cc)
|
14
|
+
message.bcc = self.bcc_override(message.bcc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.consider_local?
|
19
|
+
SanitizeEmail.local_environments.include?(Rails.env) if defined?(Rails)
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method will be called by the Hook to determine if an override should occur
|
23
|
+
def self.localish?
|
24
|
+
!SanitizeEmail.force_sanitize.nil? ? SanitizeEmail.force_sanitize : self.consider_local?
|
25
|
+
end
|
26
|
+
|
27
|
+
end # end Class Hook
|
28
|
+
end # end Module SanitizeEmail
|
29
|
+
|
30
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#Copyright (c) 2008-12 Peter H. Boling of 9thBit LLC
|
2
|
+
#Released under the MIT license
|
3
|
+
# For Rails 3.0, which didn't yet support Engines'
|
4
|
+
module SanitizeEmail
|
5
|
+
class Railtie < ::Rails::Railtie
|
6
|
+
|
7
|
+
config.before_configuration do
|
8
|
+
ActionMailer::Base.register_interceptor(SanitizeEmail::Hook)
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#Copyright (c) 2008-12 Peter H. Boling of 9thBit LLC
|
2
|
+
#Released under the MIT license
|
3
|
+
module SanitizeEmail
|
4
|
+
module Sanitizer
|
5
|
+
def self.included(base)
|
6
|
+
base.extend SanitizeEmail::Sanitizer::ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
def subject_override(real_subject, actual_addresses)
|
12
|
+
if actual_addresses.nil? || !SanitizeEmail.use_actual_email_prepended_to_subject
|
13
|
+
real_subject
|
14
|
+
else
|
15
|
+
"(#{actual_addresses.join(',').gsub(/@/,' at ').gsub(/[<>]/,'~')}) #{real_subject}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def recipients_override(actual_addresses)
|
20
|
+
override_email(:recipients, actual_addresses)
|
21
|
+
end
|
22
|
+
|
23
|
+
def cc_override(actual_addresses)
|
24
|
+
override_email(:cc, actual_addresses)
|
25
|
+
end
|
26
|
+
|
27
|
+
def bcc_override(actual_addresses)
|
28
|
+
override_email(:bcc, actual_addresses)
|
29
|
+
end
|
30
|
+
|
31
|
+
#######
|
32
|
+
private
|
33
|
+
#######
|
34
|
+
|
35
|
+
def override_email(type, actual_addresses)
|
36
|
+
real_addresses, sanitized_addresses = case type
|
37
|
+
when :recipients
|
38
|
+
[actual_addresses, SanitizeEmail.sanitized_recipients]
|
39
|
+
when :cc
|
40
|
+
[actual_addresses, SanitizeEmail.sanitized_cc]
|
41
|
+
when :bcc
|
42
|
+
[actual_addresses, SanitizeEmail.sanitized_bcc]
|
43
|
+
else raise "sanitize_email error: unknown email override"
|
44
|
+
end
|
45
|
+
# Normalize to an array
|
46
|
+
real_addresses = [real_addresses] unless real_addresses.is_a?(Array)
|
47
|
+
# Normalize to an array
|
48
|
+
sanitized_addresses = [sanitized_addresses] unless sanitized_addresses.is_a?(Array)
|
49
|
+
|
50
|
+
# If there were no original recipients, then we DO NOT override the nil with the sanitized recipients
|
51
|
+
return nil if real_addresses.blank?
|
52
|
+
# If there are no sanitized addresses we can't override!
|
53
|
+
return nil if sanitized_addresses.blank?
|
54
|
+
# If we don't want to inject the actual email in the 'user name' section of the sanitized recipients,
|
55
|
+
# then just return the default sanitized recipients
|
56
|
+
return sanitized_addresses unless SanitizeEmail.use_actual_email_as_sanitized_user_name
|
57
|
+
|
58
|
+
out = real_addresses.inject([]) do |result, real_recipient|
|
59
|
+
if real_recipient.nil?
|
60
|
+
new_recipient = sanitized_addresses
|
61
|
+
else
|
62
|
+
new_recipient = sanitized_addresses.map{|sanitized| "#{real_recipient.gsub(/@/,' at ').gsub(/[<>]/,'~')} <#{sanitized}>"}
|
63
|
+
end
|
64
|
+
result << new_recipient
|
65
|
+
result
|
66
|
+
end.flatten
|
67
|
+
return out
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
data/sanitize_email.gemspec
CHANGED
@@ -1,26 +1,85 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
9
|
-
spec.authors = ["Peter Boling", "John Trupiano", "George Anderson"]
|
10
|
-
spec.email = ["peter.boling@gmail.com", "jtrupiano@gmail.com", "george@benevolentcode.com"]
|
11
|
-
spec.summary = %q{Test an application's email abilities without ever sending a message to actual live addresses}
|
12
|
-
spec.description = %q{Test an application's email abilities without ever sending a message to actual live addresses}
|
13
|
-
spec.homepage = "http://github.com/pboling/sanitize_email"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.rdoc_options = ["--charset=UTF-8"]
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "sanitize_email"
|
8
|
+
s.version = "1.0.0.alpha2"
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Peter Boling", "John Trupiano", "George Anderson"]
|
12
|
+
s.date = "2012-07-28"
|
13
|
+
s.description = "Tool to aid in development, testing, qa, and production troubleshooting of email issues without worrying that emails will get sent to actual live addresses."
|
14
|
+
s.email = ["peter.boling@gmail.com", "jtrupiano@gmail.com", "george@benevolentcode.com"]
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".rspec",
|
20
|
+
"CHANGELOG",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"MIT-LICENSE",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"VERSION.yml",
|
27
|
+
"init.rb",
|
28
|
+
"lib/sanitize_email.rb",
|
29
|
+
"lib/sanitize_email/config.rb",
|
30
|
+
"lib/sanitize_email/engine.rb",
|
31
|
+
"lib/sanitize_email/hook.rb",
|
32
|
+
"lib/sanitize_email/railtie.rb",
|
33
|
+
"lib/sanitize_email/sanitizer.rb",
|
34
|
+
"lib/sanitize_email/version.rb",
|
35
|
+
"sanitize_email.gemspec",
|
36
|
+
"spec/sanitize_email_spec.rb",
|
37
|
+
"spec/spec_helper.rb",
|
38
|
+
"spec/tmp/mail_dump/1343461037_3f3edd7/plain.html"
|
39
|
+
]
|
40
|
+
s.homepage = "http://github.com/pboling/sanitize_email"
|
41
|
+
s.licenses = ["MIT"]
|
42
|
+
s.require_paths = ["lib"]
|
43
|
+
s.rubygems_version = "1.8.24"
|
44
|
+
s.summary = "Test an application's email abilities without ever sending a message to actual live addresses"
|
21
45
|
|
22
|
-
|
46
|
+
if s.respond_to? :specification_version then
|
47
|
+
s.specification_version = 3
|
23
48
|
|
24
|
-
|
25
|
-
|
49
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
50
|
+
s.add_runtime_dependency(%q<rails>, ["> 3"])
|
51
|
+
s.add_runtime_dependency(%q<actionmailer>, ["> 3"])
|
52
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
53
|
+
s.add_development_dependency(%q<letter_opener>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<launchy>, [">= 0"])
|
55
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
56
|
+
s.add_development_dependency(%q<mail>, [">= 0"])
|
57
|
+
s.add_development_dependency(%q<rdoc>, [">= 3.12"])
|
58
|
+
s.add_development_dependency(%q<reek>, [">= 1.2.8"])
|
59
|
+
s.add_development_dependency(%q<roodi>, [">= 2.1.0"])
|
60
|
+
else
|
61
|
+
s.add_dependency(%q<rails>, ["> 3"])
|
62
|
+
s.add_dependency(%q<actionmailer>, ["> 3"])
|
63
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
64
|
+
s.add_dependency(%q<letter_opener>, [">= 0"])
|
65
|
+
s.add_dependency(%q<launchy>, [">= 0"])
|
66
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
67
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
68
|
+
s.add_dependency(%q<rdoc>, [">= 3.12"])
|
69
|
+
s.add_dependency(%q<reek>, [">= 1.2.8"])
|
70
|
+
s.add_dependency(%q<roodi>, [">= 2.1.0"])
|
71
|
+
end
|
72
|
+
else
|
73
|
+
s.add_dependency(%q<rails>, ["> 3"])
|
74
|
+
s.add_dependency(%q<actionmailer>, ["> 3"])
|
75
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
76
|
+
s.add_dependency(%q<letter_opener>, [">= 0"])
|
77
|
+
s.add_dependency(%q<launchy>, [">= 0"])
|
78
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
79
|
+
s.add_dependency(%q<mail>, [">= 0"])
|
80
|
+
s.add_dependency(%q<rdoc>, [">= 3.12"])
|
81
|
+
s.add_dependency(%q<reek>, [">= 1.2.8"])
|
82
|
+
s.add_dependency(%q<roodi>, [">= 2.1.0"])
|
83
|
+
end
|
26
84
|
end
|
85
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SanitizeEmail do
|
4
|
+
|
5
|
+
SanitizeEmail::Config.configure do |config|
|
6
|
+
config[:sanitized_recipients] = 'to@sanitize_email.org'
|
7
|
+
config[:sanitized_bcc] = 'bcc@sanitize_email.org'
|
8
|
+
config[:sanitized_cc] = 'cc@sanitize_email.org'
|
9
|
+
config[:local_environments] = []
|
10
|
+
config[:use_actual_email_prepended_to_subject] = true
|
11
|
+
config[:use_actual_email_as_sanitized_user_name] = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def sanitize_mail_delivery(sanitization_switch = false)
|
15
|
+
# Ensure that localish? will returns sanitization_switch
|
16
|
+
SanitizeEmail::Config.config[:force_sanitize] = sanitization_switch
|
17
|
+
Launchy.should_receive(:open)
|
18
|
+
mail = Mail.deliver do
|
19
|
+
from 'from@example.org'
|
20
|
+
to 'to@example.org'
|
21
|
+
cc 'cc@example.org'
|
22
|
+
reply_to 'reply_to@example.org'
|
23
|
+
subject 'original subject'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
Launchy.stub(:open)
|
29
|
+
location = File.expand_path('../tmp/mail_dump', __FILE__)
|
30
|
+
FileUtils.rm_rf(location)
|
31
|
+
Mail.defaults do
|
32
|
+
delivery_method LetterOpener::DeliveryMethod, :location => location
|
33
|
+
end
|
34
|
+
Mail.register_interceptor(SanitizeEmail::Hook)
|
35
|
+
@location = location
|
36
|
+
end
|
37
|
+
|
38
|
+
context "localish? is false" do
|
39
|
+
it "alters nothing" do
|
40
|
+
sanitize_mail_delivery(false)
|
41
|
+
# All the email gets dumped to file once for each type of recipient (:to, :cc, :bcc)
|
42
|
+
# Each file is identical, so we only need to check one of them:
|
43
|
+
email = File.read(Dir["#{@location}/*/plain.html"].first)
|
44
|
+
email.should have_from("from@example.org")
|
45
|
+
email.should have_to("to@example.org")
|
46
|
+
# Letter Opener won't let us test the cc
|
47
|
+
#email.should have_cc("cc@example.org")
|
48
|
+
# Letter Opener won't let us test the bcc
|
49
|
+
#email.should have_bcc("cc@example.org")
|
50
|
+
email.should have_subject("original subject")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "localish? is true" do
|
55
|
+
it "should override" do
|
56
|
+
sanitize_mail_delivery(true)
|
57
|
+
# All the email gets dumped to file once for each type of recipient (:to, :cc, :bcc)
|
58
|
+
# Each file is identical, so we only need to check one of them:
|
59
|
+
email = File.read(Dir["#{@location}/*/plain.html"].first)
|
60
|
+
email.should have_from("from@example.org")
|
61
|
+
# Letter Opener won't let us test the to when the to has a 'user name'
|
62
|
+
#email.should have_to("~to at example.org~ <to@sanitize_email.org>")
|
63
|
+
# Letter Opener won't let us test the bcc
|
64
|
+
#email.should have_cc("cc@sanitize_email.org")
|
65
|
+
email.should have_subject("(to at example.org) original subject")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'sanitize_email'
|
2
|
+
require 'launchy'
|
3
|
+
require 'mail'
|
4
|
+
require 'rails'
|
5
|
+
require 'letter_opener'
|
6
|
+
|
7
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
10
|
+
config.run_all_when_everything_filtered = true
|
11
|
+
#config.filter_run :focus
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec::Matchers.define :have_from do |from|
|
15
|
+
match do |container|
|
16
|
+
container =~ Regexp.new(Regexp.escape(from))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
RSpec::Matchers.define :have_to do |to|
|
20
|
+
match do |container|
|
21
|
+
container =~ Regexp.new(Regexp.escape(to))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
RSpec::Matchers.define :have_cc do |cc|
|
25
|
+
match do |container|
|
26
|
+
container =~ Regexp.new(Regexp.escape(cc))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
# The ActionMailer :file delivery method never prints bcc recipients...
|
30
|
+
# so not testable as such, but with letter_opener we can work magic
|
31
|
+
RSpec::Matchers.define :have_bcc do |bcc|
|
32
|
+
match do |container|
|
33
|
+
container =~ Regexp.new(Regexp.escape(bcc))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RSpec::Matchers.define :have_subject do |subject|
|
37
|
+
match do |container|
|
38
|
+
container =~ Regexp.new(Regexp.escape(subject))
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
<style type="text/css">
|
2
|
+
#message_headers {
|
3
|
+
position: absolute;
|
4
|
+
top: 0px;
|
5
|
+
left: 0;
|
6
|
+
width: 100%;
|
7
|
+
height: 85px;
|
8
|
+
padding: 10px 0 0 0;
|
9
|
+
margin: 0;
|
10
|
+
background: #fff;
|
11
|
+
font-size: 12px;
|
12
|
+
font-family: "Lucida Grande";
|
13
|
+
border-bottom: 1px solid #dedede;
|
14
|
+
overflow: hidden;
|
15
|
+
}
|
16
|
+
|
17
|
+
#message_headers dl {
|
18
|
+
margin: 0;
|
19
|
+
padding: 0;
|
20
|
+
}
|
21
|
+
|
22
|
+
#message_headers dt {
|
23
|
+
width: 60px;
|
24
|
+
padding: 1px;
|
25
|
+
float: left;
|
26
|
+
text-align: right;
|
27
|
+
font-weight: bold;
|
28
|
+
color: #7f7f7f;
|
29
|
+
}
|
30
|
+
|
31
|
+
#message_headers dd {
|
32
|
+
margin-left: 70px;
|
33
|
+
padding: 1px;
|
34
|
+
}
|
35
|
+
|
36
|
+
#message_headers p.alternate {
|
37
|
+
position: absolute;
|
38
|
+
top: 0;
|
39
|
+
right: 15px;
|
40
|
+
}
|
41
|
+
|
42
|
+
#message_headers p.alternate a {
|
43
|
+
color: #09c;
|
44
|
+
}
|
45
|
+
|
46
|
+
pre#message_body {
|
47
|
+
padding: 10px;
|
48
|
+
word-wrap: break-word;
|
49
|
+
}
|
50
|
+
|
51
|
+
body {
|
52
|
+
margin-top: 96px;
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
|
56
|
+
<div id="message_headers">
|
57
|
+
<dl>
|
58
|
+
<dt>From:</dt>
|
59
|
+
<dd>from@example.org</dd>
|
60
|
+
|
61
|
+
<dt>Subject:</dt>
|
62
|
+
<dd><strong>(to at example.org) original subject</strong></dd>
|
63
|
+
|
64
|
+
<dt>Date:</dt>
|
65
|
+
<dd>Jul 28, 2012 03:37:17 AM EDT</dd>
|
66
|
+
|
67
|
+
<dt>To:</dt>
|
68
|
+
<dd>to@sanitize_email.org</dd>
|
69
|
+
</dl>
|
70
|
+
|
71
|
+
|
72
|
+
</div>
|
73
|
+
|
74
|
+
|
75
|
+
<pre id="message_body"></pre>
|
76
|
+
|