mailx_ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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