sparkpost_rails 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/sparkpost_rails.svg)](https://badge.fury.io/rb/sparkpost_rails)
|
2
2
|
[![Build Status](https://travis-ci.org/the-refinery/sparkpost_rails.svg?branch=master)](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
|