mailsafe 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 047172ca62085b8affb85a38a9ffa18123dc8589
4
- data.tar.gz: a07b0d33e190716d9d4076f90dc41ea9fa08726d
3
+ metadata.gz: 67ad0adc4f46869bab060bd9c07f998e5515fc3b
4
+ data.tar.gz: e99ad41b2eae6e0e9e3c248d740ca5e29db51993
5
5
  SHA512:
6
- metadata.gz: c494132d2bd2f9ba140c836a689f713b51b01cb4a78fad6e4169c8ccaa52c6944bddf0b9decf32327eeb190bb355c12c04e23f07b1de16faf33442a4da1d094e
7
- data.tar.gz: 2924839ee61347f45107c12dd5af6e651deb196011144fc5d18b7d40726a7ffbec67fe133d8da534272be97c11b62b270e213203e43180d73a15eca75bbe97b5
6
+ metadata.gz: 75f2a2260bc81b28beee198fc22e36d9382065ac915892b1c901b9a715c8b21f2fb251cb4f9dceddaa7b765e96c9afefdeb0ebcc47a0d4a8cfa03526a9a170f8
7
+ data.tar.gz: 49259b685320f13a7858aa35b44c7f6e4d32b4177028876624ed0537815352aa6a26367cc6c54c7e5bdb9a9f9d5f8404bd871ebc5357be69d8d99da820fc3375
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ # 0.2.0
4
+
5
+ * Filter CC and BCC addresses ([#2](https://github.com/stemps/mailsafe/issues/2))
6
+
7
+ # 0.1.0
8
+
9
+ * First public version
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  [![Code Climate](https://codeclimate.com/github/stemps/mailsafe.png)](https://codeclimate.com/github/stemps/mailsafe)
2
+ [![Build Status](https://travis-ci.org/stemps/mailsafe.svg)](https://travis-ci.org/stemps/mailsafe)
2
3
  # Mailsafe
3
4
 
4
5
  Safe emailing for Rails. Prevents you from sending emails to real customers from non-production environments. You can choose to either re-route all emails to a single developer account or allow only recipients of your own domain.
data/Rakefile CHANGED
@@ -1 +1,5 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -3,7 +3,7 @@ require "mailsafe/version"
3
3
  require "mailsafe/railtie"
4
4
  require "mailsafe/change_subject_interceptor"
5
5
  require "mailsafe/reroute_interceptor"
6
- require "mailsafe/receipient_whitelist"
6
+ require "mailsafe/recipient_whitelist"
7
7
 
8
8
  module Mailsafe
9
9
  def self.setup
@@ -0,0 +1,52 @@
1
+ module Mailsafe
2
+ class RecipientWhitelist
3
+ def initialize(message)
4
+ @message = message
5
+ @allowed_domain_config = Mailsafe.allowed_domain
6
+ @allowed_domains = parse_allowed_domains
7
+ end
8
+
9
+ def filter_recipient_domains
10
+ return unless @allowed_domains.present?
11
+ [ :to, :cc, :bcc ].each { |rec_type| filter_receipient_type(rec_type) }
12
+ end
13
+
14
+ private
15
+
16
+ def filter_receipient_type(rec_type)
17
+ receivers = @message.send(rec_type)
18
+ return unless receivers
19
+
20
+ receivers.select! { |recipient| email_has_domain?(recipient) }
21
+ @message.send("#{rec_type}=", receivers)
22
+ end
23
+
24
+ def email_has_domain?(email_address)
25
+ email_domain = extract_domain_from_address(email_address)
26
+ email_domain.present? && @allowed_domains.include?(email_domain)
27
+ end
28
+
29
+ def extract_domain_from_address(email_address)
30
+ email_address.split("@")[1].try(:downcase)
31
+ end
32
+
33
+ def parse_allowed_domains
34
+ if @allowed_domain_config.present?
35
+ @allowed_domain_config.split(',').map(&:strip).map(&:downcase)
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ # Unfortunately, monkeypatching Mail is the only way I found to actually prevent sending an email
43
+ require 'mail'
44
+
45
+ class Mail::Message
46
+ def deliver_with_recipient_filter
47
+ Mailsafe::RecipientWhitelist.new(self).filter_recipient_domains
48
+ self.deliver_without_recipient_filter unless self.to.blank? || self.to.empty?
49
+ end
50
+
51
+ alias_method_chain :deliver, :recipient_filter
52
+ end
@@ -2,9 +2,20 @@ module Mailsafe
2
2
  class RerouteInterceptor
3
3
  def self.delivering_email(message)
4
4
  unless Mailsafe.override_receiver.blank?
5
- message.subject = "[#{message.to}] #{message.subject}"
5
+ message.subject = "[#{receivers(message)}] #{message.subject}"
6
6
  message.to = Mailsafe.override_receiver
7
+ message.cc = []
8
+ message.bcc = []
7
9
  end
8
10
  end
11
+
12
+ private
13
+
14
+ def self.receivers(message)
15
+ [ :to, :cc, :bcc ].map do |rec_type|
16
+ recs = message.send(rec_type)
17
+ "#{rec_type}: #{recs.join ', '}" if recs.present?
18
+ end.compact.join '; '
19
+ end
9
20
  end
10
21
  end
@@ -1,3 +1,3 @@
1
1
  module Mailsafe
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency "rspec", "~> 2.13.0"
23
+ spec.add_development_dependency "pry"
24
+ spec.add_development_dependency "rspec", "~> 3.2.0"
24
25
  spec.add_development_dependency "rails", "~> 4.1.5"
25
26
  end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+
3
+ module Mailsafe
4
+ describe RecipientWhitelist do
5
+
6
+ describe ".filter_recipient_domain" do
7
+ subject { Mail.new(to: to, cc: cc, bcc: bcc) }
8
+ let(:to) { ["to@gmail.com", "to@yahoo.com"] }
9
+ let(:cc) { ["cc@gmail.com", "cc@yahoo.com"] }
10
+ let(:bcc) { ["bcc@gmail.com", "bcc@yahoo.com"] }
11
+
12
+ context "allowed_domains configured" do
13
+ before do
14
+ Mailsafe.allowed_domain = "gmail.com"
15
+ RecipientWhitelist.new(subject).filter_recipient_domains
16
+ end
17
+
18
+ it "filters 'to' email addresses" do
19
+ expect(subject.to).to eq ["to@gmail.com"]
20
+ end
21
+
22
+ it "filters 'cc' email addresses" do
23
+ expect(subject.cc).to eq ["cc@gmail.com"]
24
+ end
25
+
26
+ it "filters 'bcc' email addresses" do
27
+ expect(subject.bcc).to eq ["bcc@gmail.com"]
28
+ end
29
+ end
30
+
31
+ context "uninitialized receivers" do
32
+ subject { Mail.new() }
33
+
34
+ before do
35
+ Mailsafe.allowed_domain = "gmail.com"
36
+ RecipientWhitelist.new(subject).filter_recipient_domains
37
+ end
38
+
39
+ it "Regression: and does not crash" do
40
+ expect(subject.to).to eq nil
41
+ expect(subject.cc).to eq nil
42
+ expect(subject.bcc).to eq nil
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "#email_has_domain" do
48
+ before { Mailsafe.allowed_domain = whitelist }
49
+ subject { RecipientWhitelist.new(double) }
50
+
51
+ context "single whitelisted domain" do
52
+ let(:whitelist) { "gmail.com" }
53
+
54
+ it "accepts the allowed domains" do
55
+ expect(subject.send(:email_has_domain?, "bert@gmail.com")).to be_truthy
56
+ end
57
+
58
+ it "does not accept other domains" do
59
+ expect(subject.send(:email_has_domain?, "bert@gmx.de")).to be_falsy
60
+ expect(subject.send(:email_has_domain?, "bert@yahoo.com")).to be_falsy
61
+ expect(subject.send(:email_has_domain?, "bert@ggmail.com")).to be_falsy
62
+ expect(subject.send(:email_has_domain?, "bert@gmail.com.de")).to be_falsy
63
+ end
64
+ end
65
+
66
+ context "multiple whitelisted domains" do
67
+ let(:whitelist) { "gmail.com, gmx.de" }
68
+
69
+ it "accepts the allowed domains" do
70
+ expect(subject.send(:email_has_domain?, "bert@gmail.com")).to be_truthy
71
+ expect(subject.send(:email_has_domain?, "bert@gmx.de")).to be_truthy
72
+ end
73
+
74
+ it "does not accept other domains" do
75
+ expect(subject.send(:email_has_domain?, "bert@yahoo.com")).to be_falsy
76
+ expect(subject.send(:email_has_domain?, "bert@ggmail.com")).to be_falsy
77
+ end
78
+ end
79
+
80
+ context "invalid email addresses" do
81
+ let(:whitelist) { "gmail.com" }
82
+
83
+ it "does not accept them" do
84
+ expect(subject.send(:email_has_domain?, "bert")).to be_falsy
85
+ end
86
+ end
87
+
88
+ context "invalid whitelist" do
89
+ let(:whitelist) { "gmail.com, " }
90
+
91
+ it "accepts the allowed domains" do
92
+ expect(subject.send(:email_has_domain?, "bert@gmail.com")).to be_truthy
93
+ end
94
+
95
+ it "does not accept other domains" do
96
+ expect(subject.send(:email_has_domain?, "bert@gmx.de")).to be_falsy
97
+ expect(subject.send(:email_has_domain?, "bert@yahoo.com")).to be_falsy
98
+ expect(subject.send(:email_has_domain?, "bert@ggmail.com")).to be_falsy
99
+ expect(subject.send(:email_has_domain?, "bert@gmail.com.de")).to be_falsy
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ module Mailsafe
4
+ describe RerouteInterceptor do
5
+
6
+ describe ".delivering_mail" do
7
+ subject { Mail.new(to: to, cc: cc, bcc: bcc, subject: mail_subject) }
8
+ let(:to) { nil }
9
+ let(:cc) { nil }
10
+ let(:bcc) { nil }
11
+ let(:override_rec) { nil }
12
+ let(:mail_subject) { "Hi!" }
13
+
14
+ before do
15
+ Mailsafe.override_receiver = override_rec
16
+ RerouteInterceptor.delivering_email(subject)
17
+ end
18
+
19
+ context "override_receiver is not set" do
20
+ let(:to) { "joe@example.com" }
21
+ let(:cc) { "jane@example.com" }
22
+ let(:bcc) { "bob@example.com" }
23
+
24
+ # leaves the email unchanged
25
+ specify { expect(subject.subject).to eq mail_subject }
26
+ specify { expect(subject.to).to eq [to] }
27
+ specify { expect(subject.cc).to eq [cc] }
28
+ specify { expect(subject.bcc).to eq [bcc] }
29
+ end
30
+
31
+ context "override_receiver is set" do
32
+ let(:override_rec) { "override@example.com" }
33
+
34
+ context "Message without any receivers" do
35
+ specify { expect(subject.subject).to eq "[] Hi!" }
36
+ specify { expect(subject.to).to eq [override_rec] }
37
+ specify { expect(subject.cc).to eq [] }
38
+ specify { expect(subject.bcc).to eq [] }
39
+ end
40
+
41
+ context "message with a 'to' receiver" do
42
+ let(:to) { "bob@example.com" }
43
+
44
+ specify { expect(subject.subject).to eq "[to: bob@example.com] Hi!" }
45
+ specify { expect(subject.to).to eq [override_rec] }
46
+ specify { expect(subject.cc).to eq [] }
47
+ specify { expect(subject.bcc).to eq [] }
48
+ end
49
+
50
+ context "message with multiple 'to' receivers" do
51
+ let(:to) { ["bob@example.com", "jane@example.com"] }
52
+
53
+ specify { expect(subject.subject).to eq "[to: bob@example.com, jane@example.com] Hi!" }
54
+ specify { expect(subject.to).to eq [override_rec] }
55
+ specify { expect(subject.cc).to eq [] }
56
+ specify { expect(subject.bcc).to eq [] }
57
+ end
58
+
59
+ context "message with 'to', 'cc' and 'bcc' receivers" do
60
+ let(:to) { ["bob@example.com", "jane@example.com"] }
61
+ let(:cc) { "joe@example.com" }
62
+ let(:bcc) { ["mary@example.com", "alice@example.com"] }
63
+
64
+ specify { expect(subject.subject).to eq "[to: bob@example.com, jane@example.com; cc: joe@example.com; bcc: mary@example.com, alice@example.com] Hi!" }
65
+ specify { expect(subject.to).to eq [override_rec] }
66
+ specify { expect(subject.cc).to eq [] }
67
+ specify { expect(subject.bcc).to eq [] }
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,10 +1,10 @@
1
+ require 'pry'
1
2
  require 'bundler/setup'
2
3
  Bundler.setup
3
4
 
4
5
  require 'mailsafe'
5
6
 
6
7
  RSpec.configure do |config|
7
- config.treat_symbols_as_metadata_keys_with_true_values = true
8
8
  config.run_all_when_everything_filtered = true
9
9
  config.filter_run :focus
10
10
 
metadata CHANGED
@@ -1,69 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailsafe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Stemplinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-19 00:00:00.000000000 Z
11
+ date: 2015-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ~>
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 2.13.0
61
+ version: 3.2.0
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ~>
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: 2.13.0
68
+ version: 3.2.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rails
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - ~>
73
+ - - "~>"
60
74
  - !ruby/object:Gem::Version
61
75
  version: 4.1.5
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - ~>
80
+ - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: 4.1.5
69
83
  description: Safe emailing for Rails
@@ -73,8 +87,9 @@ executables: []
73
87
  extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
76
- - .gitignore
77
- - .rspec
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - CHANGELOG.md
78
93
  - Gemfile
79
94
  - LICENSE.txt
80
95
  - README.md
@@ -82,11 +97,12 @@ files:
82
97
  - lib/mailsafe.rb
83
98
  - lib/mailsafe/change_subject_interceptor.rb
84
99
  - lib/mailsafe/railtie.rb
85
- - lib/mailsafe/receipient_whitelist.rb
100
+ - lib/mailsafe/recipient_whitelist.rb
86
101
  - lib/mailsafe/reroute_interceptor.rb
87
102
  - lib/mailsafe/version.rb
88
103
  - mailsafe.gemspec
89
- - spec/receipient_whitelist_spec.rb
104
+ - spec/recipient_whitelist_spec.rb
105
+ - spec/reroute_interceptor_spec.rb
90
106
  - spec/spec_helper.rb
91
107
  homepage: https://github.com/stemps/mailsafe
92
108
  licenses:
@@ -98,21 +114,22 @@ require_paths:
98
114
  - lib
99
115
  required_ruby_version: !ruby/object:Gem::Requirement
100
116
  requirements:
101
- - - '>='
117
+ - - ">="
102
118
  - !ruby/object:Gem::Version
103
119
  version: '0'
104
120
  required_rubygems_version: !ruby/object:Gem::Requirement
105
121
  requirements:
106
- - - '>='
122
+ - - ">="
107
123
  - !ruby/object:Gem::Version
108
124
  version: '0'
109
125
  requirements: []
110
126
  rubyforge_project:
111
- rubygems_version: 2.0.3
127
+ rubygems_version: 2.4.2
112
128
  signing_key:
113
129
  specification_version: 4
114
130
  summary: Safe emailing for Rails - do not send emails to real users from development
115
131
  or staging environments.
116
132
  test_files:
117
- - spec/receipient_whitelist_spec.rb
133
+ - spec/recipient_whitelist_spec.rb
134
+ - spec/reroute_interceptor_spec.rb
118
135
  - spec/spec_helper.rb
@@ -1,41 +0,0 @@
1
- require 'mailsafe/receipient_whitelist'
2
-
3
- module Mailsafe
4
- class ReceipientWhitelist
5
- def self.filter_receipient_domain(message)
6
- allowed_domain = Mailsafe.allowed_domain
7
- if allowed_domain.present?
8
- receipients = []
9
- message.to.each do |receipient|
10
- if email_has_domain?(receipient, allowed_domain)
11
- receipients << receipient
12
- end
13
- end
14
- message.to = receipients
15
- end
16
- end
17
-
18
- def self.email_has_domain?(email, allowed_domain_config)
19
- allowed_domains = allowed_domain_config.split(',').map(&:strip).map(&:downcase)
20
- email_domain = email.split("@")[1]
21
-
22
- if email_domain.present?
23
- allowed_domains.include? email_domain.downcase
24
- else
25
- false
26
- end
27
- end
28
- end
29
- end
30
-
31
- # Unfortunately, monkeypatching Mail is the only way I found to actually prevent sending an email
32
- require 'mail'
33
-
34
- class Mail::Message
35
- def deliver_with_recipient_filter
36
- Mailsafe::ReceipientWhitelist.filter_receipient_domain(self)
37
- self.deliver_without_recipient_filter unless self.to.blank? || self.to.empty?
38
- end
39
-
40
- alias_method_chain :deliver, :recipient_filter
41
- end
@@ -1,61 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Mailsafe
4
- RSpec.describe ReceipientWhitelist do
5
-
6
- describe ".email_has_domain" do
7
- context "single whitelisted domain" do
8
- let!(:whitelist) { "gmail.com" }
9
-
10
- it "accepts the allowed domains" do
11
- expect(ReceipientWhitelist.email_has_domain?("bert@gmail.com", whitelist)).to be_true
12
- end
13
-
14
- it "does not accept other domains" do
15
- expect(ReceipientWhitelist.email_has_domain?("bert@gmx.de", whitelist)).to be_false
16
- expect(ReceipientWhitelist.email_has_domain?("bert@yahoo.com", whitelist)).to be_false
17
- expect(ReceipientWhitelist.email_has_domain?("bert@ggmail.com", whitelist)).to be_false
18
- expect(ReceipientWhitelist.email_has_domain?("bert@gmail.com.de", whitelist)).to be_false
19
- end
20
- end
21
-
22
- context "multiple whitelisted domains" do
23
- let!(:whitelist) { "gmail.com, gmx.de" }
24
-
25
- it "accepts the allowed domains" do
26
- expect(ReceipientWhitelist.email_has_domain?("bert@gmail.com", whitelist)).to be_true
27
- expect(ReceipientWhitelist.email_has_domain?("bert@gmx.de", whitelist)).to be_true
28
- end
29
-
30
- it "does not accept other domains" do
31
- expect(ReceipientWhitelist.email_has_domain?("bert@yahoo.com", whitelist)).to be_false
32
- expect(ReceipientWhitelist.email_has_domain?("bert@ggmail.com", whitelist)).to be_false
33
- end
34
- end
35
-
36
- context "invalid email addresses" do
37
- let!(:whitelist) { "gmail.com" }
38
-
39
- it "does not accept them" do
40
- expect(ReceipientWhitelist.email_has_domain?("bert", whitelist)).to be_false
41
- end
42
- end
43
-
44
- context "invalid whitelist" do
45
- let!(:whitelist) { "gmail.com, " }
46
-
47
- it "accepts the allowed domains" do
48
- expect(ReceipientWhitelist.email_has_domain?("bert@gmail.com", whitelist)).to be_true
49
- end
50
-
51
- it "does not accept other domains" do
52
- expect(ReceipientWhitelist.email_has_domain?("bert@gmx.de", whitelist)).to be_false
53
- expect(ReceipientWhitelist.email_has_domain?("bert@yahoo.com", whitelist)).to be_false
54
- expect(ReceipientWhitelist.email_has_domain?("bert@ggmail.com", whitelist)).to be_false
55
- expect(ReceipientWhitelist.email_has_domain?("bert@gmail.com.de", whitelist)).to be_false
56
- end
57
- end
58
-
59
- end
60
- end
61
- end