sparkpost_rails 1.0.1 → 1.1.0
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 +4 -4
- data/README.md +99 -14
- data/lib/sparkpost_rails.rb +11 -0
- data/lib/sparkpost_rails/delivery_method.rb +175 -20
- data/lib/sparkpost_rails/version.rb +1 -1
- data/spec/attachments_spec.rb +52 -0
- data/spec/bcc_recipients_spec.rb +81 -0
- data/spec/campaign_id_spec.rb +64 -0
- data/spec/cc_recipients_spec.rb +98 -0
- data/spec/click_tracking_spec.rb +54 -0
- data/spec/{content_spec.rb → inline_content_spec.rb} +9 -1
- data/spec/open_tracking_spec.rb +54 -0
- data/spec/recipients_list_spec.rb +34 -0
- data/spec/return_path_spec.rb +50 -0
- data/spec/sandbox_mode_spec.rb +53 -0
- data/spec/spec_helper.rb +28 -1
- data/spec/substitution_data_spec.rb +40 -0
- data/spec/template_spec.rb +36 -0
- metadata +28 -8
- data/spec/options_spec.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6daae188c29ed7eb15c6a8dbd0c5617755f0e5b3
|
4
|
+
data.tar.gz: 23751028cb6b932d786b812a894656da1b4221e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 970b8a2255cf43de5c63164715993edca7a55deb0a0eb75c47da3079c0938e1132e482a88c9244df73852a4894ba0d94e848d41f9287f0265ec065b8c799570a
|
7
|
+
data.tar.gz: 63fcc3276a23701abdf75bdd14be5000425e5369a78d3dd9c9f1e2d166209e535f1f66df25278e3caf836265e622727d7bc9b5b6dddc6c7c4212b84ceb0419a7
|
data/README.md
CHANGED
@@ -1,17 +1,25 @@
|
|
1
1
|
[](https://badge.fury.io/rb/sparkpost_rails)
|
2
2
|
[](https://travis-ci.org/the-refinery/sparkpost_rails)
|
3
3
|
|
4
|
-
|
4
|
+
SparkPost Rails
|
5
|
+
===============
|
5
6
|
|
6
|
-
|
7
|
+
This gem provides seamless integration of SparkPost with ActionMailer. It provides a delivery_method based upon the SparkPost API, and
|
8
|
+
makes getting setup and sending email via SparkPost in a Rails app pretty painless.
|
9
|
+
|
10
|
+
Getting Started
|
11
|
+
---------------
|
12
|
+
|
13
|
+
Add the gem to your Gemfile
|
7
14
|
|
8
15
|
```
|
9
16
|
gem 'sparkpost_rails'
|
10
17
|
```
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
Then run the bundle command to install it.
|
20
|
+
|
21
|
+
By default, the gem will look for your SparkPost API key in your environment, with the key 'SPARKPOST_API_KEY'. You can override this
|
22
|
+
setting by identifying a different key in the initializer (`config/initializers/sparkpost_rails.rb`):
|
15
23
|
|
16
24
|
```
|
17
25
|
SparkPostRails.configure do |c|
|
@@ -19,11 +27,20 @@ SparkPostRails.configure do |c|
|
|
19
27
|
end
|
20
28
|
```
|
21
29
|
|
22
|
-
|
23
|
-
|
30
|
+
In each environment configuration file from which you want to send emails via Sparkpost, (i.e. `config/environments/production.rb`) add
|
31
|
+
|
32
|
+
```
|
33
|
+
config.action_mailer.delivery_method = :sparkpost
|
34
|
+
```
|
35
|
+
|
36
|
+
Additional Configuration
|
37
|
+
------------------------
|
38
|
+
You can establish values for a number of SparkPost settings in the initializer. These values will be used for every message sent
|
39
|
+
from your application. You can override these settings on individual messages.
|
24
40
|
|
25
41
|
```
|
26
42
|
SparkPostRails.configure do |c|
|
43
|
+
c.sandbox = true
|
27
44
|
c.track_opens = true
|
28
45
|
c.track_clicks = true
|
29
46
|
c.return_path = 'BOUNCE-EMAIL@YOUR-DOMAIN.COM'
|
@@ -34,31 +51,99 @@ end
|
|
34
51
|
The default values for these optional configuration settings are:
|
35
52
|
|
36
53
|
```
|
54
|
+
sandbox = false
|
37
55
|
track_opens = false
|
38
56
|
track_clicks = false
|
39
57
|
return_path = nil
|
40
58
|
campaign_id = nil
|
41
59
|
```
|
42
60
|
|
43
|
-
|
61
|
+
Usage
|
62
|
+
-----
|
63
|
+
When calling the deliver! method on the mail object returned from your mailer, SparkPostRails provides the response data directly back
|
64
|
+
from SparkPost as a hash.
|
44
65
|
|
45
66
|
```
|
46
|
-
|
67
|
+
result = MyMailer.welcome_message(user).deliver!
|
68
|
+
```
|
69
|
+
|
70
|
+
Example:
|
71
|
+
|
72
|
+
```
|
73
|
+
{"total_rejected_recipients"=>0, "total_accepted_recipients"=>1, "id"=>"00000000000000"}
|
47
74
|
```
|
48
75
|
|
49
|
-
|
76
|
+
If the SparkPost API reponds with an error condition, SparkPostRails will raise a SparkPostRails::DeliveryException, which will include all the message
|
77
|
+
data returned by the API.
|
78
|
+
|
79
|
+
SparkPostRails will support multiple recipients, multilple CC, multiple BCC, ReplyTo address, file attachments, inline images, multi-part (HTML and plaintext) messages -
|
80
|
+
all utilizing the standard ActionMailer methodologies.
|
81
|
+
|
82
|
+
|
83
|
+
SparkPost Specific Features
|
84
|
+
---------------------------
|
85
|
+
|
86
|
+
### Configuration Settings
|
87
|
+
You can specifiy values for any or all of the configuration settings listed above on an individual message. Simply add a hash of these values
|
88
|
+
to the mail message in a field named "sparkpost_data":
|
50
89
|
|
51
90
|
```
|
52
|
-
|
91
|
+
data = { track_opens: true,
|
92
|
+
track_clicks: false,
|
93
|
+
campaign_id: "My Campaign"}
|
94
|
+
|
95
|
+
mail(to: to_email, subject: "Test", body: "test", sparkpost_data: data)
|
53
96
|
```
|
54
97
|
|
55
|
-
|
98
|
+
Additionally, return_path can be overriden on a specific email by setting that field on the mail message itself:
|
56
99
|
|
57
100
|
```
|
58
|
-
|
101
|
+
mail(to: to_email, subject: "Test", body: "test", return_path: "bounces@example.com")
|
59
102
|
```
|
60
103
|
|
61
|
-
|
104
|
+
|
105
|
+
### Recipient Lists
|
106
|
+
SparkPostRails supports using SparkPost stored recipient lists. Simply add the list_id to the sparkpost_data hash on the mail message:
|
107
|
+
|
108
|
+
```
|
109
|
+
data = { list_id: "MY-LIST"}
|
110
|
+
|
111
|
+
mail(subject: "Test", body: "test", sparkpost_data: data)
|
112
|
+
```
|
113
|
+
|
114
|
+
**NOTE**: If you supply a recipient list id, all To:, CC:, and BCC: data specified on the mail message will be ignored. The SparkPost API does
|
115
|
+
not support utilizing both a recipient list and inline recipients.
|
116
|
+
|
117
|
+
|
118
|
+
### Substitution Data
|
119
|
+
You can leverage SparkPost's substitution engine through the gem as well. To supply substitution data, simply add your hash of substitution data
|
120
|
+
to your sparkpost_data hash, with the key :substitution_data.
|
121
|
+
|
122
|
+
```
|
123
|
+
sub_data = {first_name: "Sam",
|
124
|
+
last_name: "Test}
|
125
|
+
|
126
|
+
data = { substitution_data: sub_data }
|
127
|
+
|
128
|
+
mail(to: to_email, subject: "Test", body: "test", sparkpost_data: data)
|
129
|
+
```
|
130
|
+
|
131
|
+
### Using SparkPost Templates
|
132
|
+
If you would rather leverage SparkPost's powerful templates rather than building ActionMailer views, SparkPostRails can support that as well. Simply
|
133
|
+
add your template id to the sparkpost_data hash:
|
134
|
+
|
135
|
+
```
|
136
|
+
data = { template_id: "MY-TEMPLATE" }
|
137
|
+
|
138
|
+
mail(to: to_email, sparkpost_data: data)
|
139
|
+
```
|
140
|
+
|
141
|
+
**NOTE**: All inline-content that may exist in your mail message will be ignored, as the SparkPost API does not accept that data when a template id is
|
142
|
+
supplied. This includes Subject, From, ReplyTo, Attachments, and Inline Images.
|
143
|
+
|
144
|
+
|
145
|
+
Update Note!
|
146
|
+
============
|
62
147
|
|
63
148
|
If you have been using Version 0.0.5 or earlier of this gem, when you upgrade, you'll need to
|
64
149
|
change your initalizer as follows:
|
data/lib/sparkpost_rails.rb
CHANGED
@@ -14,20 +14,31 @@ module SparkPostRails
|
|
14
14
|
|
15
15
|
class Configuration
|
16
16
|
attr_accessor :api_key
|
17
|
+
attr_accessor :sandbox
|
18
|
+
|
17
19
|
attr_accessor :track_opens
|
18
20
|
attr_accessor :track_clicks
|
21
|
+
|
19
22
|
attr_accessor :campaign_id
|
20
23
|
attr_accessor :return_path
|
21
24
|
|
25
|
+
|
22
26
|
def initialize
|
27
|
+
set_defaults
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_defaults
|
23
31
|
if ENV.has_key?("SPARKPOST_API_KEY")
|
24
32
|
@api_key = ENV["SPARKPOST_API_KEY"]
|
25
33
|
else
|
26
34
|
@api_key = ""
|
27
35
|
end
|
28
36
|
|
37
|
+
@sandbox = false
|
38
|
+
|
29
39
|
@track_opens = false
|
30
40
|
@track_clicks = false
|
41
|
+
|
31
42
|
@campaign_id = nil
|
32
43
|
@return_path = nil
|
33
44
|
end
|
@@ -11,14 +11,24 @@ module SparkPostRails
|
|
11
11
|
def deliver!(mail)
|
12
12
|
@data = {content: {}}
|
13
13
|
|
14
|
-
|
15
|
-
prepare_from_address_from mail
|
16
|
-
prepare_reply_to_address_from mail
|
14
|
+
sparkpost_data = find_sparkpost_data_from mail
|
17
15
|
|
18
|
-
|
19
|
-
prepare_content_from mail
|
16
|
+
prepare_recipients_from mail, sparkpost_data
|
20
17
|
|
21
|
-
|
18
|
+
if sparkpost_data.has_key?(:template_id)
|
19
|
+
prepare_template_content_from sparkpost_data
|
20
|
+
else
|
21
|
+
prepare_from_address_from mail
|
22
|
+
prepare_reply_to_address_from mail
|
23
|
+
|
24
|
+
prepare_subject_from mail
|
25
|
+
prepare_cc_headers_from mail, sparkpost_data
|
26
|
+
prepare_inline_content_from mail
|
27
|
+
prepare_attachments_from mail
|
28
|
+
end
|
29
|
+
|
30
|
+
prepare_substitution_data_from sparkpost_data
|
31
|
+
prepare_options_from mail, sparkpost_data
|
22
32
|
prepare_headers
|
23
33
|
|
24
34
|
result = post_to_api
|
@@ -27,8 +37,29 @@ module SparkPostRails
|
|
27
37
|
end
|
28
38
|
|
29
39
|
private
|
30
|
-
def
|
31
|
-
|
40
|
+
def find_sparkpost_data_from mail
|
41
|
+
if mail[:sparkpost_data]
|
42
|
+
eval(mail[:sparkpost_data].value)
|
43
|
+
else
|
44
|
+
Hash.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def prepare_recipients_from mail, sparkpost_data
|
49
|
+
if sparkpost_data.has_key?(:recipient_list_id)
|
50
|
+
@data[:recipients] = {list_id: sparkpost_data[:recipient_list_id]}
|
51
|
+
else
|
52
|
+
@data[:recipients] = prepare_addresses(mail.to, mail[:to].display_names)
|
53
|
+
|
54
|
+
if !mail.cc.nil?
|
55
|
+
@data[:recipients] += prepare_copy_addresses(mail.cc, mail[:cc].display_names, mail.to.first).flatten
|
56
|
+
end
|
57
|
+
|
58
|
+
if !mail.bcc.nil?
|
59
|
+
@data[:recipients] += prepare_copy_addresses(mail.bcc, mail[:bcc].display_names, mail.to.first).flatten
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
32
63
|
end
|
33
64
|
|
34
65
|
def prepare_addresses emails, names
|
@@ -44,6 +75,34 @@ module SparkPostRails
|
|
44
75
|
end
|
45
76
|
end
|
46
77
|
|
78
|
+
def prepare_copy_addresses emails, names, header_to
|
79
|
+
emails = [emails] unless emails.is_a?(Array)
|
80
|
+
emails.each_with_index.map {|email, index| prepare_copy_address(email, index, names, header_to) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def prepare_copy_address email, index, names, header_to
|
84
|
+
if !names[index].nil? && !header_to.nil?
|
85
|
+
{ address: { email: email, name: names[index], header_to: header_to } }
|
86
|
+
elsif !names[index].nil?
|
87
|
+
{ address: { email: email, name: names[index] } }
|
88
|
+
elsif !header_to.nil?
|
89
|
+
{ address: { email: email, header_to: header_to } }
|
90
|
+
else
|
91
|
+
{ address: { email: email } }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def prepare_template_content_from sparkpost_data
|
96
|
+
@data[:content][:template_id] = sparkpost_data[:template_id]
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def prepare_substitution_data_from sparkpost_data
|
101
|
+
if sparkpost_data[:substitution_data]
|
102
|
+
@data[:substitution_data] = sparkpost_data[:substitution_data]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
47
106
|
def prepare_from_address_from mail
|
48
107
|
if !mail[:from].display_names.first.nil?
|
49
108
|
from = { email: mail.from.first, name: mail[:from].display_names.first }
|
@@ -64,10 +123,29 @@ module SparkPostRails
|
|
64
123
|
@data[:content][:subject] = mail.subject
|
65
124
|
end
|
66
125
|
|
67
|
-
def
|
126
|
+
def prepare_cc_headers_from mail, sparkpost_data
|
127
|
+
if !mail[:cc].nil? && !sparkpost_data.has_key?(:recipient_list_id)
|
128
|
+
copies = prepare_addresses(mail.cc, mail[:cc].display_names)
|
129
|
+
emails = []
|
130
|
+
|
131
|
+
copies.each do |copy|
|
132
|
+
emails << copy[:address][:email]
|
133
|
+
end
|
134
|
+
|
135
|
+
@data[:content][:headers] = { cc: emails }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
def prepare_inline_content_from mail
|
68
141
|
if mail.multipart?
|
69
|
-
|
70
|
-
|
142
|
+
if mail.html_part
|
143
|
+
@data[:content][:html] = cleanse_encoding(mail.html_part.body.to_s)
|
144
|
+
end
|
145
|
+
|
146
|
+
if mail.text_part
|
147
|
+
@data[:content][:text] = cleanse_encoding(mail.text_part.body.to_s)
|
148
|
+
end
|
71
149
|
else
|
72
150
|
@data[:content][:text] = cleanse_encoding(mail.body.to_s)
|
73
151
|
end
|
@@ -77,18 +155,95 @@ module SparkPostRails
|
|
77
155
|
::JSON.parse({c: content}.to_json)["c"]
|
78
156
|
end
|
79
157
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
158
|
+
def prepare_attachments_from mail
|
159
|
+
attachments = Array.new
|
160
|
+
inline_images = Array.new
|
161
|
+
|
162
|
+
mail.attachments.each do |attachment|
|
163
|
+
#We decode and reencode here to ensure that attachments are
|
164
|
+
#Base64 encoded without line breaks as required by the API.
|
165
|
+
attachment_data = { name: attachment.filename,
|
166
|
+
type: attachment.content_type,
|
167
|
+
data: Base64.encode64(attachment.body.decoded).gsub("\n","") }
|
168
|
+
|
169
|
+
if attachment.inline?
|
170
|
+
inline_images << attachment_data
|
171
|
+
else
|
172
|
+
attachments << attachment_data
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if attachments.count > 0
|
177
|
+
@data[:content][:attachments] = attachments
|
178
|
+
end
|
179
|
+
|
180
|
+
if inline_images.count > 0
|
181
|
+
@data[:content][:inline_images] = inline_images
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def prepare_options_from mail, sparkpost_data
|
186
|
+
@data[:options] = Hash.new
|
187
|
+
|
188
|
+
prepare_sandbox_mode_from sparkpost_data
|
189
|
+
prepare_open_tracking_from sparkpost_data
|
190
|
+
prepare_click_tracking_from sparkpost_data
|
191
|
+
prepare_campaign_id_from sparkpost_data
|
192
|
+
prepare_return_path_from mail
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
def prepare_sandbox_mode_from sparkpost_data
|
197
|
+
if SparkPostRails.configuration.sandbox
|
198
|
+
@data[:options][:sandbox] = true
|
199
|
+
end
|
200
|
+
|
201
|
+
if sparkpost_data.has_key?(:sandbox)
|
202
|
+
if sparkpost_data[:sandbox]
|
203
|
+
@data[:options][:sandbox] = sparkpost_data[:sandbox]
|
204
|
+
else
|
205
|
+
@data[:options].delete(:sandbox)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def prepare_open_tracking_from sparkpost_data
|
211
|
+
@data[:options][:open_tracking] = SparkPostRails.configuration.track_opens
|
212
|
+
|
213
|
+
if sparkpost_data.has_key?(:track_opens)
|
214
|
+
@data[:options][:open_tracking] = sparkpost_data[:track_opens]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def prepare_click_tracking_from sparkpost_data
|
219
|
+
@data[:options][:click_tracking] = SparkPostRails.configuration.track_clicks
|
220
|
+
|
221
|
+
if sparkpost_data.has_key?(:track_clicks)
|
222
|
+
@data[:options][:click_tracking] = sparkpost_data[:track_clicks]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def prepare_campaign_id_from sparkpost_data
|
227
|
+
campaign_id = SparkPostRails.configuration.campaign_id
|
228
|
+
|
229
|
+
if sparkpost_data.has_key?(:campaign_id)
|
230
|
+
campaign_id = sparkpost_data[:campaign_id]
|
231
|
+
end
|
232
|
+
|
233
|
+
if campaign_id
|
234
|
+
@data[:campaign_id] = campaign_id
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def prepare_return_path_from mail
|
239
|
+
return_path = SparkPostRails.configuration.return_path
|
85
240
|
|
86
|
-
unless
|
87
|
-
|
241
|
+
unless mail.return_path.nil?
|
242
|
+
return_path = mail.return_path
|
88
243
|
end
|
89
244
|
|
90
|
-
|
91
|
-
@data[:return_path] =
|
245
|
+
if return_path
|
246
|
+
@data[:return_path] = return_path
|
92
247
|
end
|
93
248
|
end
|
94
249
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SparkPostRails::DeliveryMethod do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@delivery_method = SparkPostRails::DeliveryMethod.new
|
7
|
+
end
|
8
|
+
|
9
|
+
context "No Attachments" do
|
10
|
+
it "does not include attachment elements in the data" do
|
11
|
+
test_email = Mailer.test_email
|
12
|
+
@delivery_method.deliver!(test_email)
|
13
|
+
|
14
|
+
expect(@delivery_method.data[:content].has_key?(:attachments)).to eq(false)
|
15
|
+
expect(@delivery_method.data[:content].has_key?(:inline_images)).to eq(false)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "Standard Attachments" do
|
20
|
+
it "accepts a single attachment" do
|
21
|
+
test_email = Mailer.test_email attachments: 1
|
22
|
+
@delivery_method.deliver!(test_email)
|
23
|
+
|
24
|
+
expect(@delivery_method.data[:content][:attachments]).to eq([{:name=>"file_0.txt", :type=>"text/plain; filename=file_0.txt", :data=>"VGhpcyBpcyBmaWxlIDA="}])
|
25
|
+
end
|
26
|
+
|
27
|
+
it "accepts multiple attachments" do
|
28
|
+
test_email = Mailer.test_email attachments: 2
|
29
|
+
@delivery_method.deliver!(test_email)
|
30
|
+
|
31
|
+
expect(@delivery_method.data[:content][:attachments]).to eq([{:name=>"file_0.txt", :type=>"text/plain; filename=file_0.txt", :data=>"VGhpcyBpcyBmaWxlIDA="}, {:name=>"file_1.txt", :type=>"text/plain; filename=file_1.txt", :data=>"VGhpcyBpcyBmaWxlIDE="}])
|
32
|
+
end
|
33
|
+
|
34
|
+
it "accepts a single image attachment" do
|
35
|
+
test_email = Mailer.test_email images: 1
|
36
|
+
@delivery_method.deliver!(test_email)
|
37
|
+
|
38
|
+
expect(@delivery_method.data[:content][:attachments]).to eq([{:name=>"image_0.png", :type=>"image/png; filename=image_0.png", :data=>"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"}])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Inline Attachments" do
|
43
|
+
it "accepts an inline attachment" do
|
44
|
+
test_email = Mailer.test_email inline_attachments: 1
|
45
|
+
@delivery_method.deliver!(test_email)
|
46
|
+
|
47
|
+
expect(@delivery_method.data[:content][:inline_images]).to eq([{:name=>"image_0.png", :type=>"image/png; filename=image_0.png", :data=>"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"}])
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|