kafka_mailer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3295f7b9bec090e10f821b20369619dd697ad861
4
+ data.tar.gz: cfc2e4da1a2e377b0b55965095c4b058729640a0
5
+ SHA512:
6
+ metadata.gz: 5231ebe7df6e96e3389bfc315ed84b113237128eaf2a31d9801452790f1cbde885de64a7ee20cb3d5919afa3e14d4c792066f22b8731146d2a8ec48d110decfc
7
+ data.tar.gz: 87dd4fce1c44543f412ed1b7ea9c6dc244b8c343e5c254bfe473367261c088ae1550fea03c6d991bd32614d87381311f0b9a3618083cd86dd529d9b0093df50d
@@ -0,0 +1,3 @@
1
+ ## 0.0.1 ##
2
+
3
+ * Initial relase
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "codeclimate-test-reporter", group: :test, require: nil
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Eric Hayes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ # kafka_mailer [![Build Status](https://travis-ci.org/ejhayes/kafka_mailer.svg?branch=master)](https://travis-ci.org/ejhayes/kafka_mailer) [![Gem Version](https://badge.fury.io/rb/kafka_mailer.svg)](http://badge.fury.io/rb/kafka_mailer) [![Code Climate](https://codeclimate.com/github/ejhayes/kafka_mailer/badges/gpa.svg)](https://codeclimate.com/github/ejhayes/kafka_mailer) [![Test Coverage](https://codeclimate.com/github/ejhayes/kafka_mailer/badges/coverage.svg)](https://codeclimate.com/github/ejhayes/kafka_mailer) [![Dependency Status](https://gemnasium.com/ejhayes/kafka_mailer.svg)](https://gemnasium.com/ejhayes/kafka_mailer)
2
+
3
+ Use [Apache Kafka](http://kafka.apache.org/) as a delivery_method in rails.
4
+
5
+ ## Rails Setup
6
+
7
+ **IMPORTANT**: This is under development right now and is not yet ready for use in a production environment.
8
+
9
+ First add the gem to your development environment and run the +bundle+ command to install it.
10
+
11
+ gem "kafka_mailer"
12
+
13
+ Then set the delivery method in `config/environments/development.rb`
14
+
15
+ config.action_mailer.delivery_method = :kafka
16
+
17
+ Now your emails will be sent to a kafka message queue.
18
+
19
+ ## Hacking on this gem
20
+
21
+ Once you have the source, you must run the following:
22
+
23
+ bundle
24
+ bundle exec rake spec
25
+
26
+ ## TODO
27
+
28
+ Some items that will eventually need to be done:
29
+
30
+ - provide a config block that can specify the structure of the message being sent to kafka
31
+
32
+
33
+ ## Thanks to
34
+
35
+ - Ryan Bates and his [letter_opener](https://github.com/ryanb/letter_opener) which was used as the base for this gem
36
+ - [poseidon](https://github.com/bpot/poseidon) gem for interacting with Apache Kafka
37
+ - [Apache kafka](http://kafka.apache.org/)
@@ -0,0 +1,22 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ desc 'Interactive console with gem pre-loaded'
10
+ task :console do
11
+ require 'irb'
12
+ require 'irb/completion'
13
+ require 'ruby-debug'
14
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
15
+
16
+ # load the gem
17
+ require 'kafka_mailer'
18
+
19
+ ARGV.clear
20
+ puts "Console Ready!"
21
+ IRB.start
22
+ end
@@ -0,0 +1,8 @@
1
+ require "fileutils"
2
+ require "digest/sha1"
3
+ require "cgi"
4
+ require "uri"
5
+
6
+ require "kafka_mailer/message"
7
+ require "kafka_mailer/delivery_method"
8
+ require "kafka_mailer/railtie" if defined? Rails
@@ -0,0 +1,18 @@
1
+ module KafkaMailer
2
+ class DeliveryMethod
3
+ class InvalidOption < StandardError; end
4
+
5
+ attr_accessor :settings
6
+
7
+ def initialize(options = {})
8
+ raise InvalidOption, "A location option is required when using the kafka delivery method" if options[:location].nil?
9
+ self.settings = options
10
+ end
11
+
12
+ def deliver!(mail)
13
+ byebug
14
+ location = File.join(settings[:location], "#{Time.now.to_i}_#{Digest::SHA1.hexdigest(mail.encoded)[0..6]}")
15
+ messages = Message.rendered_messages(location, mail)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,125 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= encoding %>">
4
+ <% if mail.subject %>
5
+ <title><%= h mail.subject %></title>
6
+ <% end %>
7
+
8
+ <style type="text/css">
9
+ #container {
10
+ margin: 10px auto;
11
+ }
12
+ #message_headers {
13
+ background: #fff;
14
+ font-size: 12px;
15
+ font-family: "Segoe UI", "Helvetica Neue", Arial, sans-serif;
16
+ border-bottom: 1px solid #dedede;
17
+ margin-bottom: 10px;
18
+ overflow: auto;
19
+ }
20
+
21
+ #message_headers dl {
22
+ float: left;
23
+ line-height: 1.3em;
24
+ padding: 0;
25
+ }
26
+
27
+ #message_headers dt {
28
+ width: 92px;
29
+ margin: 0;
30
+ float: left;
31
+ text-align: right;
32
+ font-weight: bold;
33
+ color: #7f7f7f;
34
+ }
35
+
36
+ #message_headers dd {
37
+ margin: 0 0 0 102px;
38
+ }
39
+
40
+ #message_headers p.alternate {
41
+ float: right;
42
+ margin: 0;
43
+ }
44
+
45
+ #message_headers p.alternate a {
46
+ color: #09c;
47
+ }
48
+
49
+ pre#message_body {
50
+ padding: 4px;
51
+ white-space: pre-wrap;
52
+ border: 1px solid #eee;
53
+ background-color: #fcfcfc;
54
+ }
55
+ </style>
56
+ </head>
57
+ <body>
58
+ <div id="container">
59
+ <div id="message_headers">
60
+ <dl>
61
+ <dt>From:</dt>
62
+ <dd><%= h from %></dd>
63
+
64
+ <% unless sender.empty? %>
65
+ <dt>Sender:</dt>
66
+ <dd><%= h sender %></dd>
67
+ <% end %>
68
+
69
+ <% unless reply_to.empty? %>
70
+ <dt>Reply-To:</dt>
71
+ <dd><%= h reply_to %></dd>
72
+ <% end %>
73
+
74
+ <% if mail.subject %>
75
+ <dt>Subject:</dt>
76
+ <dd><strong><%= h mail.subject %></strong></dd>
77
+ <% end %>
78
+
79
+ <dt>Date:</dt>
80
+ <dd><%= Time.now.strftime("%b %e, %Y %I:%M:%S %p %Z") %></dd>
81
+
82
+ <% unless to.empty? %>
83
+ <dt>To:</dt>
84
+ <dd><%= h to %></dd>
85
+ <% end %>
86
+
87
+ <% unless cc.empty? %>
88
+ <dt>CC:</dt>
89
+ <dd><%= h cc %></dd>
90
+ <% end %>
91
+
92
+ <% unless bcc.empty? %>
93
+ <dt>BCC:</dt>
94
+ <dd><%= h bcc %></dd>
95
+ <% end %>
96
+
97
+ <% if @attachments.any? %>
98
+ <dt>Attachments:</dt>
99
+ <dd>
100
+ <% @attachments.each do |filename, path| %>
101
+ <a href="<%= path %>"><%= filename %></a>&nbsp;
102
+ <% end %>
103
+ </dd>
104
+ <% end %>
105
+ </dl>
106
+
107
+ <% if mail.multipart? %>
108
+ <p class="alternate">
109
+ <% if type == "plain" && mail.html_part %>
110
+ <a href="rich.html">View HTML version</a>
111
+ <% elsif type == "rich" && mail.text_part %>
112
+ <a href="plain.html">View plain text version</a>
113
+ <% end %>
114
+ </p>
115
+ <% end %>
116
+ </div>
117
+
118
+ <% if type == "plain" %>
119
+ <pre id="message_body"><%= auto_link(h(body)) %></pre>
120
+ <% else %>
121
+ <%= body %>
122
+ <% end %>
123
+ </div>
124
+ </body>
125
+ </html>
@@ -0,0 +1,117 @@
1
+ require "erb"
2
+
3
+ module KafkaMailer
4
+ class Message
5
+ attr_reader :mail
6
+
7
+ def self.rendered_messages(location, mail)
8
+ messages = []
9
+ messages << new(location, mail, mail.html_part) if mail.html_part
10
+ messages << new(location, mail, mail.text_part) if mail.text_part
11
+ messages << new(location, mail) if messages.empty?
12
+ messages.each(&:render)
13
+ messages.sort
14
+ end
15
+
16
+ def initialize(location, mail, part = nil)
17
+ @location = location
18
+ @mail = mail
19
+ @part = part
20
+ @attachments = []
21
+ end
22
+
23
+ def render
24
+ FileUtils.mkdir_p(@location)
25
+
26
+ if mail.attachments.any?
27
+ attachments_dir = File.join(@location, 'attachments')
28
+ FileUtils.mkdir_p(attachments_dir)
29
+ mail.attachments.each do |attachment|
30
+ filename = attachment.filename.gsub(/[^\w.]/, '_')
31
+ path = File.join(attachments_dir, filename)
32
+
33
+ unless File.exists?(path) # true if other parts have already been rendered
34
+ File.open(path, 'wb') { |f| f.write(attachment.body.raw_source) }
35
+ end
36
+
37
+ @attachments << [attachment.filename, "attachments/#{URI.escape(filename)}"]
38
+ end
39
+ end
40
+
41
+ File.open(filepath, 'w') do |f|
42
+ f.write ERB.new(template).result(binding)
43
+ end
44
+ end
45
+
46
+ def template
47
+ File.read(File.expand_path("../message.html.erb", __FILE__))
48
+ end
49
+
50
+ def filepath
51
+ File.join(@location, "#{type}.html")
52
+ end
53
+
54
+ def content_type
55
+ @part && @part.content_type || @mail.content_type
56
+ end
57
+
58
+ def body
59
+ @body ||= begin
60
+ body = (@part || @mail).decoded
61
+
62
+ mail.attachments.each do |attachment|
63
+ body.gsub!(attachment.url, "attachments/#{attachment.filename}")
64
+ end
65
+
66
+ body
67
+ end
68
+ end
69
+
70
+ def from
71
+ @from ||= Array(@mail['from']).join(", ")
72
+ end
73
+
74
+ def sender
75
+ @sender ||= Array(@mail['sender']).join(", ")
76
+ end
77
+
78
+ def to
79
+ @to ||= Array(@mail['to']).join(", ")
80
+ end
81
+
82
+ def cc
83
+ @cc ||= Array(@mail['cc']).join(", ")
84
+ end
85
+
86
+ def bcc
87
+ @bcc ||= Array(@mail['bcc']).join(", ")
88
+ end
89
+
90
+ def reply_to
91
+ @reply_to ||= Array(@mail['reply-to']).join(", ")
92
+ end
93
+
94
+ def type
95
+ content_type =~ /html/ ? "rich" : "plain"
96
+ end
97
+
98
+ def encoding
99
+ body.respond_to?(:encoding) ? body.encoding : "utf-8"
100
+ end
101
+
102
+ def auto_link(text)
103
+ text.gsub(URI.regexp(%W[https http])) do |link|
104
+ "<a href=\"#{ link }\">#{ link }</a>"
105
+ end
106
+ end
107
+
108
+ def h(content)
109
+ CGI.escapeHTML(content)
110
+ end
111
+
112
+ def <=>(other)
113
+ order = %w[rich plain]
114
+ order.index(type) <=> order.index(other.type)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,9 @@
1
+ module KafkaMailer
2
+ class Railtie < Rails::Railtie
3
+ initializer "letter_opener.add_delivery_method" do
4
+ ActiveSupport.on_load :action_mailer do
5
+ ActionMailer::Base.add_delivery_method :kafka, KafkaMailer::DeliveryMethod, :location => Rails.root.join("tmp", "kafka_mailer")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,277 @@
1
+ require "spec_helper"
2
+
3
+ describe KafkaMailer::DeliveryMethod do
4
+ let(:location) { File.expand_path('../../../tmp/kafka_mailer', __FILE__) }
5
+
6
+ let(:plain_file) { Dir["#{location}/*/plain.html"].first }
7
+ let(:plain) { CGI.unescape_html(File.read(plain_file)) }
8
+
9
+ before do
10
+ # TODO: STUB kafka connection
11
+ context = self
12
+
13
+ Mail.defaults do
14
+ delivery_method KafkaMailer::DeliveryMethod, :location => context.location
15
+ end
16
+ end
17
+
18
+ it 'raises an exception if no location passed' do
19
+ # expect { KafkaMailer::DeliveryMethod.new }.to raise_exception(KafkaMailer::DeliveryMethod::InvalidOption)
20
+ # expect { KafkaMailer::DeliveryMethod.new(location: "foo") }.to_not raise_exception
21
+ end
22
+
23
+ context 'integration' do
24
+
25
+ #context 'normal location path' do
26
+ # it 'opens email' do
27
+ # expect($stdout).to receive(:puts)
28
+ # expect {
29
+ # Mail.deliver do
30
+ # from 'Foo foo@example.com'
31
+ # body 'World! http://example.com'
32
+ # end
33
+ # }.not_to raise_error
34
+ # end
35
+ #end
36
+
37
+ #context 'with spaces in location path' do
38
+ # let(:location) { File.expand_path('../../../tmp/kafka_mailer with space', __FILE__) }
39
+ #
40
+ # it 'opens email' do
41
+ # expect($stdout).to receive(:puts)
42
+ # expect {
43
+ # Mail.deliver do
44
+ # from 'Foo foo@example.com'
45
+ # body 'World! http://example.com'
46
+ # end
47
+ # }.not_to raise_error
48
+ # end
49
+ #end
50
+ end
51
+
52
+ context 'content' do
53
+ context 'plain' do
54
+ before do
55
+ #expect(Launchy).to receive(:open)
56
+
57
+ Mail.deliver do
58
+ from 'Foo <foo@example.com>'
59
+ sender 'Baz <baz@example.com>'
60
+ reply_to 'No Reply <no-reply@example.com>'
61
+ to 'Bar <bar@example.com>'
62
+ cc 'Qux <qux@example.com>'
63
+ bcc 'Qux <qux@example.com>'
64
+ subject 'Hello'
65
+ body 'World! http://example.com'
66
+ end
67
+ end
68
+
69
+ # TODO: check message queue getting correct params
70
+ #it 'creates plain html document' do
71
+ # expect(File.exist?(plain_file)).to be_true
72
+ #end
73
+ #
74
+ #it 'saves From field' do
75
+ # expect(plain).to include("Foo <foo@example.com>")
76
+ #end
77
+ #
78
+ #it 'saves Sender field' do
79
+ # expect(plain).to include("Baz <baz@example.com>")
80
+ #end
81
+ #
82
+ #it 'saves Reply-to field' do
83
+ # expect(plain).to include("No Reply <no-reply@example.com>")
84
+ #end
85
+ #
86
+ #it 'saves To field' do
87
+ # expect(plain).to include("Bar <bar@example.com>")
88
+ #end
89
+ #
90
+ #it 'saves Subject field' do
91
+ # expect(plain).to include("Hello")
92
+ #end
93
+ #
94
+ #it 'saves Body with autolink' do
95
+ # expect(plain).to include('World! <a href="http://example.com">http://example.com</a>')
96
+ #end
97
+ end
98
+
99
+ context 'multipart' do
100
+ let(:rich_file) { Dir["#{location}/*/rich.html"].first }
101
+ let(:rich) { CGI.unescape_html(File.read(rich_file)) }
102
+
103
+ before do
104
+ #expect(Launchy).to receive(:open)
105
+
106
+ Mail.deliver do
107
+ from 'foo@example.com'
108
+ to 'bar@example.com'
109
+ subject 'Many parts with <html>'
110
+ text_part do
111
+ body 'This is <plain> text'
112
+ end
113
+ html_part do
114
+ content_type 'text/html; charset=UTF-8'
115
+ body '<h1>This is HTML</h1>'
116
+ end
117
+ end
118
+ end
119
+
120
+ #it 'creates plain html document' do
121
+ # expect(File.exist?(plain_file)).to be_true
122
+ #end
123
+ #
124
+ #it 'creates rich html document' do
125
+ # expect(File.exist?(rich_file)).to be_true
126
+ #end
127
+ #
128
+ #it 'shows link to rich html version' do
129
+ # expect(plain).to include("View HTML version")
130
+ #end
131
+ #
132
+ #it 'saves text part' do
133
+ # expect(plain).to include("This is <plain> text")
134
+ #end
135
+ #
136
+ #it 'saves html part' do
137
+ # expect(rich).to include("<h1>This is HTML</h1>")
138
+ #end
139
+ #
140
+ #it 'saves escaped Subject field' do
141
+ # expect(plain).to include("Many parts with <html>")
142
+ #end
143
+ #
144
+ #it 'shows subject as title' do
145
+ # expect(rich).to include("<title>Many parts with <html></title>")
146
+ #end
147
+ end
148
+ end
149
+
150
+ context 'using deliver! method' do
151
+ before do
152
+ #expect(Launchy).to receive(:open)
153
+ Mail.new do
154
+ from 'foo@example.com'
155
+ to 'bar@example.com'
156
+ subject 'Hello'
157
+ body 'World!'
158
+ end.deliver!
159
+ end
160
+
161
+ #it 'creates plain html document' do
162
+ # expect(File.exist?(plain_file)).to be_true
163
+ #end
164
+ #
165
+ #it 'saves From field' do
166
+ # expect(plain).to include("foo@example.com")
167
+ #end
168
+ #
169
+ #it 'saves To field' do
170
+ # expect(plain).to include("bar@example.com")
171
+ #end
172
+ #
173
+ #it 'saves Subject field' do
174
+ # expect(plain).to include("Hello")
175
+ #end
176
+ #
177
+ #it 'saves Body field' do
178
+ # expect(plain).to include("World!")
179
+ #end
180
+ end
181
+
182
+ context 'attachments in plain text mail' do
183
+ before do
184
+ Mail.deliver do
185
+ from 'foo@example.com'
186
+ to 'bar@example.com'
187
+ subject 'With attachments'
188
+ text_part do
189
+ body 'This is <plain> text'
190
+ end
191
+ attachments[File.basename(__FILE__)] = File.read(__FILE__)
192
+ end
193
+ end
194
+
195
+ #it 'creates attachments dir with attachment' do
196
+ # attachment = Dir["#{location}/*/attachments/#{File.basename(__FILE__)}"].first
197
+ # expect(File.exists?(attachment)).to be_true
198
+ #end
199
+ #
200
+ #it 'saves attachment name' do
201
+ # plain = File.read(Dir["#{location}/*/plain.html"].first)
202
+ # expect(plain).to include(File.basename(__FILE__))
203
+ #end
204
+ end
205
+
206
+ context 'attachments in rich mail' do
207
+ let(:url) { mail.attachments[0].url }
208
+
209
+ let!(:mail) do
210
+ Mail.deliver do
211
+ from 'foo@example.com'
212
+ to 'bar@example.com'
213
+ subject 'With attachments'
214
+ attachments[File.basename(__FILE__)] = File.read(__FILE__)
215
+ url = attachments[0].url
216
+ html_part do
217
+ content_type 'text/html; charset=UTF-8'
218
+ body "Here's an image: <img src='#{url}' />"
219
+ end
220
+ end
221
+ end
222
+
223
+ #it 'creates attachments dir with attachment' do
224
+ # attachment = Dir["#{location}/*/attachments/#{File.basename(__FILE__)}"].first
225
+ # expect(File.exists?(attachment)).to be_true
226
+ #end
227
+ #
228
+ #it 'replaces inline attachment urls' do
229
+ # text = File.read(Dir["#{location}/*/rich.html"].first)
230
+ # expect(mail.parts[0].body).to include(url)
231
+ # expect(text).to_not include(url)
232
+ # expect(text).to include("attachments/#{File.basename(__FILE__)}")
233
+ #end
234
+ end
235
+
236
+ context 'attachments with non-word characters in the filename' do
237
+ before do
238
+ Mail.deliver do
239
+ from 'foo@example.com'
240
+ to 'bar@example.com'
241
+ subject 'With attachments'
242
+ text_part do
243
+ body 'This is <plain> text'
244
+ end
245
+ attachments['non word:chars/used,01.txt'] = File.read(__FILE__)
246
+ end
247
+ end
248
+
249
+ #it 'creates attachments dir with attachment' do
250
+ # attachment = Dir["#{location}/*/attachments/non_word_chars_used_01.txt"].first
251
+ # expect(File.exists?(attachment)).to be_true
252
+ #end
253
+ #
254
+ #it 'saves attachment name' do
255
+ # plain = File.read(Dir["#{location}/*/plain.html"].first)
256
+ # expect(plain).to include('non_word_chars_used_01.txt')
257
+ #end
258
+ end
259
+
260
+
261
+ context 'subjectless mail' do
262
+ before do
263
+ #expect(Launchy).to receive(:open)
264
+
265
+ Mail.deliver do
266
+ from 'Foo foo@example.com'
267
+ reply_to 'No Reply no-reply@example.com'
268
+ to 'Bar bar@example.com'
269
+ body 'World! http://example.com'
270
+ end
271
+ end
272
+
273
+ #it 'creates plain html document' do
274
+ # expect(File.exist?(plain_file)).to be_true
275
+ #end
276
+ end
277
+ end
@@ -0,0 +1,204 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ describe KafkaMailer::Message do
5
+ let(:location) { File.expand_path('../../../tmp/letter_opener', __FILE__) }
6
+
7
+ def mail(options={}, &blk)
8
+ Mail.new(options, &blk)
9
+ end
10
+
11
+ describe '#reply_to' do
12
+ it 'handles one email as a string' do
13
+ mail = mail(:reply_to => 'test@example.com')
14
+ message = described_class.new(location, mail)
15
+ expect(message.reply_to).to eq('test@example.com')
16
+ end
17
+
18
+ it 'handles one email with display names' do
19
+ mail = mail(:reply_to => 'test <test@example.com>')
20
+ message = described_class.new(location, mail)
21
+ expect(message.reply_to).to eq('test <test@example.com>')
22
+ end
23
+
24
+ it 'handles array of emails' do
25
+ mail = mail(:reply_to => ['test1@example.com', 'test2@example.com'])
26
+ message = described_class.new(location, mail)
27
+ expect(message.reply_to).to eq('test1@example.com, test2@example.com')
28
+ end
29
+
30
+ it 'handles array of emails with display names' do
31
+ mail = mail(:reply_to => ['test1 <test1@example.com>', 'test2 <test2@example.com>'])
32
+ message = described_class.new(location, mail)
33
+ expect(message.reply_to).to eq('test1 <test1@example.com>, test2 <test2@example.com>')
34
+ end
35
+
36
+ end
37
+
38
+ describe '#to' do
39
+ it 'handles one email as a string' do
40
+ mail = mail(:to => 'test@example.com')
41
+ message = described_class.new(location, mail)
42
+ expect(message.to).to eq('test@example.com')
43
+ end
44
+
45
+ it 'handles one email with display names' do
46
+ mail = mail(:to => 'test <test@example.com>')
47
+ message = described_class.new(location, mail)
48
+ expect(message.to).to eq('test <test@example.com>')
49
+ end
50
+
51
+ it 'handles array of emails' do
52
+ mail = mail(:to => ['test1@example.com', 'test2@example.com'])
53
+ message = described_class.new(location, mail)
54
+ expect(message.to).to eq('test1@example.com, test2@example.com')
55
+ end
56
+
57
+ it 'handles array of emails with display names' do
58
+ mail = mail(:to => ['test1 <test1@example.com>', 'test2 <test2@example.com>'])
59
+ message = described_class.new(location, mail)
60
+ expect(message.to).to eq('test1 <test1@example.com>, test2 <test2@example.com>')
61
+ end
62
+
63
+ end
64
+
65
+ describe '#cc' do
66
+ it 'handles one cc email as a string' do
67
+ mail = mail(:cc => 'test@example.com')
68
+ message = described_class.new(location, mail)
69
+ expect(message.cc).to eq('test@example.com')
70
+ end
71
+
72
+ it 'handles one cc email with display name' do
73
+ mail = mail(:cc => ['test <test1@example.com>', 'test2 <test2@example.com>'])
74
+ message = described_class.new(location, mail)
75
+ expect(message.cc).to eq('test <test1@example.com>, test2 <test2@example.com>')
76
+ end
77
+
78
+ it 'handles array of cc emails' do
79
+ mail = mail(:cc => ['test1@example.com', 'test2@example.com'])
80
+ message = described_class.new(location, mail)
81
+ expect(message.cc).to eq('test1@example.com, test2@example.com')
82
+ end
83
+
84
+ it 'handles array of cc emails with display names' do
85
+ mail = mail(:cc => ['test <test1@example.com>', 'test2 <test2@example.com>'])
86
+ message = described_class.new(location, mail)
87
+ expect(message.cc).to eq('test <test1@example.com>, test2 <test2@example.com>')
88
+ end
89
+
90
+ end
91
+
92
+ describe '#bcc' do
93
+ it 'handles one bcc email as a string' do
94
+ mail = mail(:bcc => 'test@example.com')
95
+ message = described_class.new(location, mail)
96
+ expect(message.bcc).to eq('test@example.com')
97
+ end
98
+
99
+ it 'handles one bcc email with display name' do
100
+ mail = mail(:bcc => ['test <test1@example.com>', 'test2 <test2@example.com>'])
101
+ message = described_class.new(location, mail)
102
+ expect(message.bcc).to eq('test <test1@example.com>, test2 <test2@example.com>')
103
+ end
104
+
105
+ it 'handles array of bcc emails' do
106
+ mail = mail(:bcc => ['test1@example.com', 'test2@example.com'])
107
+ message = described_class.new(location, mail)
108
+ expect(message.bcc).to eq('test1@example.com, test2@example.com')
109
+ end
110
+
111
+ it 'handles array of bcc emails with display names' do
112
+ mail = mail(:bcc => ['test <test1@example.com>', 'test2 <test2@example.com>'])
113
+ message = described_class.new(location, mail)
114
+ expect(message.bcc).to eq('test <test1@example.com>, test2 <test2@example.com>')
115
+ end
116
+
117
+ end
118
+
119
+ describe '#sender' do
120
+ it 'handles one email as a string' do
121
+ mail = mail(:sender => 'sender@example.com')
122
+ message = described_class.new(location, mail)
123
+ expect(message.sender).to eq('sender@example.com')
124
+ end
125
+
126
+ it 'handles one email as a string with display name' do
127
+ mail = mail(:sender => 'test <test@example.com>')
128
+ message = described_class.new(location, mail)
129
+ expect(message.sender).to eq('test <test@example.com>')
130
+ end
131
+
132
+ it 'handles array of emails' do
133
+ mail = mail(:sender => ['sender1@example.com', 'sender2@example.com'])
134
+ message = described_class.new(location, mail)
135
+ expect(message.sender).to eq('sender1@example.com, sender2@example.com')
136
+ end
137
+
138
+ it 'handles array of emails with display names' do
139
+ mail = mail(:sender => ['test <test1@example.com>', 'test2 <test2@example.com>'])
140
+ message = described_class.new(location, mail)
141
+ expect(message.sender).to eq('test <test1@example.com>, test2 <test2@example.com>')
142
+ end
143
+
144
+ end
145
+
146
+ describe '#<=>' do
147
+ it 'sorts rich type before plain type' do
148
+ plain = described_class.new(location, double(content_type: 'text/plain'))
149
+ rich = described_class.new(location, double(content_type: 'text/html'))
150
+ expect([plain, rich].sort).to eq([rich, plain])
151
+ end
152
+ end
153
+
154
+ describe '#auto_link' do
155
+ let(:message){ described_class.new(location, mail) }
156
+
157
+ it 'does not modify unlinkable text' do
158
+ text = 'the quick brown fox jumped over the lazy dog'
159
+ expect(message.auto_link(text)).to eq(text)
160
+ end
161
+
162
+ it 'adds links for http' do
163
+ raw = "Link to http://localhost:3000/example/path path"
164
+ linked = "Link to <a href=\"http://localhost:3000/example/path\">http://localhost:3000/example/path</a> path"
165
+ expect(message.auto_link(raw)).to eq(linked)
166
+ end
167
+ end
168
+
169
+ describe '#body' do
170
+ it 'handles UTF-8 charset body correctly, with QP CTE, for a non-multipart message' do
171
+ mail = mail(:sender => 'sender@example.com') do
172
+ content_type "text/html; charset=UTF-8"
173
+ content_transfer_encoding 'quoted-printable'
174
+ body "☃"
175
+ end
176
+ message = described_class.new(location, mail)
177
+ expect(message.body.encoding.name).to eq('UTF-8')
178
+ end
179
+
180
+ it 'handles UTF-8 charset HTML part body correctly, with QP CTE, for a multipart message' do
181
+ mail = mail(:sender => 'sender@example.com') do
182
+ html_part do
183
+ content_type "text/html; charset=UTF-8"
184
+ content_transfer_encoding 'quoted-printable'
185
+ body "☃"
186
+ end
187
+ end
188
+ message = described_class.new(location, mail, mail.html_part)
189
+ expect(message.body.encoding.name).to eq('UTF-8')
190
+ end
191
+
192
+ it 'handles UTF-8 charset text part body correctly, with QP CTE, for a multipart message' do
193
+ mail = mail(:sender => 'sender@example.com') do
194
+ text_part do
195
+ content_type "text/plain; charset=UTF-8"
196
+ content_transfer_encoding 'quoted-printable'
197
+ body "☃"
198
+ end
199
+ end
200
+ message = described_class.new(location, mail, mail.text_part)
201
+ expect(message.body.encoding.name).to eq('UTF-8')
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,21 @@
1
+ # Code coverage
2
+ # Travis: use code climate
3
+ # Everything else: simplecov
4
+ if ENV['RAILS_ENV'] == 'travis'
5
+ require "codeclimate-test-reporter"
6
+ CodeClimate::TestReporter.start
7
+ else
8
+ require 'simplecov'
9
+ SimpleCov.start
10
+ end
11
+
12
+ require 'rubygems'
13
+ require 'bundler/setup'
14
+ Bundler.require(:default)
15
+
16
+ require "mail"
17
+
18
+ RSpec.configure do |config|
19
+ config.treat_symbols_as_metadata_keys_with_true_values = true
20
+ config.run_all_when_everything_filtered = true
21
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kafka_mailer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eric Hayes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: poseidon
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.0.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.7.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.7.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mail
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.5.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.5.0
97
+ description: When mail is sent from your application, kafka_mailer will put the message
98
+ contents in a kafka queue.
99
+ email: eric@deployfx.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - CHANGELOG.md
105
+ - Gemfile
106
+ - LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - lib/kafka_mailer.rb
110
+ - lib/kafka_mailer/delivery_method.rb
111
+ - lib/kafka_mailer/message.html.erb
112
+ - lib/kafka_mailer/message.rb
113
+ - lib/kafka_mailer/railtie.rb
114
+ - spec/letter_opener/delivery_method_spec.rb
115
+ - spec/letter_opener/message_spec.rb
116
+ - spec/spec_helper.rb
117
+ homepage: http://github.com/ejhayes/kafka_mailer
118
+ licenses: []
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.2.2
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Send email to apache kafka message queue.
140
+ test_files: []