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.
@@ -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
@@ -1,3 +1,5 @@
1
+ #Copyright (c) 2008-12 Peter H. Boling of 9thBit LLC
2
+ #Released under the MIT license
1
3
  module SanitizeEmail
2
- VERSION = "0.3.9"
4
+ VERSION = '1.0.0.alpha2'
3
5
  end
@@ -1,26 +1,85 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'sanitize_email/version'
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 |spec|
7
- spec.name = "sanitize_email"
8
- spec.version = SanitizeEmail::VERSION
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
- spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
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
- spec.add_runtime_dependency(%q<actionmailer>, [">= 0",'<= 3.1'])
46
+ if s.respond_to? :specification_version then
47
+ s.specification_version = 3
23
48
 
24
- spec.add_development_dependency "bundler", "~> 1.5"
25
- spec.add_development_dependency "rake"
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
@@ -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
+