mail_safe 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  coverage
4
4
  rdoc
5
5
  pkg
6
+ .ginger
@@ -13,14 +13,14 @@ with a note stating where the email was originally intended to go.
13
13
  Github: http://github.com/myronmarston/mail_safe
14
14
 
15
15
  Gem:
16
- gem install mail_safe --source http://gemcutter.org
16
+ gem install mail_safe
17
17
 
18
18
  == Installation
19
19
 
20
- Load the gem in your non-production environments using Rails' 2.1+ gem support. For example, I'm loading this in
20
+ Load the gem in the appropriate environments using Rails' 2.1+ gem support. For example, I'm loading this in
21
21
  config/environments/development.rb and config/environments/staging.rb:
22
22
 
23
- config.gem 'mail_safe', :source => 'http://gemcutter.org'
23
+ config.gem 'mail_safe'
24
24
 
25
25
  IMPORTANT: Be sure not to load this in your production environment, otherwise, your emails won't be sent to the proper
26
26
  recipients. In your test environment, you probably won't want this, either--rails ensures that no emails are ever sent in the
@@ -69,6 +69,14 @@ When mail safe replaces an email address, it appends a notice to the bottom of t
69
69
 
70
70
  **************************************************
71
71
 
72
+ == Version Compatibility
73
+
74
+ specs.should pass if RUBY_VERSION =~ /^1.(8.6|8.7|9.1)$/ && Rails.version =~ /^(1.2.6|2.\d.\d|3.0.0.beta)$/
75
+
76
+ == Continuous Integration
77
+
78
+ You can see the current status of the spec suite, for Ruby 1.8.6 and 1.9.1, on {runcoderun.org}[http://runcoderun.com/myronmarston/mail_safe].
79
+
72
80
  == Copyright
73
81
 
74
82
  Copyright (c) 2009 Myron Marston, Kashless.org. See LICENSE for details.
data/Rakefile CHANGED
@@ -10,11 +10,8 @@ begin
10
10
  gem.homepage = "http://github.com/myronmarston/mail_safe"
11
11
  gem.authors = ["Myron Marston"]
12
12
 
13
- gem.add_dependency 'activesupport'
14
- gem.add_dependency 'actionmailer'
15
-
16
- gem.add_development_dependency 'Shoulda'
17
- gem.add_development_dependency 'mocha'
13
+ gem.add_dependency 'actionmailer', '>= 1.3.6'
14
+ gem.add_development_dependency 'rspec', '>= 1.2.9'
18
15
 
19
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
17
  end
@@ -22,32 +19,26 @@ rescue LoadError
22
19
  puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
23
20
  end
24
21
 
25
- require 'rake/testtask'
26
- Rake::TestTask.new(:test) do |test|
27
- test.libs << 'lib' << 'test'
28
- test.pattern = 'test/**/*_test.rb'
29
- test.verbose = false
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
30
26
  end
31
27
 
32
- begin
33
- require 'rcov/rcovtask'
34
- Rcov::RcovTask.new do |test|
35
- test.libs << 'test'
36
- test.pattern = 'test/**/*_test.rb'
37
- test.verbose = true
38
- end
39
- rescue LoadError
40
- task :rcov do
41
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
- end
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
43
32
  end
44
33
 
34
+ task :spec => :check_dependencies if defined?(Jeweler)
45
35
 
46
- task :default => :test
36
+ task :default => :spec
47
37
 
48
38
  require 'rake/rdoctask'
49
39
  Rake::RDocTask.new do |rdoc|
50
40
  if File.exist?('VERSION.yml')
41
+ require 'yaml' unless defined?(YAML) # seems to be needed for ruby 1.9.1
51
42
  config = YAML.load(File.read('VERSION.yml'))
52
43
  version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
53
44
  else
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 2
3
+ :minor: 3
4
4
  :patch: 0
5
5
  :build:
@@ -0,0 +1,34 @@
1
+ require 'ginger'
2
+
3
+ def create_scenario(version)
4
+ scenario = Ginger::Scenario.new("Rails #{version}")
5
+ scenario[/^action_?mailer$/] = version
6
+ scenario[/^action_?pack$/] = version
7
+ scenario[/^active_?support$/] = version
8
+ scenario
9
+ end
10
+
11
+ Ginger.configure do |config|
12
+ config.aliases["action_mailer"] = "actionmailer"
13
+ config.aliases["action_pack"] = "actionpack"
14
+ config.aliases["active_support"] = "activesupport"
15
+
16
+ rails3 = create_scenario('3.0.0.beta')
17
+ rails3['mail'] = '2.1.3'
18
+ config.scenarios << rails3
19
+
20
+ %w(
21
+ 2.3.5 2.3.4 2.3.3 2.3.2
22
+ 2.2.3 2.2.2
23
+ 2.1.2 2.1.1 2.1.0
24
+ 2.0.5 2.0.4 2.0.2 2.0.1 2.0.0
25
+ ).each do |version|
26
+ config.scenarios << create_scenario(version)
27
+ end
28
+
29
+ rails126 = Ginger::Scenario.new("Rails 1.2.6")
30
+ rails126[/^action_?mailer$/] = '1.3.6'
31
+ rails126[/^action_?pack$/] = '1.13.6'
32
+ rails126[/^active_?support$/] = '1.4.4'
33
+ config.scenarios << rails126
34
+ end
@@ -1,8 +1,12 @@
1
1
  require 'active_support'
2
2
  require 'action_mailer'
3
+ require 'action_mailer/version'
3
4
 
4
5
  require 'mail_safe/config'
5
- require 'mail_safe/action_mailer'
6
6
  require 'mail_safe/address_replacer'
7
7
 
8
- ActionMailer::Base.send(:include, MailSafe::ActionMailer) unless ActionMailer::Base.ancestors.include?(MailSafe::ActionMailer)
8
+ if ActionMailer::VERSION::MAJOR < 3
9
+ require 'mail_safe/rails2_hook'
10
+ else
11
+ require 'mail_safe/rails3_hook'
12
+ end
@@ -1,7 +1,6 @@
1
1
  module MailSafe
2
2
  class AddressReplacer
3
3
  class << self
4
- include ::ActionMailer::Utils
5
4
  ADDRESS_TYPES = [:to, :cc, :bcc].freeze
6
5
 
7
6
  def replace_external_addresses(mail)
@@ -33,8 +32,8 @@ module MailSafe
33
32
  return unless replaced_addresses.size > 0
34
33
 
35
34
  case part.content_type
36
- when 'text/plain' then add_text_postscript(part, replaced_addresses)
37
- when 'text/html' then add_html_postscript(part, replaced_addresses)
35
+ when %r{^text/plain} then add_text_postscript(part, replaced_addresses)
36
+ when %r{^text/html} then add_html_postscript(part, replaced_addresses)
38
37
  end
39
38
 
40
39
  part.parts.each { |p| add_body_postscript(p, replaced_addresses) }
@@ -60,7 +59,7 @@ The original recipients were:
60
59
  **************************************************
61
60
  EOS
62
61
 
63
- set_part_body(part, part.body + postscript)
62
+ add_postscript(part, postscript)
64
63
  end
65
64
 
66
65
  def add_html_postscript(part, replaced_addresses)
@@ -93,19 +92,29 @@ The original recipients were:
93
92
  </div>
94
93
  EOS
95
94
 
96
- set_part_body(part, part.body + postscript)
95
+ add_postscript(part, postscript)
97
96
  end
98
97
 
99
- def set_part_body(part, body)
100
- # taken from action mailer:
101
- # http://github.com/rails/rails/blob/05d7409ae5fd423be6f747ad553f659fcecbf548/actionmailer/lib/action_mailer/part.rb#L58-65
102
- case part.content_transfer_encoding.to_s.downcase
103
- when "base64" then
104
- part.body = TMail::Base64.folding_encode(body)
105
- when "quoted-printable"
106
- part.body = [normalize_new_lines(body)].pack("M*")
107
- else
108
- part.body = body
98
+ if ActionMailer::VERSION::MAJOR < 3
99
+ include ::ActionMailer::Utils
100
+
101
+ def add_postscript(part, postscript)
102
+ body = part.body + postscript
103
+
104
+ # taken from action mailer:
105
+ # http://github.com/rails/rails/blob/05d7409ae5fd423be6f747ad553f659fcecbf548/actionmailer/lib/action_mailer/part.rb#L58-65
106
+ case part.content_transfer_encoding.to_s.downcase
107
+ when "base64" then
108
+ part.body = TMail::Base64.folding_encode(body)
109
+ when "quoted-printable"
110
+ part.body = [normalize_new_lines(body)].pack("M*")
111
+ else
112
+ part.body = body
113
+ end
114
+ end
115
+ else
116
+ def add_postscript(part, postscript)
117
+ part.body = part.body.to_s + postscript
109
118
  end
110
119
  end
111
120
  end
@@ -6,7 +6,7 @@ module MailSafe
6
6
 
7
7
  def self.is_internal_address?(address)
8
8
  case internal_address_definition
9
- when Regexp then address =~ internal_address_definition
9
+ when Regexp then !!(address =~ internal_address_definition)
10
10
  when Proc then internal_address_definition.call(address)
11
11
  else
12
12
  return address.downcase == developer_email_address.downcase if developer_email_address
@@ -11,4 +11,6 @@ module MailSafe
11
11
  deliver_without_mail_safe!(mail)
12
12
  end
13
13
  end
14
- end
14
+ end
15
+
16
+ ActionMailer::Base.send(:include, MailSafe::ActionMailer) unless ActionMailer::Base.ancestors.include?(MailSafe::ActionMailer)
@@ -0,0 +1,11 @@
1
+ require 'mail'
2
+
3
+ module MailSafe
4
+ class MailInterceptor
5
+ def self.delivering_email(mail)
6
+ MailSafe::AddressReplacer.replace_external_addresses(mail) if mail
7
+ end
8
+
9
+ ::Mail.register_interceptor(self)
10
+ end
11
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mail_safe}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Myron Marston"]
12
- s.date = %q{2009-11-06}
12
+ s.date = %q{2010-02-24}
13
13
  s.email = %q{myron.marston@gmail.com}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -22,26 +22,29 @@ Gem::Specification.new do |s|
22
22
  "README.rdoc",
23
23
  "Rakefile",
24
24
  "VERSION.yml",
25
+ "ginger_scenarios.rb",
25
26
  "lib/mail_safe.rb",
26
- "lib/mail_safe/action_mailer.rb",
27
27
  "lib/mail_safe/address_replacer.rb",
28
28
  "lib/mail_safe/config.rb",
29
+ "lib/mail_safe/rails2_hook.rb",
30
+ "lib/mail_safe/rails3_hook.rb",
29
31
  "mail_safe.gemspec",
30
- "test/config_test.rb",
31
- "test/mailer_test.rb",
32
- "test/mailers/test_mailer.rb",
33
- "test/test_helper.rb"
32
+ "spec/spec/config_spec.rb",
33
+ "spec/spec/mailer_spec.rb",
34
+ "spec/spec/mailers/test_mailer.rb",
35
+ "spec/spec/spec.opts",
36
+ "spec/spec/spec_helper.rb"
34
37
  ]
35
38
  s.homepage = %q{http://github.com/myronmarston/mail_safe}
36
39
  s.rdoc_options = ["--charset=UTF-8"]
37
40
  s.require_paths = ["lib"]
38
- s.rubygems_version = %q{1.3.5}
41
+ s.rubygems_version = %q{1.3.6}
39
42
  s.summary = %q{Keep your ActionMailer emails from escaping into the wild during development.}
40
43
  s.test_files = [
41
- "test/config_test.rb",
42
- "test/mailer_test.rb",
43
- "test/mailers/test_mailer.rb",
44
- "test/test_helper.rb"
44
+ "spec/spec/config_spec.rb",
45
+ "spec/spec/mailer_spec.rb",
46
+ "spec/spec/mailers/test_mailer.rb",
47
+ "spec/spec/spec_helper.rb"
45
48
  ]
46
49
 
47
50
  if s.respond_to? :specification_version then
@@ -49,21 +52,15 @@ Gem::Specification.new do |s|
49
52
  s.specification_version = 3
50
53
 
51
54
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
- s.add_runtime_dependency(%q<activesupport>, [">= 0"])
53
- s.add_runtime_dependency(%q<actionmailer>, [">= 0"])
54
- s.add_development_dependency(%q<Shoulda>, [">= 0"])
55
- s.add_development_dependency(%q<mocha>, [">= 0"])
55
+ s.add_runtime_dependency(%q<actionmailer>, [">= 1.3.6"])
56
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
56
57
  else
57
- s.add_dependency(%q<activesupport>, [">= 0"])
58
- s.add_dependency(%q<actionmailer>, [">= 0"])
59
- s.add_dependency(%q<Shoulda>, [">= 0"])
60
- s.add_dependency(%q<mocha>, [">= 0"])
58
+ s.add_dependency(%q<actionmailer>, [">= 1.3.6"])
59
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
61
60
  end
62
61
  else
63
- s.add_dependency(%q<activesupport>, [">= 0"])
64
- s.add_dependency(%q<actionmailer>, [">= 0"])
65
- s.add_dependency(%q<Shoulda>, [">= 0"])
66
- s.add_dependency(%q<mocha>, [">= 0"])
62
+ s.add_dependency(%q<actionmailer>, [">= 1.3.6"])
63
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
67
64
  end
68
65
  end
69
66
 
@@ -0,0 +1,154 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe MailSafe::Config do
4
+ describe '#developer_email_address' do
5
+ after(:each) do
6
+ # clear class variable caching...
7
+ MailSafe::Config.class_eval do
8
+ remove_class_variable(:@@developer_email_address)
9
+ end
10
+ end
11
+
12
+ context 'when git is installed' do
13
+ before(:each) do
14
+ MailSafe::Config.should_receive(:`).with('git config user.email').once.and_return("developer@domain.com\n")
15
+ end
16
+
17
+ it "guesses the developer's email address using git" do
18
+ MailSafe::Config.developer_email_address.should == 'developer@domain.com'
19
+ end
20
+
21
+ it "caches the developer's email address so multiple system calls aren't made" do
22
+ MailSafe::Config.developer_email_address.should == MailSafe::Config.developer_email_address
23
+ end
24
+ end
25
+
26
+ context 'when git is not installed' do
27
+ before(:each) do
28
+ MailSafe::Config.should_receive(:`).with('git config user.email').once.and_return(nil)
29
+ end
30
+
31
+ it "returns nil" do
32
+ MailSafe::Config.developer_email_address.should be_nil
33
+ end
34
+
35
+ it "caches the developer's email address so multiple system calls aren't made" do
36
+ MailSafe::Config.developer_email_address.should == MailSafe::Config.developer_email_address
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#is_internal_address?' do
42
+ context 'when internal_address_definition is not set' do
43
+ before(:each) do
44
+ MailSafe::Config.internal_address_definition = nil
45
+ end
46
+
47
+ context 'and #developer_email_address has a value' do
48
+ before(:each) do
49
+ @developer_address = 'developer@domain.com'
50
+ MailSafe::Config.should_receive(:developer_email_address).at_least(1).and_return(@developer_address)
51
+ end
52
+
53
+ it 'returns true when passed the developer email address' do
54
+ MailSafe::Config.is_internal_address?(@developer_address).should be_true
55
+ end
56
+
57
+ it 'returns true when passed the developer email address with different casing' do
58
+ MailSafe::Config.is_internal_address?(@developer_address.upcase).should be_true
59
+ end
60
+
61
+ it 'returns false when passed another email address' do
62
+ MailSafe::Config.is_internal_address?('another-address@domain.com').should be_false
63
+ end
64
+ end
65
+
66
+ context 'and #developer_email_address has no value' do
67
+ before(:each) do
68
+ MailSafe::Config.should_receive(:developer_email_address).and_return(nil)
69
+ end
70
+
71
+ it 'raises an error' do
72
+ lambda { MailSafe::Config.is_internal_address?('abc@foo.com') }.should raise_error(MailSafe::InvalidConfigSettingError)
73
+ end
74
+ end
75
+ end
76
+
77
+ context 'when internal_address_definition is set to a regexp' do
78
+ before(:each) do
79
+ MailSafe::Config.internal_address_definition = /.*@example\.com/
80
+ end
81
+
82
+ it 'returns true if the address matches the regexp' do
83
+ MailSafe::Config.is_internal_address?('someone@example.com').should be_true
84
+ end
85
+
86
+ it 'returns false if the address does not match the regexp' do
87
+ MailSafe::Config.is_internal_address?('someone@another-domain.com').should be_false
88
+ end
89
+ end
90
+
91
+ context 'When internal_address_definition is set to a lambda, #is_internal_address?' do
92
+ before(:each) do
93
+ MailSafe::Config.internal_address_definition = lambda { |address| address.size < 15 }
94
+ end
95
+
96
+ it 'returns true if the lambda returns true for the given address' do
97
+ MailSafe::Config.is_internal_address?('abc@foo.com').should be_true
98
+ end
99
+
100
+ it 'returns false if the lambda returns false for the given address' do
101
+ MailSafe::Config.is_internal_address?('a-long-address@example.com').should be_false
102
+ end
103
+ end
104
+ end
105
+
106
+ describe '#get_replacement_address' do
107
+ context 'when replacement_address is set to a string' do
108
+ before(:each) do
109
+ MailSafe::Config.replacement_address = 'me@mydomain.com'
110
+ end
111
+
112
+ it 'returns the configured replacement address' do
113
+ MailSafe::Config.get_replacement_address('you@example.com').should == 'me@mydomain.com'
114
+ end
115
+ end
116
+
117
+ context 'when replacement_address is set to a proc' do
118
+ before(:each) do
119
+ MailSafe::Config.replacement_address = lambda { |address| "me+#{address.split('@').first}@mydomain.com" }
120
+ end
121
+
122
+ it 'returns the configured replacement address' do
123
+ MailSafe::Config.get_replacement_address('you@example.com').should == 'me+you@mydomain.com'
124
+ end
125
+ end
126
+
127
+ context 'when replacement_address is not set' do
128
+ before(:each) do
129
+ MailSafe::Config.replacement_address = nil
130
+ end
131
+
132
+ context 'and #developer_email_address has a value' do
133
+ before(:each) do
134
+ @developer_address = 'developer@domain.com'
135
+ MailSafe::Config.should_receive(:developer_email_address).at_least(1).and_return(@developer_address)
136
+ end
137
+
138
+ it 'returns the developer address' do
139
+ MailSafe::Config.get_replacement_address('you@example.com').should == @developer_address
140
+ end
141
+ end
142
+
143
+ context 'and #developer_email_address has no value' do
144
+ before(:each) do
145
+ MailSafe::Config.should_receive(:developer_email_address).and_return(nil)
146
+ end
147
+
148
+ it 'raises an error' do
149
+ lambda { MailSafe::Config.get_replacement_address('you@example.com') }.should raise_error(MailSafe::InvalidConfigSettingError)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,107 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe MailSafe do
4
+ TEXT_POSTSCRIPT_PHRASE = /The original recipients were:/
5
+ HTML_POSTSCRIPT_PHRASE = /<p>\s+The original recipients were:\s+<\/p>/
6
+
7
+ def deliver_message(message_name, *args)
8
+ if ActionMailer::VERSION::MAJOR < 3
9
+ TestMailer.send("deliver_#{message_name}", *args)
10
+ else
11
+ TestMailer.send(message_name, *args).deliver
12
+ end
13
+ end
14
+
15
+ def have_addresses(*addresses)
16
+ simple_matcher("have addresses #{addresses.inspect}") do |array|
17
+ array.to_a.sort == addresses
18
+ end
19
+ end
20
+
21
+ describe 'Delivering a plain text email to internal addresses' do
22
+ before(:each) do
23
+ MailSafe::Config.stub(:is_internal_address?).and_return(true)
24
+ @email = deliver_message(:plain_text_message, :to => 'internal-to@address.com', :bcc => 'internal-bcc@address.com', :cc => 'internal-cc@address.com')
25
+ end
26
+
27
+ it 'sends the email to the original addresses' do
28
+ @email.to.should have_addresses('internal-to@address.com')
29
+ @email.cc.should have_addresses('internal-cc@address.com')
30
+ @email.bcc.should have_addresses('internal-bcc@address.com')
31
+ end
32
+
33
+ it 'does not add a post script to the body' do
34
+ @email.body.to_s.should_not =~ TEXT_POSTSCRIPT_PHRASE
35
+ end
36
+ end
37
+
38
+ describe 'Delivering a plain text email to external addresses' do
39
+ before(:each) do
40
+ MailSafe::Config.stub(:is_internal_address?).and_return(false)
41
+ MailSafe::Config.stub(:get_replacement_address).and_return('replacement@example.com')
42
+ @email = deliver_message(:plain_text_message, :to => 'external-to@address.com', :bcc => 'external-bcc@address.com', :cc => 'external-cc@address.com')
43
+ end
44
+
45
+ it 'sends the email to the replacement address' do
46
+ @email.to.should have_addresses('replacement@example.com')
47
+ @email.cc.should have_addresses('replacement@example.com')
48
+ @email.bcc.should have_addresses('replacement@example.com')
49
+ end
50
+ end
51
+
52
+ def deliver_email_with_mix_of_internal_and_external_addresses(message_name)
53
+ MailSafe::Config.internal_address_definition = /internal/
54
+ MailSafe::Config.replacement_address = 'internal@domain.com'
55
+ @email = deliver_message(message_name,
56
+ {
57
+ :to => ['internal1@address.com', 'external1@address.com'],
58
+ :cc => ['internal1@address.com', 'internal2@address.com'],
59
+ :bcc => ['external1@address.com', 'external2@address.com']
60
+ }
61
+ )
62
+ end
63
+
64
+ describe 'Delivering a plain text email to a mix of internal and external addresses' do
65
+ before(:each) do
66
+ deliver_email_with_mix_of_internal_and_external_addresses(:plain_text_message)
67
+ end
68
+
69
+ it 'sends the email to the appropriate address' do
70
+ @email.to.should have_addresses('internal1@address.com', 'internal@domain.com')
71
+ @email.cc.should have_addresses('internal1@address.com', 'internal2@address.com')
72
+ @email.bcc.should have_addresses('internal@domain.com', 'internal@domain.com')
73
+ end
74
+
75
+ it 'adds a plain text post script to the body' do
76
+ @email.body.to_s.should =~ TEXT_POSTSCRIPT_PHRASE
77
+ end
78
+ end
79
+
80
+ describe 'Delivering an html email to a mix of internal and external addresses' do
81
+ before(:each) do
82
+ deliver_email_with_mix_of_internal_and_external_addresses(:html_message)
83
+ end
84
+
85
+ it 'adds an html post script to the body' do
86
+ @email.body.to_s.should =~ HTML_POSTSCRIPT_PHRASE
87
+ end
88
+ end
89
+
90
+ describe 'Delivering a multipart email to a mix of internal and external addresses' do
91
+ before(:each) do
92
+ deliver_email_with_mix_of_internal_and_external_addresses(:multipart_message)
93
+ end
94
+
95
+ def part(type)
96
+ @email.parts.detect { |p| p.content_type == type }.body.to_s
97
+ end
98
+
99
+ it 'adds a text post script to the body of the text part' do
100
+ part('text/plain').should =~ TEXT_POSTSCRIPT_PHRASE
101
+ end
102
+
103
+ it 'adds an html post script to the body of the html part' do
104
+ part('text/html').should =~ HTML_POSTSCRIPT_PHRASE
105
+ end
106
+ end
107
+ end
@@ -1,6 +1,14 @@
1
+ if ActionMailer::VERSION::MAJOR == 3
2
+ require 'action_dispatch/http/mime_type' # needs to be required to avoid an error: uninitialized constant AbstractController::Collector::Mime
3
+ end
4
+
1
5
  class TestMailer < ActionMailer::Base
2
6
  # template root must be set for multipart emails, or ActionMailer will throw an exception.
3
- self.template_root = File.dirname(__FILE__)
7
+ if respond_to?(:view_paths)
8
+ view_paths.unshift File.dirname(__FILE__)
9
+ else
10
+ template_root File.dirname(__FILE__)
11
+ end
4
12
 
5
13
  def plain_text_message(options)
6
14
  setup_recipients(options)
@@ -0,0 +1 @@
1
+ --color
@@ -1,7 +1,11 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'spec'
4
+ require 'spec/autorun'
1
5
  require 'rubygems'
2
- require 'test/unit'
3
- require 'shoulda'
4
- require 'mocha'
6
+ require 'ginger'
7
+ require 'mail_safe'
8
+ require 'mailers/test_mailer'
5
9
 
6
10
  begin
7
11
  require 'ruby-debug'
@@ -11,12 +15,7 @@ rescue LoadError
11
15
  # ruby-debug wasn't available so neither can the debugging be
12
16
  end
13
17
 
14
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
- $LOAD_PATH.unshift(File.dirname(__FILE__))
16
- require 'mail_safe'
17
- require 'mailers/test_mailer'
18
-
19
18
  ActionMailer::Base.delivery_method = :test
20
19
 
21
- class Test::Unit::TestCase
22
- end
20
+ Spec::Runner.configure do |config|
21
+ end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mail_safe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 0
9
+ version: 0.3.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Myron Marston
@@ -9,49 +14,37 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-11-06 00:00:00 -08:00
17
+ date: 2010-02-24 00:00:00 -08:00
13
18
  default_executable:
14
19
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: activesupport
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
20
  - !ruby/object:Gem::Dependency
26
21
  name: actionmailer
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
30
24
  requirements:
31
25
  - - ">="
32
26
  - !ruby/object:Gem::Version
33
- version: "0"
34
- version:
27
+ segments:
28
+ - 1
29
+ - 3
30
+ - 6
31
+ version: 1.3.6
32
+ type: :runtime
33
+ version_requirements: *id001
35
34
  - !ruby/object:Gem::Dependency
36
- name: Shoulda
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
40
38
  requirements:
41
39
  - - ">="
42
40
  - !ruby/object:Gem::Version
43
- version: "0"
44
- version:
45
- - !ruby/object:Gem::Dependency
46
- name: mocha
41
+ segments:
42
+ - 1
43
+ - 2
44
+ - 9
45
+ version: 1.2.9
47
46
  type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: "0"
54
- version:
47
+ version_requirements: *id002
55
48
  description:
56
49
  email: myron.marston@gmail.com
57
50
  executables: []
@@ -68,15 +61,18 @@ files:
68
61
  - README.rdoc
69
62
  - Rakefile
70
63
  - VERSION.yml
64
+ - ginger_scenarios.rb
71
65
  - lib/mail_safe.rb
72
- - lib/mail_safe/action_mailer.rb
73
66
  - lib/mail_safe/address_replacer.rb
74
67
  - lib/mail_safe/config.rb
68
+ - lib/mail_safe/rails2_hook.rb
69
+ - lib/mail_safe/rails3_hook.rb
75
70
  - mail_safe.gemspec
76
- - test/config_test.rb
77
- - test/mailer_test.rb
78
- - test/mailers/test_mailer.rb
79
- - test/test_helper.rb
71
+ - spec/spec/config_spec.rb
72
+ - spec/spec/mailer_spec.rb
73
+ - spec/spec/mailers/test_mailer.rb
74
+ - spec/spec/spec.opts
75
+ - spec/spec/spec_helper.rb
80
76
  has_rdoc: true
81
77
  homepage: http://github.com/myronmarston/mail_safe
82
78
  licenses: []
@@ -90,23 +86,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
90
86
  requirements:
91
87
  - - ">="
92
88
  - !ruby/object:Gem::Version
89
+ segments:
90
+ - 0
93
91
  version: "0"
94
- version:
95
92
  required_rubygems_version: !ruby/object:Gem::Requirement
96
93
  requirements:
97
94
  - - ">="
98
95
  - !ruby/object:Gem::Version
96
+ segments:
97
+ - 0
99
98
  version: "0"
100
- version:
101
99
  requirements: []
102
100
 
103
101
  rubyforge_project:
104
- rubygems_version: 1.3.5
102
+ rubygems_version: 1.3.6
105
103
  signing_key:
106
104
  specification_version: 3
107
105
  summary: Keep your ActionMailer emails from escaping into the wild during development.
108
106
  test_files:
109
- - test/config_test.rb
110
- - test/mailer_test.rb
111
- - test/mailers/test_mailer.rb
112
- - test/test_helper.rb
107
+ - spec/spec/config_spec.rb
108
+ - spec/spec/mailer_spec.rb
109
+ - spec/spec/mailers/test_mailer.rb
110
+ - spec/spec/spec_helper.rb
@@ -1,178 +0,0 @@
1
- require 'test_helper'
2
-
3
- class ConfigTest < Test::Unit::TestCase
4
- context '#developer_email_address' do
5
- teardown do
6
- # clear class variable caching...
7
- MailSafe::Config.class_eval do
8
- remove_class_variable(:@@developer_email_address)
9
- end
10
- end
11
-
12
- context 'when git is installed' do
13
- setup do
14
- backtick_call_count = 0
15
- # mock out the ` method. I can't find a simpler way to do this with mocha.
16
- Kernel.class_eval do
17
- define_method '`'.to_sym do |cmd|
18
- backtick_call_count += 1
19
- return "too many calls" if backtick_call_count > 1
20
- if cmd == 'git config user.email'
21
- "developer@domain.com\n"
22
- end
23
- end
24
- end
25
- end
26
-
27
- should "guess the developer's email address using git" do
28
- assert_equal 'developer@domain.com', MailSafe::Config.developer_email_address
29
- end
30
-
31
- should "cache the developer's email address so multiple system calls aren't made" do
32
- assert_equal MailSafe::Config.developer_email_address, MailSafe::Config.developer_email_address
33
- end
34
- end
35
-
36
- context 'when git is not installed' do
37
- setup do
38
- backtick_call_count = 0
39
- # mock out the ` method. I can't find a simpler way to do this with mocha.
40
- Kernel.class_eval do
41
- define_method '`'.to_sym do |cmd|
42
- backtick_call_count += 1
43
- return "too many calls" if backtick_call_count > 1
44
- if cmd == 'git config user.email'
45
- raise RuntimeError.new("Git is not installed")
46
- end
47
- end
48
- end
49
- end
50
-
51
- should "return nil" do
52
- assert_nil MailSafe::Config.developer_email_address
53
- end
54
-
55
- should "cache the developer's email address so multiple system calls aren't made" do
56
- assert_equal MailSafe::Config.developer_email_address, MailSafe::Config.developer_email_address
57
- end
58
- end
59
- end
60
-
61
- context '#is_internal_address?' do
62
- context 'when internal_address_definition is not set' do
63
- setup do
64
- MailSafe::Config.internal_address_definition = nil
65
- end
66
-
67
- context 'and #developer_email_address has a value' do
68
- setup do
69
- @developer_address = 'developer@domain.com'
70
- MailSafe::Config.expects(:developer_email_address).at_least_once.returns(@developer_address)
71
- end
72
-
73
- should 'return true when passed the developer email address' do
74
- assert MailSafe::Config.is_internal_address?(@developer_address)
75
- end
76
-
77
- should 'return true when passed the developer email address with different casing' do
78
- assert MailSafe::Config.is_internal_address?(@developer_address.upcase)
79
- end
80
-
81
- should 'return false when passed another email address' do
82
- assert !MailSafe::Config.is_internal_address?('another-address@domain.com')
83
- end
84
- end
85
-
86
- context 'and #developer_email_address has no value' do
87
- setup do
88
- MailSafe::Config.expects(:developer_email_address).returns(nil)
89
- end
90
-
91
- should 'raise an error' do
92
- assert_raise MailSafe::InvalidConfigSettingError do
93
- MailSafe::Config.is_internal_address?('abc@foo.com')
94
- end
95
- end
96
- end
97
- end
98
-
99
- context 'when internal_address_definition is set to a regexp' do
100
- setup do
101
- MailSafe::Config.internal_address_definition = /.*@example\.com/
102
- end
103
-
104
- should 'return true if the address matches the regexp' do
105
- assert MailSafe::Config.is_internal_address?('someone@example.com')
106
- end
107
-
108
- should 'return false if the address does not match the regexp' do
109
- assert !MailSafe::Config.is_internal_address?('someone@another-domain.com')
110
- end
111
- end
112
-
113
- context 'When internal_address_definition is set to a lambda, #is_internal_address?' do
114
- setup do
115
- MailSafe::Config.internal_address_definition = lambda { |address| address.size < 15 }
116
- end
117
-
118
- should 'return true if the lambda returns true for the given address' do
119
- assert MailSafe::Config.is_internal_address?('abc@foo.com')
120
- end
121
-
122
- should 'return false if the lambda returns false for the given address' do
123
- assert !MailSafe::Config.is_internal_address?('a-long-address@example.com')
124
- end
125
- end
126
- end
127
-
128
- context '#get_replacement_address' do
129
- context 'when replacement_address is set to a string' do
130
- setup do
131
- MailSafe::Config.replacement_address = 'me@mydomain.com'
132
- end
133
-
134
- should 'return the configured replacement address' do
135
- assert_equal 'me@mydomain.com', MailSafe::Config.get_replacement_address('you@example.com')
136
- end
137
- end
138
-
139
- context 'when replacement_address is set to a proc' do
140
- setup do
141
- MailSafe::Config.replacement_address = lambda { |address| "me+#{address.split('@').first}@mydomain.com" }
142
- end
143
-
144
- should 'return the configured replacement address' do
145
- assert_equal 'me+you@mydomain.com', MailSafe::Config.get_replacement_address('you@example.com')
146
- end
147
- end
148
-
149
- context 'when replacement_address is not set' do
150
- setup do
151
- MailSafe::Config.replacement_address = nil
152
- end
153
-
154
- context 'and #developer_email_address has a value' do
155
- setup do
156
- @developer_address = 'developer@domain.com'
157
- MailSafe::Config.expects(:developer_email_address).at_least_once.returns(@developer_address)
158
- end
159
-
160
- should 'return the developer address' do
161
- assert_equal @developer_address, MailSafe::Config.get_replacement_address('you@example.com')
162
- end
163
- end
164
-
165
- context 'and #developer_email_address has no value' do
166
- setup do
167
- MailSafe::Config.expects(:developer_email_address).returns(nil)
168
- end
169
-
170
- should 'raise an error' do
171
- assert_raise MailSafe::InvalidConfigSettingError do
172
- MailSafe::Config.get_replacement_address('you@example.com')
173
- end
174
- end
175
- end
176
- end
177
- end
178
- end
@@ -1,88 +0,0 @@
1
- require 'test_helper'
2
-
3
- class MailerTest < Test::Unit::TestCase
4
- TEXT_POSTSCRIPT_PHRASE = /The original recipients were:/
5
- HTML_POSTSCRIPT_PHRASE = /<p>\s+The original recipients were:\s+<\/p>/
6
-
7
- context 'Delivering a plain text email to internal addresses' do
8
- setup do
9
- MailSafe::Config.stubs(:is_internal_address? => true)
10
- @email = TestMailer.deliver_plain_text_message(:to => 'internal-to@address.com', :bcc => 'internal-bcc@address.com', :cc => 'internal-cc@address.com')
11
- end
12
-
13
- should 'send the email to the original addresses' do
14
- assert_equal ['internal-to@address.com'], @email.to
15
- assert_equal ['internal-cc@address.com'], @email.cc
16
- assert_equal ['internal-bcc@address.com'], @email.bcc
17
- end
18
-
19
- should 'not add a post script to the body' do
20
- assert_no_match TEXT_POSTSCRIPT_PHRASE, @email.body
21
- end
22
- end
23
-
24
- context 'Delivering a plain text email to external addresses' do
25
- setup do
26
- MailSafe::Config.stubs(:is_internal_address? => false, :get_replacement_address => 'replacement@example.com')
27
- @email = TestMailer.deliver_plain_text_message(:to => 'internal-to@address.com', :bcc => 'internal-bcc@address.com', :cc => 'internal-cc@address.com')
28
- end
29
-
30
- should 'send the email to the replacement address' do
31
- assert_equal ['replacement@example.com'], @email.to
32
- assert_equal ['replacement@example.com'], @email.cc
33
- assert_equal ['replacement@example.com'], @email.bcc
34
- end
35
- end
36
-
37
- def deliver_email_with_mix_of_internal_and_external_addresses(delivery_method)
38
- MailSafe::Config.internal_address_definition = /internal/
39
- MailSafe::Config.replacement_address = 'internal@domain.com'
40
- @email = TestMailer.send(delivery_method,
41
- {
42
- :to => ['internal1@address.com', 'external1@address.com'],
43
- :cc => ['internal1@address.com', 'internal2@address.com'],
44
- :bcc => ['external1@address.com', 'external2@address.com']
45
- }
46
- )
47
- end
48
-
49
- context 'Delivering a plain text email to a mix of internal and external addresses' do
50
- setup do
51
- deliver_email_with_mix_of_internal_and_external_addresses(:deliver_plain_text_message)
52
- end
53
-
54
- should 'send the email to the appropriate address' do
55
- assert_same_elements ['internal1@address.com', 'internal@domain.com'], @email.to
56
- assert_same_elements ['internal1@address.com', 'internal2@address.com'], @email.cc
57
- assert_same_elements ['internal@domain.com', 'internal@domain.com'], @email.bcc
58
- end
59
-
60
- should 'add a plain text post script to the body' do
61
- assert_match TEXT_POSTSCRIPT_PHRASE, @email.body
62
- end
63
- end
64
-
65
- context 'Delivering an html email to a mix of internal and external addresses' do
66
- setup do
67
- deliver_email_with_mix_of_internal_and_external_addresses(:deliver_html_message)
68
- end
69
-
70
- should 'add an html post script to the body' do
71
- assert_match HTML_POSTSCRIPT_PHRASE, @email.body
72
- end
73
- end
74
-
75
- context 'Delivering a multipart email to a mix of internal and external addresses' do
76
- setup do
77
- deliver_email_with_mix_of_internal_and_external_addresses(:deliver_multipart_message)
78
- end
79
-
80
- should 'add an text post script to the body of the text part' do
81
- assert_match TEXT_POSTSCRIPT_PHRASE, @email.parts.detect { |p| p.content_type == 'text/plain' }.body
82
- end
83
-
84
- should 'add an html post script to the body of the html part' do
85
- assert_match HTML_POSTSCRIPT_PHRASE, @email.parts.detect { |p| p.content_type == 'text/html' }.body
86
- end
87
- end
88
- end