sendgrid-actionmailer 2.3.0 → 3.0.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
- SHA1:
3
- metadata.gz: 8b9759582a0f44713dc2156adf7bee7b68bae837
4
- data.tar.gz: c7d4ce8a043e7cd17123050eaf2d82b324354cd7
2
+ SHA256:
3
+ metadata.gz: 8d75cda77ec587c85751c71dd79de21562a35e38562ae691dbd164ec86eae8bf
4
+ data.tar.gz: 8ba014c01b1e37162bb96a7c6b2c00a59c8a6ad9ad7eef126cacd1046dd03d60
5
5
  SHA512:
6
- metadata.gz: 7854d66ae9ad7afee89676cdbc1118a4d088067fce78ccc6482612aa294eb0ff04b19cfbf85f91a77bbf788e13d8c68fce79a70131b7ba6f7fb2b7447ee1f96d
7
- data.tar.gz: 723510475e8b051695d35cfc039b984ba4e788649aa398ea5eaf9acf895456f8cfbe1c85443b3031929d3919cc9103ed6a6898e098a5561d8b8febbf9f04fd28
6
+ metadata.gz: 5c425f306373fd3a70490aacf0e55e312827bdf94b24f33d602bd3dd0335c66682f0352ed9ffe964e50c6dd4a6a99a4ec8cbcca24f1b2e7dfa6e195e63fd00be
7
+ data.tar.gz: 91bf36ef8d4e4a1fd8de5e019f94f9486ae3ea106240256c7c8a08a84c3ebceceab49c348b26936ddc6162e32eb82739646a80b8df6df393855071acb353488e
data/.gitignore CHANGED
@@ -20,3 +20,4 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
+ .DS_Store
@@ -1,14 +1,12 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.5.1
5
- - 2.4.4
6
- - 2.3.4
7
- - 2.3.7
4
+ - 2.6.5
5
+ - 2.5.7
6
+ - 2.4.9
7
+ - 2.3.8
8
8
  before_install:
9
9
  - gem update --system
10
10
  - gem install bundler
11
11
  gemfile:
12
- - gemfiles/mail_2.5.gemfile
13
- - gemfiles/mail_2.6.gemfile
14
12
  - gemfiles/mail_2.7.gemfile
data/Appraisals CHANGED
@@ -1,11 +1,3 @@
1
- appraise "mail-2.5" do
2
- gem "mail", "2.5.4"
3
- end
4
-
5
- appraise "mail-2.6" do
6
- gem "mail", "2.6.4"
7
- end
8
-
9
1
  appraise "mail-2.7" do
10
2
  gem "mail", "2.7.0"
11
3
  end
@@ -1,5 +1,73 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.0.0 - 2020-3-2
4
+
5
+ ### Removed
6
+
7
+ - Compatibility with mail gems before version 2.7
8
+
9
+ ## 2.6.0 - 2020-1-23
10
+
11
+ ### Chages
12
+
13
+ - Dont send content types with dynamic templates (#69)
14
+
15
+ ## 2.5.0 - 2020-1-21
16
+
17
+ ### Chages
18
+
19
+ - Add personalizations field (#60)
20
+
21
+ ### Fixes
22
+
23
+ - Revert "Lazy load ActionMailer::Base" (#64)
24
+ - Yank 2.4.1
25
+
26
+ ## 2.4.2 - 2020-1-21
27
+
28
+ ### Fixes
29
+
30
+ - Revert "Lazy load ActionMailer::Base" (#64)
31
+ - Yank 2.4.1
32
+
33
+ ## 2.4.1 - 2020-1-20
34
+
35
+ ### Changed
36
+
37
+ - Update Travis CI settings to test on latest Ruby and mail gem version (#55)
38
+ - Lazy load ActionMailer::Base (#57)
39
+
40
+ ## 2.4.0 - 2019-07-9
41
+
42
+ ### Changed
43
+
44
+ - Compatibility with `sendgrid-ruby` v6.0.
45
+
46
+ ## 2.3.0 - 2019-4-10
47
+
48
+ ### Fixes
49
+
50
+ - No asm substitutions if template_id present
51
+
52
+ ## 2.2.1 - 2019-1-4
53
+
54
+ ### Fixes
55
+
56
+ - Fix Travis
57
+
58
+ ## 2.2.0 - 2018-11-23
59
+
60
+ ### Fixes
61
+
62
+ - Update Readme
63
+
64
+ ## 2.1.0 - 2018-11-20
65
+
66
+ ### Fixes
67
+
68
+ - Substiutions and dynamic_template_data should be compatible.
69
+
70
+
3
71
  ## 2.0.0 - 2018-08-15
4
72
 
5
73
  ### Changed
data/README.md CHANGED
@@ -217,10 +217,42 @@ The name of the campaign.
217
217
 
218
218
  ### dynamic_template_data (json)
219
219
 
220
- Data to provide for feeding the new dynamic templates in Sendgrid with valueable data. This also disables the following Unsubscribe links because of deprecation of substitutions in the new template implementaiton.
220
+ Data to provide for feeding the new dynamic templates in Sendgrid with valueable data. This also disables the following Unsubscribe links because of deprecation of substitutions in the new template implementaiton. Variables are available within templates using [{{handlebar syntax}}](https://sendgrid.com/docs/for-developers/sending-email/using-handlebars).
221
221
 
222
222
  ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data:{ variable_1: 'foo', variable_2: 'bar'})```
223
223
 
224
+ ### personalizations (json)
225
+
226
+ Allows providing a customized [personalizations](https://sendgrid.com/docs/for-developers/sending-email/personalizations/) array for the v3 Mail Send endpoint. This allows customizing how an email is sent and also allows sending multiple different emails to different recipients with a single API call.
227
+
228
+ The personalizations object supports:
229
+
230
+ - "to", "cc", "bcc" - The recipients of your email.
231
+ - "subject" - The subject of your email.
232
+ - "headers" - Any headers you would like to include in your email.
233
+ - "substitutions" - Any substitutions you would like to be made for your email.
234
+ - "custom_args" - Any custom arguments you would like to include in your email.
235
+ - "send_at" - A specific time that you would like your email to be sent.
236
+ - "dynamic_template_data" - data for dynamic templates.
237
+
238
+ The following should be noted about these personalization attributes:
239
+ - to, cc, or bcc: if either to, cc, or bcc is also set when calling mail, those addresses provided to mail will be inserted as a separate personalization from the ones you provide. However, when using personalizations, you are not required to specify `to` when calling the mail function.
240
+ - dynamic_template_data specified in the mail function will be merged with any dynamic_template_data specified in the personalizations object (with the personalizations object keys having priority).
241
+ - Other fields set in the personalizations object will override any global parameters defined outside of personalizations.
242
+
243
+ Also note that substitutions will not work with dynamic templates.
244
+
245
+ Example usage:
246
+
247
+ ```
248
+ mail(subject: 'default subject', 'email body', personalizations: [
249
+ { to: { email: 'example@example.com' }},
250
+ { to: { email: 'example2@example.com' }}
251
+ ])
252
+
253
+ ```
254
+
255
+
224
256
  ### Unsubscribe Links
225
257
 
226
258
  Sendgrid unfortunately uses <% %> for their default substitution syntax, which makes it incompatible with Rails templates. Their proposed solution is to use Personalization Substitutions with the v3 Mail Send Endpoint. This gem makes that modification to make the following Rails friendly unsubscribe urls.
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "mail", "2.7.0"
5
+ gem "mail", "2.7.1"
6
6
 
7
7
  gemspec :path => "../"
@@ -4,6 +4,7 @@ require 'sendgrid-ruby'
4
4
 
5
5
  module SendGridActionMailer
6
6
  class DeliveryMethod
7
+
7
8
  # TODO: use custom class to customer excpetion payload
8
9
  SendgridDeliveryError = Class.new(StandardError)
9
10
 
@@ -24,17 +25,15 @@ module SendGridActionMailer
24
25
  m.from = to_email(mail.from)
25
26
  m.reply_to = to_email(mail.reply_to)
26
27
  m.subject = mail.subject || ""
27
- # https://sendgrid.com/docs/Classroom/Send/v3_Mail_Send/personalizations.html
28
- m.add_personalization(to_personalizations(mail))
29
28
  end
30
29
 
30
+ add_personalizations(sendgrid_mail, mail)
31
31
  add_api_key(sendgrid_mail, mail)
32
32
  add_content(sendgrid_mail, mail)
33
33
  add_send_options(sendgrid_mail, mail)
34
34
  add_mail_settings(sendgrid_mail, mail)
35
35
  add_tracking_settings(sendgrid_mail, mail)
36
36
 
37
-
38
37
  response = perform_send_request(sendgrid_mail)
39
38
 
40
39
  settings[:return_response] ? response : self
@@ -75,20 +74,51 @@ module SendGridActionMailer
75
74
  end
76
75
  end
77
76
 
78
- def to_personalizations(mail)
79
- Personalization.new.tap do |p|
80
- to_emails(mail.to).each { |to| p.add_to(to) }
81
- to_emails(mail.cc).each { |cc| p.add_cc(cc) }
82
- to_emails(mail.bcc).each { |bcc| p.add_bcc(bcc) }
77
+ def setup_personalization(mail, personalization_hash)
78
+ personalization = Personalization.new
83
79
 
80
+ personalization_hash = self.class.transform_keys(personalization_hash, &:to_s)
81
+
82
+ (personalization_hash['to'] || []).each do |to|
83
+ personalization.add_to Email.new(email: to['email'], name: to['name'])
84
+ end
85
+ (personalization_hash['cc'] || []).each do |cc|
86
+ personalization.add_cc Email.new(email: cc['email'], name: cc['name'])
87
+ end
88
+ (personalization_hash['bcc'] || []).each do |bcc|
89
+ personalization.add_bcc Email.new(email: bcc['email'], name: bcc['name'])
90
+ end
91
+ (personalization_hash['headers'] || []).each do |header_key, header_value|
92
+ personalization.add_header Header.new(key: header_key, value: header_value)
93
+ end
94
+ (personalization_hash['substitutions'] || {}).each do |sub_key, sub_value|
95
+ personalization.add_substitution(Substitution.new(key: sub_key, value: sub_value))
96
+ end
97
+ (personalization_hash['custom_args'] || {}).each do |arg_key, arg_value|
98
+ personalization.add_custom_arg(CustomArg.new(key: arg_key, value: arg_value))
99
+ end
100
+ if personalization_hash['send_at']
101
+ personalization.send_at = personalization_hash['send_at']
102
+ end
103
+ if personalization_hash['subject']
104
+ personalization.subject = personalization_hash['subject']
105
+ end
106
+
107
+ if mail['dynamic_template_data'] || personalization_hash['dynamic_template_data']
84
108
  if mail['dynamic_template_data']
85
- p.add_dynamic_template_data(json_parse(mail['dynamic_template_data'].value))
86
- elsif mail['template_id'].nil?
87
- p.add_substitution(Substitution.new(key: "%asm_group_unsubscribe_raw_url%", value: "<%asm_group_unsubscribe_raw_url%>"))
88
- p.add_substitution(Substitution.new(key: "%asm_global_unsubscribe_raw_url%", value: "<%asm_global_unsubscribe_raw_url%>"))
89
- p.add_substitution(Substitution.new(key: "%asm_preferences_raw_url%", value: "<%asm_preferences_raw_url%>"))
109
+ data = mail['dynamic_template_data'].unparsed_value
110
+ data.merge!(personalization_hash['dynamic_template_data'] || {})
111
+ else
112
+ data = personalization_hash['dynamic_template_data']
90
113
  end
114
+ personalization.add_dynamic_template_data(data)
115
+ elsif mail['template_id'].nil?
116
+ personalization.add_substitution(Substitution.new(key: "%asm_group_unsubscribe_raw_url%", value: "<%asm_group_unsubscribe_raw_url%>"))
117
+ personalization.add_substitution(Substitution.new(key: "%asm_global_unsubscribe_raw_url%", value: "<%asm_global_unsubscribe_raw_url%>"))
118
+ personalization.add_substitution(Substitution.new(key: "%asm_preferences_raw_url%", value: "<%asm_preferences_raw_url%>"))
91
119
  end
120
+
121
+ return personalization
92
122
  end
93
123
 
94
124
  def to_attachment(part)
@@ -115,28 +145,49 @@ module SendGridActionMailer
115
145
  def add_api_key(sendgrid_mail, mail)
116
146
  self.api_key = settings.fetch(:api_key)
117
147
  if mail['delivery-method-options'] && mail['delivery-method-options'].value.include?('api_key')
118
- self.api_key = JSON.parse(mail['delivery-method-options'].value.gsub('=>', ':'))['api_key']
148
+ self.api_key = mail['delivery-method-options'].unparsed_value['api_key']
149
+ end
150
+ end
151
+
152
+ def add_attachments(sendgrid_mail, mail)
153
+ mail.attachments.each do |part|
154
+ sendgrid_mail.add_attachment(to_attachment(part))
119
155
  end
120
156
  end
121
157
 
122
158
  def add_content(sendgrid_mail, mail)
123
- case mail.mime_type
124
- when 'text/plain'
125
- sendgrid_mail.add_content(to_content(:plain, mail.body.decoded))
126
- when 'text/html'
127
- sendgrid_mail.add_content(to_content(:html, mail.body.decoded))
128
- when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
129
- sendgrid_mail.add_content(to_content(:plain, mail.text_part.decoded)) if mail.text_part
130
- sendgrid_mail.add_content(to_content(:html, mail.html_part.decoded)) if mail.html_part
131
-
132
- mail.attachments.each do |part|
133
- sendgrid_mail.add_attachment(to_attachment(part))
159
+ if mail['template_id']
160
+ # We are sending a template, so we don't need to add any content outside
161
+ # of attachments
162
+ add_attachments(sendgrid_mail, mail)
163
+ else
164
+ case mail.mime_type
165
+ when 'text/plain'
166
+ sendgrid_mail.add_content(to_content(:plain, mail.body.decoded))
167
+ when 'text/html'
168
+ sendgrid_mail.add_content(to_content(:html, mail.body.decoded))
169
+ when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
170
+ sendgrid_mail.add_content(to_content(:plain, mail.text_part.decoded)) if mail.text_part
171
+ sendgrid_mail.add_content(to_content(:html, mail.html_part.decoded)) if mail.html_part
172
+
173
+ add_attachments(sendgrid_mail, mail)
134
174
  end
135
175
  end
136
176
  end
137
177
 
138
- def json_parse(text, symbolize=true)
139
- JSON.parse(text.empty? ? '{}' : text.gsub(/:*\"*([\%a-zA-Z0-9_-]*)\"*(( *)=>\ *)/) { "\"#{$1}\":" }, symbolize_names: symbolize)
178
+ def add_personalizations(sendgrid_mail, mail)
179
+ if mail['personalizations']
180
+ mail['personalizations'].unparsed_value.each do |p|
181
+ sendgrid_mail.add_personalization(setup_personalization(mail, p))
182
+ end
183
+ end
184
+ if (mail.to && mail.to.any?) || (mail.cc && mail.cc.any?) || (mail.bcc && mail.bcc.any?)
185
+ personalization = setup_personalization(mail, {})
186
+ to_emails(mail.to).each { |to| personalization.add_to(to) }
187
+ to_emails(mail.cc).each { |cc| personalization.add_cc(cc) }
188
+ to_emails(mail.bcc).each { |bcc| personalization.add_bcc(bcc) }
189
+ sendgrid_mail.add_personalization(personalization)
190
+ end
140
191
  end
141
192
 
142
193
  def add_send_options(sendgrid_mail, mail)
@@ -144,12 +195,12 @@ module SendGridActionMailer
144
195
  sendgrid_mail.template_id = mail['template_id'].to_s
145
196
  end
146
197
  if mail['sections']
147
- json_parse(mail['sections'].value, false).each do |key, value|
198
+ mail['sections'].unparsed_value.each do |key, value|
148
199
  sendgrid_mail.add_section(Section.new(key: key, value: value))
149
200
  end
150
201
  end
151
202
  if mail['headers']
152
- json_parse(mail['headers'].value, false).each do |key, value|
203
+ mail['headers'].unparsed_value.each do |key, value|
153
204
  sendgrid_mail.add_header(Header.new(key: key, value: value))
154
205
  end
155
206
  end
@@ -159,18 +210,21 @@ module SendGridActionMailer
159
210
  end
160
211
  end
161
212
  if mail['custom_args']
162
- json_parse(mail['custom_args'].value, false).each do |key, value|
213
+ mail['custom_args'].unparsed_value.each do |key, value|
163
214
  sendgrid_mail.add_custom_arg(CustomArg.new(key: key, value: value))
164
215
  end
165
216
  end
166
- if mail['send_at'] && mail['batch_id']
217
+ if mail['send_at']
167
218
  sendgrid_mail.send_at = mail['send_at'].value.to_i
168
- sendgrid_mail.batch_id= mail['batch_id'].to_s
219
+ end
220
+ if mail['batch_id']
221
+ sendgrid_mail.batch_id = mail['batch_id'].to_s
169
222
  end
170
223
  if mail['asm']
171
- asm = json_parse(mail['asm'].value)
172
- asm = asm.delete_if { |key, value| !key.to_s.match(/(group_id)|(groups_to_display)/) }
173
- if asm[:group_id]
224
+ asm = mail['asm'].unparsed_value
225
+ asm = asm.delete_if { |key, value|
226
+ !key.to_s.match(/(group_id)|(groups_to_display)/) }
227
+ if asm.keys.map(&:to_s).include?('group_id')
174
228
  sendgrid_mail.asm = ASM.new(asm)
175
229
  end
176
230
  end
@@ -181,7 +235,7 @@ module SendGridActionMailer
181
235
 
182
236
  def add_mail_settings(sendgrid_mail, mail)
183
237
  if mail['mail_settings']
184
- settings = json_parse(mail['mail_settings'].value)
238
+ settings = mail['mail_settings'].unparsed_value || {}
185
239
  sendgrid_mail.mail_settings = MailSettings.new.tap do |m|
186
240
  if settings[:bcc]
187
241
  m.bcc = BccSettings.new(settings[:bcc])
@@ -204,7 +258,7 @@ module SendGridActionMailer
204
258
 
205
259
  def add_tracking_settings(sendgrid_mail, mail)
206
260
  if mail['tracking_settings']
207
- settings = json_parse(mail['tracking_settings'].value)
261
+ settings = mail['tracking_settings'].unparsed_value
208
262
  sendgrid_mail.tracking_settings = TrackingSettings.new.tap do |t|
209
263
  if settings[:click_tracking]
210
264
  t.click_tracking = ClickTracking.new(settings[:click_tracking])
@@ -226,7 +280,7 @@ module SendGridActionMailer
226
280
  result = client.mail._('send').post(request_body: email.to_json) # ლ(ಠ益ಠლ) that API
227
281
 
228
282
  if result.status_code && result.status_code.start_with?('4')
229
- message = JSON.parse(result.body).fetch('errors').pop.fetch('message')
283
+ message = !!(result.body) ? JSON.parse(result.body).fetch('errors').pop.fetch('message') : 'Sendgrid API Error'
230
284
  full_message = "Sendgrid delivery failed with #{result.status_code} #{message}"
231
285
 
232
286
  settings[:raise_delivery_errors] ? raise(SendgridDeliveryError, full_message) : warn(full_message)
@@ -234,5 +288,17 @@ module SendGridActionMailer
234
288
 
235
289
  result
236
290
  end
291
+
292
+ # Recursive key transformation based on Rails deep_transform_values
293
+ def self.transform_keys(object, &block)
294
+ case object
295
+ when Hash
296
+ object.map { |key, value| [yield(key), transform_keys(value, &block)] }.to_h
297
+ when Array
298
+ object.map { |e| transform_keys(e, &block) }
299
+ else
300
+ object
301
+ end
302
+ end
237
303
  end
238
304
  end
@@ -1,3 +1,3 @@
1
1
  module SendGridActionMailer
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '3.0.0'.freeze
3
3
  end
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_dependency 'mail', '~> 2.5'
23
- spec.add_dependency 'sendgrid-ruby', '~> 5.3.0'
22
+ spec.add_dependency 'mail', '~> 2.7'
23
+ spec.add_dependency 'sendgrid-ruby', '~> 6.0'
24
24
 
25
25
  spec.add_development_dependency 'appraisal', '~> 2.1.0'
26
26
  spec.add_development_dependency 'bundler'
@@ -3,6 +3,10 @@ require 'webmock/rspec'
3
3
 
4
4
  module SendGridActionMailer
5
5
  describe DeliveryMethod do
6
+ def transform_keys(object, &block)
7
+ SendGridActionMailer::DeliveryMethod.transform_keys(object, &block)
8
+ end
9
+
6
10
  subject(:mailer) do
7
11
  DeliveryMethod.new(api_key: 'key')
8
12
  end
@@ -242,13 +246,51 @@ module SendGridActionMailer
242
246
  ])
243
247
  end
244
248
 
245
- context 'send options' do
246
- it 'sets a template_id' do
249
+ context 'template_id' do
250
+ before do
247
251
  mail['template_id'] = '1'
252
+ end
253
+
254
+ it 'sets a template_id' do
248
255
  mailer.deliver!(mail)
249
256
  expect(client.sent_mail['template_id']).to eq('1')
250
257
  end
251
258
 
259
+ it 'does not set unsubscribe substitutions' do
260
+ mailer.deliver!(mail)
261
+ expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
262
+ end
263
+
264
+ it 'does not set send a content type' do
265
+ mailer.deliver!(mail)
266
+ expect(client.sent_mail['content']).to eq(nil)
267
+ end
268
+
269
+ it 'does not set send a content type even if body is given' do
270
+ # This matches the default behavior of ActionMail. body must be
271
+ # specified and content_type defaults to text/plain.
272
+ mail.body = 'I heard you like pineapple.'
273
+ mail.content_type = 'text/plain'
274
+ mailer.deliver!(mail)
275
+ expect(client.sent_mail['content']).to eq(nil)
276
+ end
277
+ end
278
+
279
+ context 'without dynamic template data or a template id' do
280
+ it 'sets unsubscribe substitutions' do
281
+ mailer.deliver!(mail)
282
+ expect(client.sent_mail['personalizations'].first).to have_key('substitutions')
283
+ substitutions = client.sent_mail['personalizations'].first['substitutions']
284
+ expect(substitutions).to eq({
285
+ '%asm_group_unsubscribe_raw_url%' => '<%asm_group_unsubscribe_raw_url%>',
286
+ '%asm_global_unsubscribe_raw_url%' => '<%asm_global_unsubscribe_raw_url%>',
287
+ '%asm_preferences_raw_url%' => '<%asm_preferences_raw_url%>'
288
+ })
289
+ end
290
+ end
291
+
292
+ context 'send options' do
293
+
252
294
  it 'sets sections' do
253
295
  mail['sections'] = {'%foo%' => 'bar'}
254
296
  mailer.deliver!(mail)
@@ -283,10 +325,10 @@ module SendGridActionMailer
283
325
  end
284
326
 
285
327
  it 'sets asm' do
286
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
328
+ asm = {group_id: 99, groups_to_display: [4,5,6,7,8]}
287
329
  mail['asm'] = asm
288
330
  mailer.deliver!(mail)
289
- expect(client.sent_mail['asm']).to eq(asm)
331
+ expect(client.sent_mail['asm']).to eq(transform_keys(asm, &:to_s))
290
332
  end
291
333
 
292
334
  it 'sets ip_pool_name' do
@@ -295,109 +337,109 @@ module SendGridActionMailer
295
337
  expect(client.sent_mail['ip_pool_name']).to eq('marketing')
296
338
  end
297
339
 
298
- context 'parse object' do
299
- it "should parse 1.8 hash" do
300
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
301
- mail['asm'] = asm
302
- mailer.deliver!(mail)
303
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
304
- end
305
-
306
- it "should parse 1.9 hash" do
307
- asm = { group_id: 99, groups_to_display: [4,5,6,7,8]}
308
- mail['asm'] = asm
309
- mailer.deliver!(mail)
310
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
311
- end
312
-
313
- it "should parse json" do
314
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
315
- mail['asm'] = asm.to_json
316
- mailer.deliver!(mail)
317
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
318
- end
340
+ it 'should not change values inside custom args' do
341
+ custom_args = { 'text' => 'line with a => in it' }
342
+ mail['custom_args'] = custom_args
343
+ mailer.deliver!(mail)
344
+ expect(client.sent_mail['custom_args']).to eq('text' => 'line with a => in it')
319
345
  end
320
346
 
321
347
  context 'mail_settings' do
322
348
  it 'sets bcc' do
323
- bcc = { 'bcc' => { 'enable' => true, 'email' => 'test@example.com' }}
349
+ bcc = { bcc: { enable: true, email: 'test@example.com' }}
324
350
  mail['mail_settings'] = bcc
325
351
  mailer.deliver!(mail)
326
- expect(client.sent_mail['mail_settings']).to eq(bcc)
352
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bcc, &:to_s))
327
353
  end
328
354
 
329
355
  it 'sets bypass_list_management' do
330
- bypass = { 'bypass_list_management' => { 'enable' => true }}
356
+ bypass = { bypass_list_management: { enable: true }}
331
357
  mail['mail_settings'] = bypass
332
358
  mailer.deliver!(mail)
333
- expect(client.sent_mail['mail_settings']).to eq(bypass)
359
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bypass, &:to_s))
334
360
  end
335
361
 
336
362
  it 'sets footer' do
337
- footer = {'footer' => { 'enable' => true, 'text' => 'Footer Text', 'html' => '<html><body>Footer Text</body></html>'}}
363
+ footer = {footer: { enable: true, text: 'Footer Text', html: '<html><body>Footer Text</body></html>'}}
338
364
  mail['mail_settings'] = footer
339
365
  mailer.deliver!(mail)
340
- expect(client.sent_mail['mail_settings']).to eq(footer)
366
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(footer, &:to_s))
341
367
  end
342
368
 
343
369
  it 'sets sandbox_mode' do
344
- sandbox = {'sandbox_mode' => { 'enable' => true }}
370
+ sandbox = {sandbox_mode: { enable: true }}
345
371
  mail['mail_settings'] = sandbox
346
372
  mailer.deliver!(mail)
347
- expect(client.sent_mail['mail_settings']).to eq(sandbox)
373
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(sandbox, &:to_s))
348
374
  end
349
375
 
350
376
  it 'sets spam_check' do
351
- spam_check = {'spam_check' => { 'enable' => true, 'threshold' => 1, 'post_to_url' => 'https://spamcatcher.sendgrid.com'}}
377
+ spam_check = {spam_check: { enable: true, threshold: 1, post_to_url: 'https://spamcatcher.sendgrid.com'}}
352
378
  mail['mail_settings'] = spam_check
353
379
  mailer.deliver!(mail)
354
- expect(client.sent_mail['mail_settings']).to eq(spam_check)
380
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(spam_check, &:to_s))
355
381
  end
356
382
  end
357
383
 
358
384
  context 'tracking_settings' do
359
385
  it 'sets click_tracking' do
360
- tracking = { 'click_tracking' => { 'enable' => false, 'enable_text' => false }}
361
- mail['tracking_settings'] = tracking
386
+ tracking = { click_tracking: { enable: false, enable_text: false }}
387
+ mail['tracking_settings'] = tracking.dup
362
388
  mailer.deliver!(mail)
363
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
389
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
364
390
  end
365
391
 
366
392
  it 'sets open_tracking' do
367
- tracking = { 'open_tracking' => { 'enable' => true, 'substitution_tag' => 'Optional tag to replace with the open image in the body of the message' }}
393
+ tracking = { open_tracking: { enable: true, substitution_tag: 'Optional tag to replace with the open image in the body of the message' }}
368
394
  mail['tracking_settings'] = tracking
369
395
  mailer.deliver!(mail)
370
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
396
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
371
397
  end
372
398
 
373
399
  it 'sets subscription_tracking' do
374
- tracking = { 'subscription_tracking' => { 'enable' => true, 'text' => 'text to insert into the text/plain portion of the message', 'html' => 'html to insert into the text/html portion of the message', 'substitution_tag' => 'Optional tag to replace with the open image in the body of the def message' }}
400
+ tracking = { subscription_tracking: { enable: true, text: 'text to insert into the text/plain portion of the message', html: 'html to insert into the text/html portion of the message', substitution_tag: 'Optional tag to replace with the open image in the body of the def message' }}
375
401
  mail['tracking_settings'] = tracking
376
402
  mailer.deliver!(mail)
377
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
403
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
378
404
  end
379
405
 
380
406
  it 'sets ganalytics' do
381
- tracking = { 'ganalytics' => {'enable' => true, 'utm_source' => 'some source', 'utm_medium' => 'some medium', 'utm_term' => 'some term', 'utm_content' => 'some content', 'utm_campaign' => 'some campaign' }}
407
+ tracking = { ganalytics: { enable: true, utm_source: 'some source', utm_medium: 'some medium', utm_term: 'some term', utm_content: 'some content', utm_campaign: 'some campaign' }}
382
408
  mail['tracking_settings'] = tracking
383
409
  mailer.deliver!(mail)
384
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
410
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
385
411
  end
386
412
  end
387
413
 
388
414
  context 'dynamic template data' do
415
+ let(:template_data) do
416
+ { variable_1: '1', variable_2: '2' }
417
+ end
418
+
419
+ before { mail['dynamic_template_data'] = template_data }
420
+
389
421
  it 'sets dynamic_template_data' do
390
- template_data = { variable_1: '1', variable_2: '2' }
391
- mail['dynamic_template_data'] = template_data
392
422
  mailer.deliver!(mail)
393
423
  expect(client.sent_mail['personalizations'].first['dynamic_template_data']).to eq(template_data)
394
424
  end
395
- end
396
425
 
397
- it 'sets dynamic template data and sandbox_mode' do
398
- mail['mail_settings'] = '{}'
399
- mailer.deliver!(mail)
400
- expect(client.sent_mail['mail_settings']).to eq(nil)
426
+ it 'does not set unsubscribe substitutions' do
427
+ mailer.deliver!(mail)
428
+ expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
429
+ end
430
+
431
+ context 'containing what looks like hash syntax' do
432
+ let(:template_data) do
433
+ { hint: 'Just use => instead of :' }
434
+ end
435
+
436
+ it 'does not change values inside dynamic template data' do
437
+ mailer.deliver!(mail)
438
+ expect(
439
+ client.sent_mail['personalizations'].first['dynamic_template_data']
440
+ ).to eq(template_data)
441
+ end
442
+ end
401
443
  end
402
444
 
403
445
  it 'sets dynamic template data and sandbox_mode' do
@@ -509,6 +551,212 @@ module SendGridActionMailer
509
551
  expect(content['content_id'].class).to eq(String)
510
552
  end
511
553
  end
554
+
555
+ context 'with personalizations' do
556
+ let(:personalizations) do
557
+ [
558
+ {
559
+ 'to' => [
560
+ {'email' => 'john1@example.com', 'name' => 'John 1'},
561
+ {'email' => 'john2@example.com', 'name' => 'John 2'},
562
+ ]
563
+ },
564
+ {
565
+ 'to' => [
566
+ {'email' => 'john3@example.com', 'name' => 'John 3'},
567
+ {'email' => 'john4@example.com'}
568
+ ],
569
+ 'cc' => [
570
+ {'email' => 'cc@example.com'}
571
+ ],
572
+ 'bcc' => [
573
+ {'email' => 'bcc@example.com'}
574
+ ],
575
+ 'substitutions' => {
576
+ '%fname%' => 'Bob'
577
+ },
578
+ 'subject' => 'personalized subject',
579
+ 'send_at' => 1443636843,
580
+ 'custom_args' => {
581
+ 'user_id' => '343'
582
+ },
583
+ 'headers' => {
584
+ 'X-Test' => true
585
+ }
586
+ }
587
+ ]
588
+ end
589
+
590
+ before do
591
+ mail.to = nil
592
+ mail.cc = nil
593
+ mail.bcc = nil
594
+ mail['personalizations'] = personalizations
595
+ end
596
+
597
+ it 'sets the provided to address personalizations' do
598
+ mailer.deliver!(mail)
599
+ expect(client.sent_mail['personalizations'].length).to eq(2)
600
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(personalizations[0]['to'])
601
+ expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[1]['to'])
602
+ end
603
+
604
+ it 'sets the provided cc address personalizations' do
605
+ mailer.deliver!(mail)
606
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('cc')
607
+ expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[1]['cc'])
608
+ end
609
+
610
+ it 'sets the provided bcc address personalizations' do
611
+ mailer.deliver!(mail)
612
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('bcc')
613
+ expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[1]['bcc'])
614
+ end
615
+
616
+ it 'sets the provided subject personalizations' do
617
+ mailer.deliver!(mail)
618
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('subject')
619
+ expect(client.sent_mail['personalizations'][1]['subject']).to eq(personalizations[1]['subject'])
620
+ end
621
+
622
+ it 'sets the provided headers personalizations' do
623
+ mailer.deliver!(mail)
624
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('headers')
625
+ expect(client.sent_mail['personalizations'][1]['headers']).to eq(personalizations[1]['headers'])
626
+ end
627
+
628
+ it 'sets the provided custom_arg personalizations' do
629
+ mailer.deliver!(mail)
630
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('custom_args')
631
+ expect(client.sent_mail['personalizations'][1]['custom_args']).to eq(personalizations[1]['custom_args'])
632
+ end
633
+
634
+ it 'sets the provided send_at personalizations' do
635
+ mailer.deliver!(mail)
636
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('send_at')
637
+ expect(client.sent_mail['personalizations'][1]['send_at']).to eq(personalizations[1]['send_at'])
638
+ end
639
+
640
+ it 'sets the provided substitution personalizations' do
641
+ mailer.deliver!(mail)
642
+ expect(client.sent_mail['personalizations'][1]['substitutions']).to include(personalizations[1]['substitutions'])
643
+ end
644
+
645
+ it 'adds to the unsubscribe link substitutions' do
646
+ mailer.deliver!(mail)
647
+ expect(client.sent_mail['personalizations'][0]['substitutions']).to eq({
648
+ '%asm_group_unsubscribe_raw_url%' => '<%asm_group_unsubscribe_raw_url%>',
649
+ '%asm_global_unsubscribe_raw_url%' => '<%asm_global_unsubscribe_raw_url%>',
650
+ '%asm_preferences_raw_url%' => '<%asm_preferences_raw_url%>'
651
+ })
652
+ expect(client.sent_mail['personalizations'][1]['substitutions']).to include({
653
+ '%asm_group_unsubscribe_raw_url%' => '<%asm_group_unsubscribe_raw_url%>',
654
+ '%asm_global_unsubscribe_raw_url%' => '<%asm_global_unsubscribe_raw_url%>',
655
+ '%asm_preferences_raw_url%' => '<%asm_preferences_raw_url%>'
656
+ })
657
+ end
658
+
659
+ context 'with symbols used as keys' do
660
+ let(:personalizations) do
661
+ [
662
+ {
663
+ to: [
664
+ {email: 'sally1@example.com', name: 'Sally 1'},
665
+ {email: 'sally2@example.com', name: 'Sally 2'},
666
+ ]
667
+ }
668
+ ]
669
+ end
670
+
671
+ it 'still works' do
672
+ mailer.deliver!(mail)
673
+ expect(client.sent_mail['personalizations'].length).to eq(1)
674
+ expected_to = personalizations[0][:to].map { |t| transform_keys(t, &:to_s) }
675
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(expected_to)
676
+ end
677
+ end
678
+
679
+ context 'dynamic template data passed into a personalizaiton' do
680
+ let(:personalization_data) do
681
+ {
682
+ 'variable_1' => '1', 'variable_2' => '2'
683
+ }
684
+ end
685
+
686
+ let(:personalizations_with_dynamic_data) do
687
+ personalizations.tap do |p|
688
+ p[1]['dynamic_template_data'] = personalization_data
689
+ end
690
+ end
691
+
692
+ before do
693
+ mail['personalizations'] = nil
694
+ mail['personalizations'] = personalizations_with_dynamic_data
695
+ end
696
+
697
+ it 'sets the provided dynamic template data personalizations' do
698
+ mailer.deliver!(mail)
699
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('dynamic_template_data')
700
+ expect(client.sent_mail['personalizations'][1]['dynamic_template_data']).to eq(personalization_data)
701
+ end
702
+
703
+ context 'dynamic template data is also set on the mail object' do
704
+ let(:mail_template_data) do
705
+ { 'variable_3' => '1', 'variable_4' => '2' }
706
+ end
707
+
708
+ before { mail['dynamic_template_data'] = mail_template_data.dup }
709
+
710
+ it 'sets dynamic_template_data where not also provided as a personalization' do
711
+ mailer.deliver!(mail)
712
+ expect(client.sent_mail['personalizations'][0]['dynamic_template_data']).to eq(mail_template_data)
713
+ end
714
+
715
+ it 'merges the template data with a personalizations dynamic data' do
716
+ mailer.deliver!(mail)
717
+ expect(client.sent_mail['personalizations'][1]['dynamic_template_data']).to eq(
718
+ mail_template_data.merge(personalization_data)
719
+ )
720
+ end
721
+ end
722
+ end
723
+
724
+ context 'when to is set on mail object' do
725
+ before { mail.to = 'test@sendgrid.com' }
726
+
727
+ it 'adds that to address as a separate personalization' do
728
+ mailer.deliver!(mail)
729
+ expect(client.sent_mail['personalizations'].length).to eq(3)
730
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(personalizations[0]['to'])
731
+ expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[1]['to'])
732
+ expect(client.sent_mail['personalizations'][2]['to']).to eq([{"email"=>"test@sendgrid.com"}])
733
+ end
734
+ end
735
+
736
+ context 'when cc is set on mail object' do
737
+ before { mail.cc = 'test@sendgrid.com' }
738
+
739
+ it 'adds that cc address as a separate personalization' do
740
+ mailer.deliver!(mail)
741
+ expect(client.sent_mail['personalizations'].length).to eq(3)
742
+ expect(client.sent_mail['personalizations'][0]['cc']).to eq(personalizations[0]['cc'])
743
+ expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[1]['cc'])
744
+ expect(client.sent_mail['personalizations'][2]['cc']).to eq([{"email"=>"test@sendgrid.com"}])
745
+ end
746
+ end
747
+
748
+ context 'when bcc is set on mail object' do
749
+ before { mail.bcc = 'test@sendgrid.com' }
750
+
751
+ it 'adds that bcc address as a separate personalization' do
752
+ mailer.deliver!(mail)
753
+ expect(client.sent_mail['personalizations'].length).to eq(3)
754
+ expect(client.sent_mail['personalizations'][0]['bcc']).to eq(personalizations[0]['bcc'])
755
+ expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[1]['bcc'])
756
+ expect(client.sent_mail['personalizations'][2]['bcc']).to eq([{"email"=>"test@sendgrid.com"}])
757
+ end
758
+ end
759
+ end
512
760
  end
513
761
  end
514
762
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sendgrid-actionmailer
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eddie Zaneski
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-04-10 00:00:00.000000000 Z
13
+ date: 2020-03-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mail
@@ -18,28 +18,28 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '2.5'
21
+ version: '2.7'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: '2.5'
28
+ version: '2.7'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: sendgrid-ruby
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: 5.3.0
35
+ version: '6.0'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: 5.3.0
42
+ version: '6.0'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: appraisal
45
45
  requirement: !ruby/object:Gem::Requirement
@@ -128,8 +128,6 @@ files:
128
128
  - LICENSE.txt
129
129
  - README.md
130
130
  - Rakefile
131
- - gemfiles/mail_2.5.gemfile
132
- - gemfiles/mail_2.6.gemfile
133
131
  - gemfiles/mail_2.7.gemfile
134
132
  - lib/sendgrid-actionmailer.rb
135
133
  - lib/sendgrid_actionmailer.rb
@@ -157,8 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
155
  - !ruby/object:Gem::Version
158
156
  version: '0'
159
157
  requirements: []
160
- rubyforge_project:
161
- rubygems_version: 2.6.14
158
+ rubygems_version: 3.0.6
162
159
  signing_key:
163
160
  specification_version: 4
164
161
  summary: SendGrid support for ActionMailer.
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "mail", "2.5.4"
6
-
7
- gemspec :path => "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "mail", "2.6.4"
6
-
7
- gemspec :path => "../"