mailpeek 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0235196fb58aaf81253349db5403378590dbf0b359a0f553fda33db73dac5072'
4
- data.tar.gz: b3646014f52e01d097d60a46dd5ae1cb2468e306af777f3d71bf9106d1b94786
3
+ metadata.gz: 8175b6629889a19c09ac2b9ea39791481afe4b14c07cdec0d8b63fd4c1529e3d
4
+ data.tar.gz: 5e2885db884fb3ca70db10b436c966d776a2fe1e6ac57f1b678469c27d703cf8
5
5
  SHA512:
6
- metadata.gz: 22786fdb89e523070567fee50898956592bed0ffdfddee8f4da0ffd7d7d4efe8cf6e9ace3bf3a9a5e88ca3028181fb2233241a09eb500ed1ec7d28a1a68b6dc6
7
- data.tar.gz: 39fb2a5a99003630057871273c1925da8d059c5364eb5345ae9b151131da32c2399be8b176854f72e8a3e5fb9a51f259ac58ed0302e78317e4b0ef7b581cbdd1
6
+ metadata.gz: 8582f7df76eb9123e3a9eef08006bd1b0676bb9ad56edd93b3b4fa9862f6e41548b04e0386dae477f04438781541f77dbfc734131689cf17722d5bbf8ee69e54
7
+ data.tar.gz: bc6cc33ceec866f1affe7f85408bc86a4cd955a960ee6bdc825af31dc095da00365a4a5db978e118e3deb3567b7199b91c6debee1b2c4216704c95117107d731
@@ -1,24 +1,22 @@
1
1
  require:
2
2
  - rubocop-performance
3
+ - rubocop-rspec
3
4
 
4
5
  AllCops:
5
6
  Exclude:
6
7
  - '**/bin/**/*'
8
+ Layout/LineLength:
9
+ Max: 80
10
+ Lint/AmbiguousBlockAssociation:
11
+ Enabled: false
7
12
  Metrics/AbcSize:
8
13
  Max: 30
9
- Style/BlockDelimiters:
10
- Enabled: false
11
14
  Metrics/BlockLength:
12
15
  Exclude:
13
16
  - '**/spec/**/*'
14
17
  - '**/lib/**/*.rake'
15
18
  Metrics/ClassLength:
16
19
  Max: 150
17
- Style/Lambda:
18
- Exclude:
19
- - 'app/models/**/*'
20
- Layout/LineLength:
21
- Max: 80
22
20
  Metrics/MethodLength:
23
21
  Max: 15
24
22
  Metrics/ModuleLength:
@@ -27,10 +25,13 @@ Naming/FileName:
27
25
  Exclude:
28
26
  - '**/Guardfile'
29
27
  - '**/Capfile'
30
- Lint/AmbiguousBlockAssociation:
28
+ Style/BlockDelimiters:
31
29
  Enabled: false
32
30
  Style/Documentation:
33
31
  Exclude:
34
32
  - '**/db/migrate/*'
35
33
  Style/EvalWithLocation:
36
34
  Enabled: false
35
+ Style/Lambda:
36
+ Exclude:
37
+ - 'app/models/**/*'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :rubocop, all_on_start: true, cli: ['-D'] do
4
+ watch(/.+\.rb$/)
5
+ watch(/.+\.rake$/)
6
+ watch(/.+\.jbuilder$/)
7
+ watch(/Rakefile$/)
8
+ watch(/Gemfile$/)
9
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
10
+ end
@@ -8,8 +8,9 @@ require 'mailpeek/web'
8
8
  require 'mailpeek/version'
9
9
 
10
10
  require 'json'
11
+ require 'tmpdir'
11
12
 
12
- # Public: Mailpeek
13
+ # Public: Mailpeek Base Class
13
14
  module Mailpeek
14
15
  def self.configuration
15
16
  @configuration ||= Configuration.new
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mail/check_delivery_params'
4
-
5
3
  module Mailpeek
6
4
  # Public: Stores config info for Mailpeek
7
5
  class Configuration
8
6
  attr_accessor :location, :limit
9
7
 
10
8
  def initialize
11
- @location = Rails.root.join('tmp', 'mailpeek')
9
+ @location = Dir.mktmpdir('mailpeek')
12
10
  @limit = 50
13
11
  end
14
12
  end
@@ -1,12 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mail/check_delivery_params'
4
-
5
3
  module Mailpeek
6
- # Public: Delivery
4
+ # Public: Handles consuming emails, checking configuration, creating
5
+ # directories, cleaning up emails and saving attachments
7
6
  class Delivery
8
- include Mail::CheckDeliveryParams if defined?(Mail::CheckDeliveryParams)
9
-
10
7
  class InvalidOption < StandardError; end
11
8
 
12
9
  attr_accessor :settings
@@ -17,40 +14,34 @@ module Mailpeek
17
14
  options[:limit] = options[:limit].to_i
18
15
 
19
16
  if options[:location].nil?
20
- raise InvalidOption, 'A location option is required when using Mailpeek'
17
+ raise InvalidOption, 'The Mailpeek location option is required'
21
18
  end
22
19
 
23
- # rubocop:disable Style/GuardClause
24
- if options[:limit].nil?
25
- raise InvalidOption, 'A limit option is required when using Mailpeek'
26
- elsif options[:limit] <= 0
27
- raise InvalidOption, 'A limit option is an invalid number'
20
+ if options[:limit] <= 0
21
+ raise InvalidOption, 'The Mailpeek limit option is an invalid number'
28
22
  end
29
23
 
30
- # rubocop:enable Style/GuardClause
31
-
32
24
  self.settings = options
33
25
  end
34
26
 
35
27
  def deliver!(mail)
36
- check_delivery_params(mail) if respond_to?(:check_delivery_params)
37
-
38
28
  clean_up
39
29
 
40
- basepath = File.join(settings[:location], Time.now.to_i.to_s)
30
+ timestamp = Time.now.to_i.to_s
31
+
32
+ basepath = File.join(settings[:location], timestamp)
41
33
 
42
34
  save_email(mail, basepath)
43
35
 
44
- return true unless mail.attachments.any?
36
+ add_attachments(mail, basepath) if mail.attachments.any?
45
37
 
46
- add_attachments(mail, basepath)
38
+ timestamp
47
39
  end
48
40
 
49
41
  private
50
42
 
43
+ # remove oldest email if over `limit` settings
51
44
  def clean_up
52
- # remove oldest email if over `limit` settings
53
-
54
45
  directory = File.join(settings[:location], '*')
55
46
  return if Dir[directory].length < settings[:limit]
56
47
 
@@ -60,8 +51,8 @@ module Mailpeek
60
51
  def save_email(mail, basepath)
61
52
  FileUtils.mkdir_p(basepath)
62
53
 
63
- File.open(File.join(basepath, 'mail'), 'w') do |f|
64
- f.write mail.to_s
54
+ File.open(File.join(basepath, 'mail'), 'w') do |file|
55
+ file.write(mail.to_s)
65
56
  end
66
57
  end
67
58
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'mail/check_delivery_params'
4
-
5
3
  module Mailpeek
6
4
  # Public: Wrapper class for mail object
7
5
  class Email
@@ -21,11 +19,7 @@ module Mailpeek
21
19
  @date = mail.date
22
20
  @attachments = []
23
21
 
24
- if mail.multipart?
25
- parse_parts
26
- else
27
- parse_body
28
- end
22
+ mail.multipart? ? parse_parts : parse_body
29
23
  end
30
24
 
31
25
  def match?(query)
@@ -33,9 +27,7 @@ module Mailpeek
33
27
  end
34
28
 
35
29
  def destroy
36
- location = Mailpeek.configuration.location
37
-
38
- FileUtils.rm_rf("#{location}/#{id}")
30
+ FileUtils.rm_rf("#{Mailpeek.configuration.location}/#{id}")
39
31
  end
40
32
 
41
33
  def read
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mailpeek
4
- VERSION = '1.0.2'
4
+ VERSION = '1.0.3'
5
5
  end
@@ -18,7 +18,7 @@ module Mailpeek
18
18
  end
19
19
 
20
20
  def redirect(location)
21
- throw :halt, [302, { 'Location' => "#{request.base_url}#{location}" }, []]
21
+ halt([302, { 'Location' => "#{request.base_url}#{location}" }, []])
22
22
  end
23
23
 
24
24
  def params
@@ -89,9 +89,7 @@ module Mailpeek
89
89
  @env = env
90
90
  @block = block
91
91
 
92
- # rubocop:disable Style/ClassVars
93
- @@files ||= {}
94
- # rubocop:enable Style/ClassVars
92
+ # @@files ||= {}
95
93
  end
96
94
 
97
95
  private
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.files = `git ls-files`.split("\n")
21
21
 
22
- # s.test_files = Dir['spec/**/*']
22
+ s.test_files = Dir['spec/**/*']
23
23
 
24
24
  s.required_ruby_version = '>= 2.3.0'
25
25
 
@@ -27,6 +27,11 @@ Gem::Specification.new do |s|
27
27
  s.add_dependency 'rack', '~> 2.0'
28
28
  s.add_dependency 'rack-protection', '~> 2.0'
29
29
 
30
+ s.add_development_dependency 'faker', '~> 2'
31
+ s.add_development_dependency 'guard-rubocop', '~> 1.3'
32
+ s.add_development_dependency 'rspec', '~> 3'
30
33
  s.add_development_dependency 'rubocop', '~> 0.79'
31
34
  s.add_development_dependency 'rubocop-performance', '~> 1.5'
35
+ s.add_development_dependency 'rubocop-rspec', '~> 1.37'
36
+ s.add_development_dependency 'simplecov', '~> 0.17'
32
37
  end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Mailpeek::Delivery do
4
+ subject(:delivery) { described_class.new(options) }
5
+
6
+ let(:options) { {} }
7
+
8
+ describe '#new' do
9
+ let(:configuration) { Mailpeek::Configuration.new }
10
+
11
+ it 'sets settings to default configuration' do
12
+ settings = {
13
+ limit: Mailpeek.configuration.limit,
14
+ location: Mailpeek.configuration.location
15
+ }
16
+
17
+ expect(delivery.settings).to eq settings
18
+ end
19
+
20
+ context 'without location option' do
21
+ before do
22
+ configuration.location = nil
23
+
24
+ allow(Mailpeek).to receive(:configuration).and_return(configuration)
25
+ end
26
+
27
+ it 'raises InvalidOption' do
28
+ expect { delivery }.to raise_error(Mailpeek::Delivery::InvalidOption)
29
+ end
30
+ end
31
+
32
+ context 'without limit option' do
33
+ before do
34
+ configuration.limit = nil
35
+
36
+ allow(Mailpeek).to receive(:configuration).and_return(configuration)
37
+ end
38
+
39
+ it 'raises InvalidOption' do
40
+ expect { delivery }.to raise_error(Mailpeek::Delivery::InvalidOption)
41
+ end
42
+ end
43
+
44
+ context 'with limit set to non-number' do
45
+ before do
46
+ configuration.limit = 'invalid'
47
+
48
+ allow(Mailpeek).to receive(:configuration).and_return(configuration)
49
+ end
50
+
51
+ it 'raises InvalidOption' do
52
+ expect { delivery }.to raise_error(Mailpeek::Delivery::InvalidOption)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#deliver!' do
58
+ let(:path) { "./spec/support/emails/#{id}/mail" }
59
+ let(:mail) { ::Mail.read(path) }
60
+ let(:timestamp) { delivery.deliver!(mail) }
61
+ let(:basepath) { File.join(Mailpeek.configuration.location, timestamp) }
62
+ let(:file) { instance_double('File') }
63
+
64
+ before do
65
+ mail # declare first so our File stubs don't get in the way
66
+
67
+ allow(FileUtils).to receive(:mkdir_p).and_return(true)
68
+
69
+ allow(file).to receive(:write).and_return(file)
70
+ allow(File).to receive(:open).and_yield(file)
71
+ end
72
+
73
+ context 'with email without attachments' do
74
+ let(:id) { 'html_and_text' }
75
+
76
+ it 'returns a timestamp' do
77
+ expect(timestamp).to be_truthy
78
+ end
79
+
80
+ it 'creates a directory' do
81
+ timestamp
82
+
83
+ expect(FileUtils).to have_received(:mkdir_p).with(basepath).once
84
+ end
85
+
86
+ it 'opens a file' do
87
+ timestamp
88
+
89
+ expect(File).to(
90
+ have_received(:open).with(File.join(basepath, 'mail'), 'w').once
91
+ )
92
+ end
93
+
94
+ it 'saves a file' do
95
+ timestamp
96
+
97
+ expect(file).to have_received(:write).once
98
+ end
99
+ end
100
+
101
+ context 'with attachment email' do
102
+ let(:id) { 'html_text_and_attachment' }
103
+
104
+ it 'returns a timestamp' do
105
+ expect(timestamp).to be_truthy
106
+ end
107
+
108
+ it 'creates 2 directories' do
109
+ timestamp
110
+
111
+ expect(FileUtils).to have_received(:mkdir_p).twice
112
+ end
113
+
114
+ it 'opens 2 files' do
115
+ timestamp
116
+
117
+ expect(File).to have_received(:open).twice
118
+ end
119
+
120
+ it 'saves 2 files' do
121
+ timestamp
122
+
123
+ expect(file).to have_received(:write).twice
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Mailpeek::Email do
4
+ subject(:email) { described_class.new(id, ::Mail.read(path)) }
5
+
6
+ let(:path) { "./spec/support/emails/#{id}/mail" }
7
+ let(:id) { 'html_and_text' }
8
+
9
+ describe '#new' do
10
+ context 'with html and text email' do
11
+ it 'sets html' do
12
+ expect(email.html.nil?).to eq false
13
+ end
14
+
15
+ it 'sets text' do
16
+ expect(email.text.nil?).to eq false
17
+ end
18
+
19
+ it 'has 0 attachments' do
20
+ expect(email.attachments.empty?).to eq true
21
+ end
22
+ end
23
+
24
+ context 'with text email' do
25
+ let(:id) { 'text' }
26
+
27
+ it 'does not set html' do
28
+ expect(email.html.nil?).to eq true
29
+ end
30
+
31
+ it 'sets text' do
32
+ expect(email.text.nil?).to eq false
33
+ end
34
+
35
+ it 'has 0 attachments' do
36
+ expect(email.attachments.empty?).to eq true
37
+ end
38
+ end
39
+
40
+ context 'with html email' do
41
+ let(:id) { 'html' }
42
+
43
+ it 'sets html' do
44
+ expect(email.html.nil?).to eq false
45
+ end
46
+
47
+ it 'does not set text' do
48
+ expect(email.text.nil?).to eq true
49
+ end
50
+
51
+ it 'has 0 attachments' do
52
+ expect(email.attachments.empty?).to eq true
53
+ end
54
+ end
55
+
56
+ context 'with html, text and attachment email' do
57
+ let(:id) { 'html_text_and_attachment' }
58
+
59
+ it 'sets html' do
60
+ expect(email.html.nil?).to eq false
61
+ end
62
+
63
+ it 'sets text' do
64
+ expect(email.text.nil?).to eq false
65
+ end
66
+
67
+ it 'has attachments' do
68
+ expect(email.attachments.empty?).to eq false
69
+ end
70
+ end
71
+ end
72
+
73
+ describe '#match?' do
74
+ let(:results) { email.match?(query) }
75
+
76
+ context 'with valid query' do
77
+ let(:query) { 'Itaque' }
78
+
79
+ it 'returns true' do
80
+ expect(results).to be_truthy
81
+ end
82
+ end
83
+
84
+ context 'with invalid query' do
85
+ let(:query) { 'Invalid' }
86
+
87
+ it 'returns true' do
88
+ expect(results).to be_falsey
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#destroy' do
94
+ before do
95
+ allow(FileUtils).to receive(:rm_rf).and_return(true)
96
+ end
97
+
98
+ it 'returns true' do
99
+ expect(email.destroy).to eq true
100
+ end
101
+
102
+ it 'removes directory' do
103
+ email.destroy
104
+
105
+ with = "#{Mailpeek.configuration.location}/#{id}"
106
+
107
+ expect(FileUtils).to have_received(:rm_rf).with(with).once
108
+ end
109
+ end
110
+
111
+ describe '#read' do
112
+ context 'with read email' do
113
+ it 'returns true' do
114
+ expect(email.read).to eq true
115
+ end
116
+ end
117
+
118
+ context 'with unread email' do
119
+ let(:id) { 'text' }
120
+
121
+ it 'returns false' do
122
+ expect(email.read).to eq false
123
+ end
124
+ end
125
+ end
126
+
127
+ describe '#read=' do
128
+ context 'with read email' do
129
+ after do
130
+ email.read = true
131
+ end
132
+
133
+ it 'unreads file' do
134
+ email.read = false
135
+ expect(email.read).to eq false
136
+ end
137
+ end
138
+
139
+ context 'with unread email' do
140
+ let(:id) { 'html' }
141
+
142
+ after do
143
+ email.read = false
144
+ end
145
+
146
+ it 'unreads file' do
147
+ email.read = true
148
+ expect(email.read).to eq true
149
+ end
150
+ end
151
+ end
152
+ end