mailpeek 1.0.2 → 1.0.3

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
  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