mailx_ruby 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3e2bc65108a4449141800bdacfecdd3657a25602
4
+ data.tar.gz: 579e3c4a28280059d6aeac66b338d56612294876
5
+ SHA512:
6
+ metadata.gz: 7a90f12a26f52c7350b98554ab868519419ebc170575bc68ba4acbf88ca44118822162ed493ec0bbd6c03396c08ec0ee6546305aab8cb5b7ba9ed650cc64583f
7
+ data.tar.gz: 77d2b98216ff46f970854101152530260d43e4be365b14af2999f90f44823ca5ec838b4157d670dff83aa6935c4de0ab12652eecce1615ea969dc95eff948748
data/lib/mailx_ruby.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'nokogiri'
2
+ require 'premailer'
3
+
4
+ module MailxRuby
5
+ require 'mailx_ruby/command_generator'
6
+ require 'mailx_ruby/body'
7
+ require 'mailx_ruby/version'
8
+
9
+ def send_mail(body:, to:, **options)
10
+ CommandGenerator.execute options.merge(body: body, to: to)
11
+ end
12
+ module_function :send_mail
13
+ end
@@ -0,0 +1,38 @@
1
+ module MailxRuby
2
+ class Body
3
+ extend Forwardable
4
+ delegate [:to_inline_css, :to_plain_text] => :premailer
5
+
6
+ attr_accessor :html
7
+ alias_method :text, :html
8
+
9
+ def initialize(html)
10
+ @html = html
11
+ end
12
+
13
+ def has_css?
14
+ nokogiri_html.xpath("//style").any?
15
+ end
16
+
17
+ def premailer
18
+ @premailer ||= generate_premailer
19
+ end
20
+
21
+ private
22
+
23
+ def nokogiri_html
24
+ @nokogiri_html ||= Nokogiri::HTML(html)
25
+ end
26
+
27
+ def generate_premailer
28
+ File.open(tmp_filepath, "w"){|f| f.write(html) }
29
+ premailer = Premailer.new(tmp_filepath, warn_level: Premailer::Warnings::SAFE)
30
+ File.delete(tmp_filepath)
31
+ premailer
32
+ end
33
+
34
+ def tmp_filepath
35
+ @tmp_filepath ||= "mail#{Time.now.to_i}.html"
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,75 @@
1
+ module MailxRuby
2
+ class CommandGenerator
3
+ attr_accessor :body, :to, :subject, :cc, :bcc, :html
4
+
5
+ def self.execute(options)
6
+ new(options).execute
7
+ end
8
+
9
+ def initialize(attributes)
10
+ assign_attributes attributes
11
+ end
12
+
13
+ def execute
14
+ `#{generate}`
15
+ end
16
+
17
+ def body=(body_text)
18
+ @body = Body.new(body_text)
19
+ end
20
+
21
+ def inline_css_body
22
+ if !html
23
+ body.text
24
+ elsif body.has_css?
25
+ body.to_inline_css
26
+ else
27
+ body.to_plain_text
28
+ end
29
+ end
30
+
31
+ def generate
32
+ "mailx #{options_string} #{stringify(to)} <<-\"EOM\"
33
+ #{inline_css_body}
34
+ EOM"
35
+ end
36
+
37
+ def options_string
38
+ options_hash.map do |key, value|
39
+ "-#{key} \"#{value}\""
40
+ end.join(" ")
41
+ end
42
+
43
+ def subject_with_headers
44
+ if html
45
+ "$(echo \"#{subject}\nContent-Type: text/html\")"
46
+ else
47
+ subject
48
+ end
49
+ end
50
+
51
+ private
52
+ def self.symbolize_keys(hash)
53
+ hash.map{|k,v| [k.to_sym, v] }.to_h
54
+ end
55
+
56
+ def assign_attributes(attributes)
57
+ attributes.each do |key, value|
58
+ send("#{key}=", value)
59
+ end
60
+ end
61
+
62
+ def options_hash
63
+ {
64
+ s: subject_with_headers,
65
+ c: stringify(cc),
66
+ b: stringify(bcc),
67
+ }.select{|k,v| v }
68
+ end
69
+
70
+ def stringify(arr_or_string)
71
+ return nil unless arr_or_string
72
+ arr_or_string.is_a?(Array) ? arr_or_string.join(",") : arr_or_string.to_s
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,3 @@
1
+ module MailxRuby
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'mailx_ruby'
3
+
4
+ describe MailxRuby::Body do
5
+ let(:body){ described_class.new html }
6
+
7
+ describe "has_css?" do
8
+ subject{ body.has_css? }
9
+ context "with plaintext" do
10
+ let(:html){ "Some body" }
11
+
12
+ it { is_expected.to be_falsy }
13
+ end
14
+
15
+ context "with HTML without CSS" do
16
+ let(:html){ "<p>Hello World" }
17
+
18
+ it { is_expected.to be_falsy }
19
+ end
20
+
21
+ context "with HTML with CSS" do
22
+ let(:html) do
23
+ "
24
+ <html>
25
+ <head>
26
+ <style>
27
+ p { color:red; }
28
+ </style>
29
+ </head>
30
+ <body>
31
+ <p>Some nonsense
32
+ </body>
33
+ </html>
34
+ "
35
+ end
36
+
37
+ it { is_expected.to be_truthy }
38
+ end
39
+ end
40
+
41
+ describe "premailer" do
42
+ subject{ body.premailer }
43
+ let(:html){ "<p>Hello World" }
44
+
45
+ it { is_expected.to be_a Premailer }
46
+ end
47
+ end
@@ -0,0 +1,239 @@
1
+ require 'spec_helper'
2
+ require 'mailx_ruby'
3
+
4
+ describe MailxRuby::CommandGenerator do
5
+
6
+ describe "class methods" do
7
+ describe "self.execute" do
8
+ subject { described_class.execute options }
9
+ let(:options){ {some: :options} }
10
+ let(:generator){ double described_class, execute: true }
11
+ before { allow(described_class).to receive(:new).and_return generator }
12
+
13
+ it "should call execute on new instance" do
14
+ expect(described_class).to receive(:new).with(options)
15
+ expect(generator).to receive(:execute)
16
+ subject
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "instance methods" do
22
+ let(:generator){ described_class.new options }
23
+ let(:options){ ({body: "Hello world\nI'm here!", to: "jimbob@example.com"}) }
24
+
25
+ describe "execute" do
26
+ subject { generator.execute }
27
+ let(:generated){ "mailx something" }
28
+ before do
29
+ allow(generator).to receive(:generate).and_return generated
30
+ allow(generator).to receive(:`)
31
+ end
32
+
33
+ it "should execute string returned by generate" do
34
+ expect(generator).to receive(:generate)
35
+ expect(generator).to receive(:`).with(generated)
36
+ subject
37
+ end
38
+ end
39
+
40
+ describe "inline_css_body" do
41
+ subject{ generator.inline_css_body }
42
+
43
+ context "with html unspecified" do
44
+ it { is_expected.to eq options[:body] }
45
+ end
46
+
47
+ context "with html true" do
48
+ let(:options){ ({body: body, to: "jimbob@example.com", html: true}) }
49
+
50
+ context "and body without styles" do
51
+ let(:body) do
52
+ "<html>
53
+ <body>
54
+ <p>Some nonsense
55
+ </body>
56
+ </html>"
57
+ end
58
+
59
+ it { is_expected.to eq "Some nonsense" }
60
+ end
61
+
62
+ context "and body with styles" do
63
+ let(:body) do
64
+ "<html>
65
+ <head>
66
+ <style>
67
+ p { color:red; }
68
+ </style>
69
+ </head>
70
+ <body>
71
+ <p>Some nonsense
72
+ </body>
73
+ </html>"
74
+ end
75
+
76
+ it { is_expected.to include "<p style=\"color: red;\">Some nonsense" }
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "generate" do
82
+ subject { generator.generate }
83
+ let(:options_string){ nil }
84
+ before { allow(generator).to receive(:options_string).and_return options_string }
85
+
86
+ context "with string to" do
87
+ context "without options_string" do
88
+ it { is_expected.to eq "mailx jimbob@example.com <<-\"EOM\"\nHello world\nI'm here!\nEOM" }
89
+ end
90
+
91
+ context "with options_string" do
92
+ let(:options_string){ "-t JUSTTESTING" }
93
+
94
+ it { is_expected.to eq "mailx -t JUSTTESTING jimbob@example.com <<-\"EOM\"\nHello world\nI'm here!\nEOM" }
95
+ end
96
+ end
97
+
98
+ context "with array to" do
99
+ let(:options){ ({body: "Hello world\nI'm here!", to: ["jimbob@example.com", "tinman@example.com"]}) }
100
+
101
+ context "without options_string" do
102
+ it { is_expected.to eq "mailx jimbob@example.com,tinman@example.com <<-\"EOM\"\nHello world\nI'm here!\nEOM" }
103
+ end
104
+
105
+ context "with options_string" do
106
+ let(:options_string){ "-t JUSTTESTING" }
107
+
108
+ it { is_expected.to eq "mailx -t JUSTTESTING jimbob@example.com,tinman@example.com <<-\"EOM\"\nHello world\nI'm here!\nEOM" }
109
+ end
110
+ end
111
+ end
112
+
113
+ describe "options_string" do
114
+ subject { generator.options_string }
115
+
116
+ context "without subject" do
117
+ context "without cc" do
118
+ context 'without bcc' do
119
+ it { is_expected.to be_empty }
120
+ end
121
+
122
+ context "with string bcc" do
123
+ before { options[:bcc] = "jack@example.com" }
124
+
125
+ it { is_expected.to eq '-b "jack@example.com"' }
126
+ end
127
+
128
+ context "with array bcc" do
129
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
130
+
131
+ it { is_expected.to eq '-b "jack@example.com,jill@example.com,hill@example.com"' }
132
+ end
133
+ end
134
+
135
+ context "with string cc" do
136
+ before { options[:cc] = "joebob@example.com" }
137
+
138
+ context 'without bcc' do
139
+ it { is_expected.to eq '-c "joebob@example.com"' }
140
+ end
141
+
142
+ context "with string bcc" do
143
+ before { options[:bcc] = "jack@example.com" }
144
+
145
+ it { is_expected.to eq '-c "joebob@example.com" -b "jack@example.com"' }
146
+ end
147
+
148
+ context "with array bcc" do
149
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
150
+
151
+ it { is_expected.to eq '-c "joebob@example.com" -b "jack@example.com,jill@example.com,hill@example.com"' }
152
+ end
153
+ end
154
+
155
+ context "with array cc" do
156
+ before { options[:cc] = ["joebob@example.com", "janebob@example.com"] }
157
+
158
+ context 'without bcc' do
159
+ it { is_expected.to eq '-c "joebob@example.com,janebob@example.com"' }
160
+ end
161
+
162
+ context "with string bcc" do
163
+ before { options[:bcc] = "jack@example.com" }
164
+
165
+ it { is_expected.to eq '-c "joebob@example.com,janebob@example.com" -b "jack@example.com"' }
166
+ end
167
+
168
+ context "with array bcc" do
169
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
170
+
171
+ it { is_expected.to eq '-c "joebob@example.com,janebob@example.com" -b "jack@example.com,jill@example.com,hill@example.com"' }
172
+ end
173
+ end
174
+ end # end "without subject"
175
+
176
+ context "with subject" do
177
+ before { options[:subject] = "Hello there!" }
178
+
179
+ context "without cc" do
180
+ context 'without bcc' do
181
+ it { is_expected.to eq '-s "Hello there!"' }
182
+ end
183
+
184
+ context "with string bcc" do
185
+ before { options[:bcc] = "jack@example.com" }
186
+
187
+ it { is_expected.to eq '-s "Hello there!" -b "jack@example.com"' }
188
+ end
189
+
190
+ context "with array bcc" do
191
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
192
+
193
+ it { is_expected.to eq '-s "Hello there!" -b "jack@example.com,jill@example.com,hill@example.com"' }
194
+ end
195
+ end
196
+
197
+ context "with string cc" do
198
+ before { options[:cc] = "joebob@example.com" }
199
+
200
+ context 'without bcc' do
201
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com"' }
202
+ end
203
+
204
+ context "with string bcc" do
205
+ before { options[:bcc] = "jack@example.com" }
206
+
207
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com" -b "jack@example.com"' }
208
+ end
209
+
210
+ context "with array bcc" do
211
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
212
+
213
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com" -b "jack@example.com,jill@example.com,hill@example.com"' }
214
+ end
215
+ end
216
+
217
+ context "with array cc" do
218
+ before { options[:cc] = ["joebob@example.com", "janebob@example.com"] }
219
+
220
+ context 'without bcc' do
221
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com,janebob@example.com"' }
222
+ end
223
+
224
+ context "with string bcc" do
225
+ before { options[:bcc] = "jack@example.com" }
226
+
227
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com,janebob@example.com" -b "jack@example.com"' }
228
+ end
229
+
230
+ context "with array bcc" do
231
+ before { options[:bcc] = ["jack@example.com", "jill@example.com", "hill@example.com"] }
232
+
233
+ it { is_expected.to eq '-s "Hello there!" -c "joebob@example.com,janebob@example.com" -b "jack@example.com,jill@example.com,hill@example.com"' }
234
+ end
235
+ end
236
+ end # end "with subject"
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require 'mailx_ruby'
3
+
4
+ describe MailxRuby do
5
+ describe "VERSION" do
6
+ subject { described_class::VERSION }
7
+ it { is_expected.to_not be_nil }
8
+ end
9
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'mailx_ruby'
3
+
4
+ describe MailxRuby do
5
+ describe "send_mail" do
6
+ subject { described_class.send_mail **options }
7
+ let(:commander){ described_class::CommandGenerator }
8
+ before { allow(commander).to receive(:execute) }
9
+
10
+ context "with body and to" do
11
+ let(:options){ ({body: "body", to: "to"}) }
12
+
13
+ it "should send them to CommandGenerator" do
14
+ expect(commander).to receive(:execute).with(options)
15
+ subject
16
+ end
17
+
18
+ context "with other options" do
19
+ let(:options){ ({body: "body", to: "to", another: "thing", one: "more"}) }
20
+
21
+ it "should send them to CommandGenerator" do
22
+ expect(commander).to receive(:execute).with(options)
23
+ subject
24
+ end
25
+ end
26
+ end
27
+
28
+ context "with only to" do
29
+ let(:options){ ({to: "to"}) }
30
+
31
+ it { expect{ subject }.to raise_error ArgumentError }
32
+ end
33
+
34
+ context "with only body" do
35
+ let(:options){ ({body: "body"}) }
36
+
37
+ it { expect{ subject }.to raise_error ArgumentError }
38
+ end
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailx_ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric Griffis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: premailer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.10'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.8.17
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.8.17
83
+ description: Ruby wrapper for mailx command
84
+ email: eric.griffis@nyu.edu
85
+ executables: []
86
+ extensions: []
87
+ extra_rdoc_files: []
88
+ files:
89
+ - lib/mailx_ruby.rb
90
+ - lib/mailx_ruby/body.rb
91
+ - lib/mailx_ruby/command_generator.rb
92
+ - lib/mailx_ruby/version.rb
93
+ - spec/lib/mailx_ruby/body_spec.rb
94
+ - spec/lib/mailx_ruby/command_generator_spec.rb
95
+ - spec/lib/mailx_ruby/version_spec.rb
96
+ - spec/lib/mailx_ruby_spec.rb
97
+ homepage: https://github.com/NYULibraries/mailx_ruby
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.6.8
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Ruby wrapper for mailx command
121
+ test_files:
122
+ - spec/lib/mailx_ruby_spec.rb
123
+ - spec/lib/mailx_ruby/body_spec.rb
124
+ - spec/lib/mailx_ruby/command_generator_spec.rb
125
+ - spec/lib/mailx_ruby/version_spec.rb