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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 368eabc1112630441a50e7b6c9b2024905900755
4
- data.tar.gz: ed9358eb97aa57d35579b23825d537570b1563de
3
+ metadata.gz: 6daae188c29ed7eb15c6a8dbd0c5617755f0e5b3
4
+ data.tar.gz: 23751028cb6b932d786b812a894656da1b4221e9
5
5
  SHA512:
6
- metadata.gz: 032d4a48dfd4946223695f197872e1abd4e111f85431017a443bbb620352a1f369a9296dfa9b0bc42047587ff474818326e67988ef776fda170ea8080b18f8c4
7
- data.tar.gz: ef0a2aaa4f7ab3fdf4a8962195658c0265886ef7c682e2a6f29f5a517695ef29ee480e65868080d831822ec816d179fa17f59e52d4a6837c332067ac5d24d50b
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
- # SparkPost Rails
4
+ SparkPost Rails
5
+ ===============
5
6
 
6
- In `Gemfile` add
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
- By default, the gem will look for your SparkPost API key in your environment, with the key
13
- 'SPARKPOST_API_KEY'. You can override this setting by identifying a different key in the initializer
14
- (`config/initializers/sparkpost_rails.rb`):
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
- Additionally, the following configuration options are available to be set in your initializer
23
- ( `config/initializers/sparkpost_rails.rb`):
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
- In `config/environments/production.rb` add
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
- config.action_mailer.delivery_method = :sparkpost
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
- The deliver! method returns the response data from the SparkPost API call as a hash:
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
- response = UserMailer.welcome_email(user).deliver_now!
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
- Example:
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
- {"total_rejected_recipients"=>0, "total_accepted_recipients"=>1, "id"=>"00000000000000"}
101
+ mail(to: to_email, subject: "Test", body: "test", return_path: "bounces@example.com")
59
102
  ```
60
103
 
61
- # Update Note!
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:
@@ -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
- prepare_recipients_from mail
15
- prepare_from_address_from mail
16
- prepare_reply_to_address_from mail
14
+ sparkpost_data = find_sparkpost_data_from mail
17
15
 
18
- prepare_subject_from mail
19
- prepare_content_from mail
16
+ prepare_recipients_from mail, sparkpost_data
20
17
 
21
- prepare_options
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 prepare_recipients_from mail
31
- @data[:recipients] = prepare_addresses(mail.to, mail[:to].display_names)
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 prepare_content_from mail
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
- @data[:content][:html] = cleanse_encoding(mail.html_part.body.to_s)
70
- @data[:content][:text] = cleanse_encoding(mail.text_part.body.to_s)
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 prepare_options
81
- @data[:options] = {
82
- :open_tracking => SparkPostRails.configuration.track_opens,
83
- :click_tracking => SparkPostRails.configuration.track_clicks
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 SparkPostRails.configuration.campaign_id.nil?
87
- @data[:campaign_id] = SparkPostRails.configuration.campaign_id
241
+ unless mail.return_path.nil?
242
+ return_path = mail.return_path
88
243
  end
89
244
 
90
- unless SparkPostRails.configuration.return_path.nil?
91
- @data[:return_path] = SparkPostRails.configuration.return_path
245
+ if return_path
246
+ @data[:return_path] = return_path
92
247
  end
93
248
  end
94
249
 
@@ -1,4 +1,4 @@
1
1
  module SparkPostRails
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
4
4
 
@@ -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