sparkpost_rails 1.1.0 → 1.2.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: 6daae188c29ed7eb15c6a8dbd0c5617755f0e5b3
4
- data.tar.gz: 23751028cb6b932d786b812a894656da1b4221e9
3
+ metadata.gz: 81fd8507b990b04184b483dd003722b8ca08289f
4
+ data.tar.gz: 8b1007d2d0ddd41f8391215e873675d9bc58fc55
5
5
  SHA512:
6
- metadata.gz: 970b8a2255cf43de5c63164715993edca7a55deb0a0eb75c47da3079c0938e1132e482a88c9244df73852a4894ba0d94e848d41f9287f0265ec065b8c799570a
7
- data.tar.gz: 63fcc3276a23701abdf75bdd14be5000425e5369a78d3dd9c9f1e2d166209e535f1f66df25278e3caf836265e622727d7bc9b5b6dddc6c7c4212b84ceb0419a7
6
+ metadata.gz: 5fcc12025be8147f289b17ff1dcb56ea568c2018ab3cb98499e77fea53241ca41b077c1bbcbcdb01b7e4bf8fa22169e8731ff9160fa08ad51a993c6a85035181
7
+ data.tar.gz: c2521eca5c10a02e8d313882653ebfdfb7c4423d5f117d054c29bc5d2f3af6f912be938b45714266267fe29d5bc575eeede28035216cbc678406c1e1934701c3
data/README.md CHANGED
@@ -45,6 +45,8 @@ SparkPostRails.configure do |c|
45
45
  c.track_clicks = true
46
46
  c.return_path = 'BOUNCE-EMAIL@YOUR-DOMAIN.COM'
47
47
  c.campaign_id = 'YOUR-CAMPAIGN'
48
+ c.transactional = true
49
+ c.ip_pool = "MY-POOL"
48
50
  end
49
51
  ```
50
52
 
@@ -56,6 +58,8 @@ track_opens = false
56
58
  track_clicks = false
57
59
  return_path = nil
58
60
  campaign_id = nil
61
+ transactional = false
62
+ ip_pool = nil
59
63
  ```
60
64
 
61
65
  Usage
@@ -90,7 +94,11 @@ to the mail message in a field named "sparkpost_data":
90
94
  ```
91
95
  data = { track_opens: true,
92
96
  track_clicks: false,
93
- campaign_id: "My Campaign"}
97
+ campaign_id: "My Campaign",
98
+ transactional: true,
99
+ ip_pool = "SPECIAL_POOL",
100
+ subaccount_api_key = "SUBACCOUNT_API_KEY"
101
+ }
94
102
 
95
103
  mail(to: to_email, subject: "Test", body: "test", sparkpost_data: data)
96
104
  ```
@@ -101,6 +109,33 @@ Additionally, return_path can be overriden on a specific email by setting that f
101
109
  mail(to: to_email, subject: "Test", body: "test", return_path: "bounces@example.com")
102
110
  ```
103
111
 
112
+ ### Transmission Specific Settings
113
+
114
+ For an individual transmisison you can specifiy that SparkPost should ignore customer supression rules - if your SparkPost account allows for this
115
+ feature. Simply include the flag in the "sparkpost_data" field on the message:
116
+
117
+ ```
118
+ data = { skip_suppression: true }
119
+
120
+ mail(to: to_email, subject: "Test", body: "test", sparkpost_data: data)
121
+ ```
122
+
123
+ To schedule the generation of messages for a future date and time, specify a start time in the date parameter of the mail. Date must be in the future and less than 1 year from today. If date is in the past or too far in the future, no date will be passed, and no delivery schedule will be set.
124
+
125
+ ```
126
+ start_time = DateTime.now + 4.hours
127
+
128
+ mail(to: to_email, subject: "Test", body: "test", date: start_time)
129
+ ```
130
+
131
+ You can set a description for a transmission via the "sparkpost_data" as well. The maximum length of the decription is 1024 characters - values
132
+ longer than the maxium will be truncated.
133
+
134
+ ```
135
+ data = { description: "My Important Message" }
136
+
137
+ mail(to: to_email, subject: "Test", body: "test", sparkpost_data: data)
138
+ ```
104
139
 
105
140
  ### Recipient Lists
106
141
  SparkPostRails supports using SparkPost stored recipient lists. Simply add the list_id to the sparkpost_data hash on the mail message:
@@ -121,7 +156,7 @@ to your sparkpost_data hash, with the key :substitution_data.
121
156
 
122
157
  ```
123
158
  sub_data = {first_name: "Sam",
124
- last_name: "Test}
159
+ last_name: "Test"}
125
160
 
126
161
  data = { substitution_data: sub_data }
127
162
 
@@ -141,6 +176,17 @@ mail(to: to_email, sparkpost_data: data)
141
176
  **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
177
  supplied. This includes Subject, From, ReplyTo, Attachments, and Inline Images.
143
178
 
179
+ ###Other Mail Headers
180
+ If you need to identify custom mail headers for your messages, utilize the ActionMailer header[] method. The gem will pass all approprite headers through
181
+ to the api. Note, per the SparkPost API documentation, "Headers such as 'Content-Type' and 'Content-Transfer-Encoding' are not allowed here as they are auto
182
+ generated upon construction of the email."
183
+
184
+ ```
185
+ headers["Priority"] = "urgent"
186
+ headers["Sensitivity"] = "private"
187
+
188
+ mail(to: to_email, subject: "Test", body: "test")
189
+ ```
144
190
 
145
191
  Update Note!
146
192
  ============
@@ -22,6 +22,10 @@ module SparkPostRails
22
22
  attr_accessor :campaign_id
23
23
  attr_accessor :return_path
24
24
 
25
+ attr_accessor :transactional
26
+ attr_accessor :ip_pool
27
+
28
+ attr_accessor :subaccount
25
29
 
26
30
  def initialize
27
31
  set_defaults
@@ -41,6 +45,11 @@ module SparkPostRails
41
45
 
42
46
  @campaign_id = nil
43
47
  @return_path = nil
48
+
49
+ @transactional = false
50
+ @ip_pool = nil
51
+
52
+ @subaccount = nil
44
53
  end
45
54
  end
46
55
  end
@@ -2,7 +2,7 @@ module SparkPostRails
2
2
  class DeliveryMethod
3
3
  require 'net/http'
4
4
 
5
- attr_accessor :settings, :data, :response
5
+ attr_accessor :settings, :data, :response, :headers
6
6
 
7
7
  def initialize(options = {})
8
8
  @settings = options
@@ -28,8 +28,11 @@ module SparkPostRails
28
28
  end
29
29
 
30
30
  prepare_substitution_data_from sparkpost_data
31
+ prepare_description_from sparkpost_data
31
32
  prepare_options_from mail, sparkpost_data
32
- prepare_headers
33
+ prepare_additional_mail_headers_from mail
34
+
35
+ prepare_api_headers_from sparkpost_data
33
36
 
34
37
  result = post_to_api
35
38
 
@@ -162,9 +165,9 @@ module SparkPostRails
162
165
  mail.attachments.each do |attachment|
163
166
  #We decode and reencode here to ensure that attachments are
164
167
  #Base64 encoded without line breaks as required by the API.
165
- attachment_data = { name: attachment.filename,
168
+ attachment_data = { name: attachment.inline? ? attachment.url : attachment.filename,
166
169
  type: attachment.content_type,
167
- data: Base64.encode64(attachment.body.decoded).gsub("\n","") }
170
+ data: Base64.strict_encode64(attachment.body.decoded) }
168
171
 
169
172
  if attachment.inline?
170
173
  inline_images << attachment_data
@@ -190,7 +193,10 @@ module SparkPostRails
190
193
  prepare_click_tracking_from sparkpost_data
191
194
  prepare_campaign_id_from sparkpost_data
192
195
  prepare_return_path_from mail
193
-
196
+ prepare_transactional_from sparkpost_data
197
+ prepare_skip_suppression_from sparkpost_data
198
+ prepare_ip_pool_from sparkpost_data
199
+ prepare_delivery_schedule_from mail
194
200
  end
195
201
 
196
202
  def prepare_sandbox_mode_from sparkpost_data
@@ -247,11 +253,99 @@ module SparkPostRails
247
253
  end
248
254
  end
249
255
 
250
- def prepare_headers
256
+ def prepare_transactional_from sparkpost_data
257
+ @data[:options][:transactional] = SparkPostRails.configuration.transactional
258
+
259
+ if sparkpost_data.has_key?(:transactional)
260
+ @data[:options][:transactional] = sparkpost_data[:transactional]
261
+ end
262
+ end
263
+
264
+
265
+ def prepare_skip_suppression_from sparkpost_data
266
+ if sparkpost_data[:skip_suppression]
267
+ @data[:options][:skip_suppression] = sparkpost_data[:skip_suppression]
268
+ end
269
+ end
270
+
271
+ def prepare_description_from sparkpost_data
272
+ if sparkpost_data[:description]
273
+ @data[:description] = sparkpost_data[:description].truncate(1024)
274
+ end
275
+ end
276
+
277
+ def prepare_ip_pool_from sparkpost_data
278
+ ip_pool = SparkPostRails.configuration.ip_pool
279
+
280
+ if sparkpost_data.has_key?(:ip_pool)
281
+ ip_pool = sparkpost_data[:ip_pool]
282
+ end
283
+
284
+ if ip_pool
285
+ @data[:options][:ip_pool] = ip_pool
286
+ end
287
+ end
288
+
289
+ def prepare_delivery_schedule_from mail
290
+ # Format YYYY-MM-DDTHH:MM:SS+-HH:MM or "now". Example: '2015-02-11T08:00:00-04:00'. -From SparkPost API Docs
291
+ if mail.date && (mail.date > DateTime.now) && (mail.date < (DateTime.now + 1.year))
292
+ @data[:options][:start_time] = mail.date.strftime("%Y-%m-%dT%H:%M:%S%:z")
293
+ end
294
+ end
295
+
296
+ def prepare_additional_mail_headers_from mail
297
+ valid_headers = Hash.new
298
+
299
+ invalid_names = ["sparkpost-data",
300
+ "from",
301
+ "to",
302
+ "cc",
303
+ "bcc",
304
+ "subject",
305
+ "reply-to",
306
+ "return-path",
307
+ "date",
308
+ "mime-version",
309
+ "content-type",
310
+ "content-transfer-encoding",
311
+ "text-part"]
312
+
313
+ mail.header.fields.each do |field|
314
+ unless invalid_names.include?(field.name.downcase)
315
+ valid_headers[field.name] = field.value
316
+ end
317
+ end
318
+
319
+ if valid_headers.count > 0
320
+ unless @data[:content].has_key?(:headers)
321
+ @data[:content][:headers] = Hash.new
322
+ end
323
+
324
+ @data[:content][:headers].merge!(valid_headers)
325
+ end
326
+ end
327
+
328
+ def prepare_api_headers_from sparkpost_data
329
+ if sparkpost_data.has_key?(:api_key)
330
+ api_key = sparkpost_data[:api_key]
331
+ else
332
+ api_key = SparkPostRails.configuration.api_key
333
+ end
334
+
251
335
  @headers = {
252
- "Authorization" => SparkPostRails.configuration.api_key,
336
+ "Authorization" => api_key,
253
337
  "Content-Type" => "application/json"
254
338
  }
339
+
340
+ if sparkpost_data.has_key?(:subaccount)
341
+ subaccount = sparkpost_data[:subaccount]
342
+ else
343
+ subaccount = SparkPostRails.configuration.subaccount
344
+ end
345
+
346
+ if subaccount
347
+ @headers["X-MSYS-SUBACCOUNT"] = subaccount.to_s
348
+ end
255
349
  end
256
350
 
257
351
  def post_to_api
@@ -1,4 +1,4 @@
1
1
  module SparkPostRails
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
4
4
 
@@ -44,7 +44,11 @@ describe SparkPostRails::DeliveryMethod do
44
44
  test_email = Mailer.test_email inline_attachments: 1
45
45
  @delivery_method.deliver!(test_email)
46
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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"}])
47
+ images = @delivery_method.data[:content][:inline_images]
48
+ expect(images.length).to eq(1)
49
+ image = images[0]
50
+ expect(image).to include(:name, :type=>"image/png; filename=image_0.png", :data=>"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")
51
+ expect(image[:name]).to match(/cid:.*@.*/)
48
52
  end
49
53
 
50
54
  end
@@ -0,0 +1,46 @@
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 "Delivery Schedule" do
10
+ it "handles supplied future DateTime value less than a year from now" do
11
+ start_time = (DateTime.now + 4.hours)
12
+ formatted_start_time = start_time.strftime("%Y-%m-%dT%H:%M:%S%:z")
13
+
14
+ test_email = Mailer.test_email date: start_time
15
+ @delivery_method.deliver!(test_email)
16
+
17
+ expect(@delivery_method.data[:options][:start_time]).to eq(formatted_start_time)
18
+ end
19
+
20
+ it "does not include start_time if date is in the past" do
21
+ start_time = (DateTime.now - 4.hours)
22
+
23
+ test_email = Mailer.test_email date: start_time
24
+ @delivery_method.deliver!(test_email)
25
+
26
+ expect(@delivery_method.data[:options].has_key?(:start_time)).to eq(false)
27
+ end
28
+
29
+ it "does not include start_time if date is more than 1 year from now" do
30
+ start_time = (DateTime.now + 4.years)
31
+
32
+ test_email = Mailer.test_email date: start_time
33
+ @delivery_method.deliver!(test_email)
34
+
35
+ expect(@delivery_method.data[:options].has_key?(:start_time)).to eq(false)
36
+ end
37
+
38
+ it "does not include start_time if not set" do
39
+ test_email = Mailer.test_email
40
+ @delivery_method.deliver!(test_email)
41
+
42
+ expect(@delivery_method.data[:options].has_key?(:start_time)).to eq(false)
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,39 @@
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 "Description" do
10
+ it "handles value from message" do
11
+ test_email = Mailer.test_email sparkpost_data: {description: "Test Email"}
12
+
13
+ @delivery_method.deliver!(test_email)
14
+
15
+ expect(@delivery_method.data[:description]).to eq("Test Email")
16
+ end
17
+
18
+ it "truncates values longer than 1024 characters" do
19
+ raw_description = "X" * 1050
20
+ truncated_description = ("X" * 1021) + "..."
21
+
22
+ test_email = Mailer.test_email sparkpost_data: {description: raw_description}
23
+
24
+ @delivery_method.deliver!(test_email)
25
+
26
+ expect(@delivery_method.data[:description]).to eq(truncated_description)
27
+ end
28
+
29
+ it "does not include description element if not supplied" do
30
+ test_email = Mailer.test_email
31
+ @delivery_method.deliver!(test_email)
32
+
33
+ expect(@delivery_method.data.has_key?(:description)).to eq(false)
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+
@@ -0,0 +1,33 @@
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 "Headers" do
10
+ it "passes appropriate headers through to the API" do
11
+ test_email = Mailer.test_email headers: {"Priority" => "urgent", "Sensitivity" => "private"}
12
+ @delivery_method.deliver!(test_email)
13
+
14
+ expect(@delivery_method.data[:content][:headers]).to eq({"Priority" => "urgent", "Sensitivity" => "private"})
15
+ end
16
+
17
+ it "is compatible with CC functionality" do
18
+ test_email = Mailer.test_email cc: "Carl Test <cc@example.com>", headers: {"Priority" => "urgent", "Sensitivity" => "private"}
19
+ @delivery_method.deliver!(test_email)
20
+
21
+ expect(@delivery_method.data[:content][:headers]).to eq({cc: ["cc@example.com"], "Priority" => "urgent", "Sensitivity" => "private"})
22
+ end
23
+
24
+ it "does not pass inappropriate headers through to the API" do
25
+ test_email = Mailer.test_email headers: {content_type: "POSTSCRIPT", "Priority" => "urgent", "Sensitivity" => "private"}
26
+ @delivery_method.deliver!(test_email)
27
+
28
+ expect(@delivery_method.data[:content][:headers]).to eq({"Priority" => "urgent", "Sensitivity" => "private"})
29
+ end
30
+
31
+ end
32
+ end
33
+
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe SparkPostRails::DeliveryMethod do
4
+
5
+ before(:each) do
6
+ SparkPostRails.configuration.set_defaults
7
+ @delivery_method = SparkPostRails::DeliveryMethod.new
8
+ end
9
+
10
+ context "IP Pool" do
11
+ it "handles ip_pool set in the configuration" do
12
+ SparkPostRails.configure do |c|
13
+ c.ip_pool = "default_ip"
14
+ end
15
+
16
+ test_email = Mailer.test_email
17
+ @delivery_method.deliver!(test_email)
18
+
19
+ expect(@delivery_method.data[:options][:ip_pool]).to eq("default_ip")
20
+ end
21
+
22
+ it "handles ip_pool set on an individual message" do
23
+ test_email = Mailer.test_email sparkpost_data: {ip_pool: "message_ip"}
24
+
25
+ @delivery_method.deliver!(test_email)
26
+
27
+ expect(@delivery_method.data[:options][:ip_pool]).to eq("message_ip")
28
+ end
29
+
30
+ it "handles the value on an individual message overriding configuration" do
31
+ SparkPostRails.configure do |c|
32
+ c.ip_pool = "default_ip"
33
+ end
34
+
35
+ test_email = Mailer.test_email sparkpost_data: {ip_pool: "message_ip"}
36
+
37
+ @delivery_method.deliver!(test_email)
38
+
39
+ expect(@delivery_method.data[:options][:ip_pool]).to eq("message_ip")
40
+ end
41
+
42
+ it "handles a default setting of none" do
43
+ test_email = Mailer.test_email
44
+ @delivery_method.deliver!(test_email)
45
+
46
+ expect(@delivery_method.data[:options].has_key?(:ip_pool)).to eq(false)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,27 @@
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 "Skip Suppression" do
10
+ it "handles value from message" do
11
+ test_email = Mailer.test_email sparkpost_data: {skip_suppression: true}
12
+
13
+ @delivery_method.deliver!(test_email)
14
+
15
+ expect(@delivery_method.data[:options][:skip_suppression]).to eq(true)
16
+ end
17
+
18
+ it "does not include skip_suppression element if not supplied" do
19
+ test_email = Mailer.test_email
20
+ @delivery_method.deliver!(test_email)
21
+
22
+ expect(@delivery_method.data[:options].has_key?(:skip_suppression)).to eq(false)
23
+ end
24
+
25
+ end
26
+ end
27
+
data/spec/spec_helper.rb CHANGED
@@ -52,6 +52,14 @@ class Mailer < ActionMailer::Base
52
52
  options.delete(:inline_attachments)
53
53
  end
54
54
 
55
+ if options.has_key?(:headers)
56
+ if options[:headers].class == Hash
57
+ headers options[:headers]
58
+ end
59
+
60
+ options.delete(:headers)
61
+ end
62
+
55
63
  data.merge! options
56
64
 
57
65
  if data.has_key?(:html_part)
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe SparkPostRails::DeliveryMethod do
4
+
5
+ before(:each) do
6
+ SparkPostRails.configuration.set_defaults
7
+ @delivery_method = SparkPostRails::DeliveryMethod.new
8
+ end
9
+
10
+ context "Message-Specific API Key" do
11
+ it "uses supplied API key instead of default" do
12
+ SparkPostRails.configure do |c|
13
+ c.api_key = 'NEW_DEFAULT_API_KEY'
14
+ end
15
+
16
+ test_email = Mailer.test_email sparkpost_data: {api_key: 'SUBACCOUNT_API_KEY'}
17
+ @delivery_method.deliver!(test_email)
18
+
19
+ expect(@delivery_method.headers).to include("Authorization" => "SUBACCOUNT_API_KEY")
20
+ end
21
+
22
+ it "uses default API if no message-specific API key applied" do
23
+ SparkPostRails.configure do |c|
24
+ c.api_key = 'NEW_DEFAULT_API_KEY'
25
+ end
26
+
27
+ test_email = Mailer.test_email
28
+ @delivery_method.deliver!(test_email)
29
+
30
+ expect(@delivery_method.headers).to include("Authorization" => "NEW_DEFAULT_API_KEY")
31
+ end
32
+ end
33
+
34
+ context "Subaccount ID" do
35
+ it "accepts a subaccount ID in the configuration" do
36
+ SparkPostRails.configure do |c|
37
+ c.subaccount = 123
38
+ end
39
+
40
+ test_email = Mailer.test_email
41
+ @delivery_method.deliver!(test_email)
42
+
43
+ expect(@delivery_method.headers).to include("X-MSYS-SUBACCOUNT" => "123")
44
+ end
45
+
46
+ it "defaults to no subaccount ID in the configuration" do
47
+ expect(SparkPostRails.configuration.subaccount).to eq(nil)
48
+ end
49
+
50
+ it "accepts subaccount ID for an individual message" do
51
+ test_email = Mailer.test_email sparkpost_data: {subaccount: 456}
52
+ @delivery_method.deliver!(test_email)
53
+
54
+ expect(@delivery_method.headers).to include("X-MSYS-SUBACCOUNT" => "456")
55
+ end
56
+
57
+ it "uses subaccount ID on message instead of value in configuration" do
58
+ SparkPostRails.configure do |c|
59
+ c.subaccount = 123
60
+ end
61
+
62
+ test_email = Mailer.test_email sparkpost_data: {subaccount: 456}
63
+ @delivery_method.deliver!(test_email)
64
+
65
+ expect(@delivery_method.headers).to include("X-MSYS-SUBACCOUNT" => "456")
66
+ end
67
+
68
+ it "does not include the subaccount header when none is specified" do
69
+ test_email = Mailer.test_email
70
+ @delivery_method.deliver!(test_email)
71
+
72
+ expect(@delivery_method.headers.has_key?("X-MSYS-SUBACCOUNT")).to eq(false)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe SparkPostRails::DeliveryMethod do
4
+
5
+ before(:each) do
6
+ SparkPostRails.configuration.set_defaults
7
+ @delivery_method = SparkPostRails::DeliveryMethod.new
8
+ end
9
+
10
+ context "Transactional" do
11
+ it "handles transactional flag set in the configuration" do
12
+ SparkPostRails.configure do |c|
13
+ c.transactional = true
14
+ end
15
+
16
+ test_email = Mailer.test_email
17
+ @delivery_method.deliver!(test_email)
18
+
19
+ expect(@delivery_method.data[:options][:transactional]).to eq(true)
20
+ end
21
+
22
+ it "handles transactional set on an individual message" do
23
+ test_email = Mailer.test_email sparkpost_data: {transactional: true}
24
+
25
+ @delivery_method.deliver!(test_email)
26
+
27
+ expect(@delivery_method.data[:options][:transactional]).to eq(true)
28
+ end
29
+
30
+ it "handles the value on an individual message overriding configuration" do
31
+ SparkPostRails.configure do |c|
32
+ c.transactional = true
33
+ end
34
+
35
+ test_email = Mailer.test_email sparkpost_data: {transactional: false}
36
+
37
+ @delivery_method.deliver!(test_email)
38
+
39
+ expect(@delivery_method.data[:options][:transactional]).to eq(false)
40
+ end
41
+
42
+ it "handles unset value" do
43
+ test_email = Mailer.test_email
44
+ @delivery_method.deliver!(test_email)
45
+
46
+ expect(@delivery_method.data[:options][:transactional]).to eq(false)
47
+ end
48
+
49
+ end
50
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparkpost_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Kimball
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-07 00:00:00.000000000 Z
12
+ date: 2016-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -74,8 +74,12 @@ files:
74
74
  - spec/campaign_id_spec.rb
75
75
  - spec/cc_recipients_spec.rb
76
76
  - spec/click_tracking_spec.rb
77
+ - spec/delivery_schedule_spec.rb
78
+ - spec/description_spec.rb
77
79
  - spec/from_spec.rb
80
+ - spec/headers_spec.rb
78
81
  - spec/inline_content_spec.rb
82
+ - spec/ip_pool_spec.rb
79
83
  - spec/open_tracking_spec.rb
80
84
  - spec/recipients_list_spec.rb
81
85
  - spec/recipients_spec.rb
@@ -83,9 +87,12 @@ files:
83
87
  - spec/response_spec.rb
84
88
  - spec/return_path_spec.rb
85
89
  - spec/sandbox_mode_spec.rb
90
+ - spec/skip_suppression_spec.rb
86
91
  - spec/spec_helper.rb
92
+ - spec/subaccount_api_spec.rb
87
93
  - spec/substitution_data_spec.rb
88
94
  - spec/template_spec.rb
95
+ - spec/transactional_spec.rb
89
96
  homepage: https://github.com/the-refinery/sparkpost_rails
90
97
  licenses:
91
98
  - MIT
@@ -112,15 +119,21 @@ specification_version: 4
112
119
  summary: SparkPost for Rails
113
120
  test_files:
114
121
  - spec/cc_recipients_spec.rb
122
+ - spec/subaccount_api_spec.rb
123
+ - spec/ip_pool_spec.rb
115
124
  - spec/inline_content_spec.rb
116
125
  - spec/return_path_spec.rb
126
+ - spec/transactional_spec.rb
117
127
  - spec/recipients_list_spec.rb
118
128
  - spec/campaign_id_spec.rb
129
+ - spec/description_spec.rb
119
130
  - spec/response_spec.rb
120
131
  - spec/bcc_recipients_spec.rb
121
132
  - spec/sandbox_mode_spec.rb
122
133
  - spec/from_spec.rb
123
134
  - spec/recipients_spec.rb
135
+ - spec/delivery_schedule_spec.rb
136
+ - spec/headers_spec.rb
124
137
  - spec/spec_helper.rb
125
138
  - spec/template_spec.rb
126
139
  - spec/open_tracking_spec.rb
@@ -128,3 +141,4 @@ test_files:
128
141
  - spec/attachments_spec.rb
129
142
  - spec/click_tracking_spec.rb
130
143
  - spec/substitution_data_spec.rb
144
+ - spec/skip_suppression_spec.rb