sendgrid-actionmailer 2.4.0 → 3.0.1

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: bd39b2edccaafaa5842c9ce058a3cb454c128e6c
4
- data.tar.gz: 23f300c8fb257f9f06983eaebcb54504fcb2fbcf
2
+ SHA256:
3
+ metadata.gz: 216459b27a5755c4aaadca781956a6ca22298ade1fabd652debec76cc3727864
4
+ data.tar.gz: 3876cce1f0c1cf0011cbc62bce448bf450124ac7639aea5b03010a6378ed0529
5
5
  SHA512:
6
- metadata.gz: 272cd434acac86b4a069c6d53ab0a9462021d4550cd4f24c2659258ceddf30f10d7c30c42de558d064400f676bd1a7107149ac34c92fb7a8cd115656c307fa2d
7
- data.tar.gz: cfeabef756e01eaf744ba91401650495e591f0f1d224d3ac4eca0b6ece405a9629937c86aa1fbdb9fb376a2da798f38a929c65611d3d0ea154265acec3855494
6
+ metadata.gz: '0668df5a8839949ce2cfc252f8d86ed7beecf5c0ff0f6524a3215e5c79dbcbfa9279267be7790bec0e81634d74e943182cf2fe7ee2ef411de1346ca7f9d72918'
7
+ data.tar.gz: 9cee753e264ec435abe9a6fa468cb9521adba7d2914c00c811b8683bb39265df86dfec71b48bc9577d72bff174eec64adae9031ce0340cc56cc439fc2e82c1fd
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,11 +1,78 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.0.1 - 2020-4-3
4
+
5
+ ### Changes
6
+
7
+ - Validate error response body for empty string
8
+
9
+ ## 3.0.0 - 2020-3-2
10
+
11
+ ### Removed
12
+
13
+ - Compatibility with mail gems before version 2.7
14
+
15
+ ## 2.6.0 - 2020-1-23
16
+
17
+ ### Changes
18
+
19
+ - Dont send content types with dynamic templates (#69)
20
+
21
+ ## 2.5.0 - 2020-1-21
22
+
23
+ ### Changes
24
+
25
+ - Add personalizations field (#60)
26
+
27
+ ### Fixes
28
+
29
+ - Revert "Lazy load ActionMailer::Base" (#64)
30
+ - Yank 2.4.1
31
+
32
+ ## 2.4.2 - 2020-1-21
33
+
34
+ ### Fixes
35
+
36
+ - Revert "Lazy load ActionMailer::Base" (#64)
37
+ - Yank 2.4.1
38
+
39
+ ## 2.4.1 - 2020-1-20
40
+
41
+ ### Changed
42
+
43
+ - Update Travis CI settings to test on latest Ruby and mail gem version (#55)
44
+ - Lazy load ActionMailer::Base (#57)
45
+
3
46
  ## 2.4.0 - 2019-07-9
4
47
 
5
48
  ### Changed
6
49
 
7
50
  - Compatibility with `sendgrid-ruby` v6.0.
8
51
 
52
+ ## 2.3.0 - 2019-4-10
53
+
54
+ ### Fixes
55
+
56
+ - No asm substitutions if template_id present
57
+
58
+ ## 2.2.1 - 2019-1-4
59
+
60
+ ### Fixes
61
+
62
+ - Fix Travis
63
+
64
+ ## 2.2.0 - 2018-11-23
65
+
66
+ ### Fixes
67
+
68
+ - Update Readme
69
+
70
+ ## 2.1.0 - 2018-11-20
71
+
72
+ ### Fixes
73
+
74
+ - Substiutions and dynamic_template_data should be compatible.
75
+
9
76
 
10
77
  ## 2.0.0 - 2018-08-15
11
78
 
data/README.md CHANGED
@@ -31,11 +31,12 @@ If you need to send mail for a number of Sendgrid accounts, you can set the API
31
31
 
32
32
  ```ruby
33
33
  mail(to: 'example@email.com',
34
- subject: 'email subject',
35
- body: 'email body',
36
- delivery_method_options: {
37
- api_key: 'SENDGRID_API_KEY'
38
- })
34
+ subject: 'email subject',
35
+ body: 'email body',
36
+ delivery_method_options: {
37
+ api_key: 'SENDGRID_API_KEY'
38
+ }
39
+ )
39
40
  ```
40
41
 
41
42
  ## SendGrid Mail Extensions
@@ -86,7 +87,7 @@ The unsubscribe group to associate with this email.
86
87
  #### groups_to_display (array[integer])
87
88
  An array containing the unsubscribe groups that you would like to be displayed on the unsubscribe preferences page.
88
89
 
89
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', asm: group_id: 99, groups_to_display: [4,5,6,7,8])```
90
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', asm: { group_id: 99, groups_to_display: [4,5,6,7,8] })```
90
91
 
91
92
  ### ip_pool_name (string)
92
93
  The IP Pool that you would like to send this email from.
@@ -105,7 +106,7 @@ Indicates if this setting is enabled.
105
106
  ##### email (string)
106
107
  The email address that you would like to receive the BCC.
107
108
 
108
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: {bcc: {enable: true, email: 'bcc@example.com}})```
109
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: { bcc: { enable: true, email: 'bcc@example.com }})```
109
110
 
110
111
  #### bypass_list_management (object)
111
112
  Allows you to bypass all unsubscribe groups and suppressions to ensure that the email is delivered to every single recipient. This should only be used in emergencies when it is absolutely necessary that every recipient receives your email.
@@ -113,7 +114,7 @@ Allows you to bypass all unsubscribe groups and suppressions to ensure that the
113
114
  ###### enable (boolean)
114
115
  Indicates if this setting is enabled.
115
116
 
116
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings:{ bypass_list_management: { enable: true }})```
117
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: { bypass_list_management: { enable: true }})```
117
118
 
118
119
  #### footer (object)
119
120
  The default footer that you would like included on every email.
@@ -127,7 +128,7 @@ The plain text content of your footer.
127
128
  ##### html (string)
128
129
  The HTML content of your footer.
129
130
 
130
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings:{ footer: { enable: true, text: 'FOOTER', html: '<h1>FOOTER</h1>' }})```
131
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: { footer: { enable: true, text: 'FOOTER', html: '<h1>FOOTER</h1>' }})```
131
132
 
132
133
  #### sandbox_mode (object)
133
134
  This allows you to send a test email to ensure that your request body is valid and formatted correctly.
@@ -135,7 +136,7 @@ This allows you to send a test email to ensure that your request body is valid a
135
136
  ##### enable (boolean)
136
137
  Indicates if this setting is enabled.
137
138
 
138
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings:{ sandbox_mode: { enable: true }})```
139
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: { sandbox_mode: { enable: true }})```
139
140
 
140
141
  #### spam_check (object)
141
142
  This allows you to test the content of your email for spam.
@@ -149,7 +150,8 @@ The threshold used to determine if your content qualifies as spam on a scale fro
149
150
  ##### post_to_url (string)
150
151
  An Inbound Parse URL that you would like a copy of your email along with the spam report to be sent to.
151
152
 
152
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings:{ spam_check: {enable: true, threshold: 1, post_to_url: 'https://spamcatcher.sendgrid.com'}})```
153
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', mail_settings: { spam_check: { enable: true, threshold: 1, post_to_url: 'https://spamcatcher.sendgrid.com' }})```
154
+
153
155
  ### tracking_settings(json)
154
156
  Settings to determine how you would like to track the metrics of how your recipients interact with your email.
155
157
 
@@ -159,10 +161,10 @@ Allows you to track whether a recipient clicked a link in your email.
159
161
  ##### enable (boolean)
160
162
  Indicates if this setting is enabled.
161
163
 
162
- ##### enable_text (boolean)
164
+ ##### enable_text (boolean)
163
165
  Indicates if this setting should be included in the text/plain portion of your email.
164
166
 
165
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings:{ enable: false, enable_text: false }})```
167
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings: { click_tracking: { enable: false, enable_text: false }})```
166
168
 
167
169
  #### open_tracking (object)
168
170
  Allows you to track whether the email was opened or not, but including a single pixel image in the body of the content. When the pixel is loaded, we can log that the email was opened.
@@ -173,7 +175,7 @@ Indicates if this setting is enabled.
173
175
  ##### substitution_tag (string)
174
176
  Allows you to specify a substitution tag that you can insert in the body of your email at a location that you desire. This tag will be replaced by the open tracking pixel.
175
177
 
176
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings:{ enable: true, substitution_tag: 'Optional tag to replace with the open image in the body of the message' }})```
178
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings: { open_tracking: { enable: true, substitution_tag: 'Optional tag to replace with the open image in the body of the message' }})```
177
179
 
178
180
  #### subscription_tracking (object)
179
181
  Allows you to insert a subscription management link at the bottom of the text and html bodies of your email. If you would like to specify the location of the link within your email, you may use the substitution_tag.
@@ -190,7 +192,7 @@ HTML to be appended to the email, with the subscription tracking link. You may c
190
192
  ##### substitution_tag (string)
191
193
  A tag that will be replaced with the unsubscribe URL. for example: [unsubscribe_url]. If this parameter is used, it will override both the text and html parameters. The URL of the link will be placed at the substitution tag’s location, with no additional formatting.
192
194
 
193
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings:{ 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 message' }})```
195
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings: { 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 message' }})```
194
196
 
195
197
  #### ganalytics (object)
196
198
  Allows you to enable tracking provided by Google Analytics.
@@ -213,17 +215,49 @@ Used to differentiate your campaign from advertisements.
213
215
  ##### utm_campaign (string)
214
216
  The name of the campaign.
215
217
 
216
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings:{ enable: true, utm_source: 'some source', utm_medium: 'some medium', utm_term: 'some term', utm_content: 'some content', utm_campaign: 'some campaign' }})```
218
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', tracking_settings: { ganalytics: { enable: true, utm_source: 'some source', utm_medium: 'some medium', utm_term: 'some term', utm_content: 'some content', utm_campaign: 'some campaign' }})```
217
219
 
218
220
  ### dynamic_template_data (json)
219
221
 
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.
222
+ 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).
223
+
224
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data: { variable_1: 'foo', variable_2: 'bar' })```
225
+
226
+ ### personalizations (json)
227
+
228
+ 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.
229
+
230
+ The personalizations object supports:
231
+
232
+ - "to", "cc", "bcc" - The recipients of your email.
233
+ - "subject" - The subject of your email.
234
+ - "headers" - Any headers you would like to include in your email.
235
+ - "substitutions" - Any substitutions you would like to be made for your email.
236
+ - "custom_args" - Any custom arguments you would like to include in your email.
237
+ - "send_at" - A specific time that you would like your email to be sent.
238
+ - "dynamic_template_data" - data for dynamic templates.
239
+
240
+ The following should be noted about these personalization attributes:
241
+ - 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.
242
+ - 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).
243
+ - Other fields set in the personalizations object will override any global parameters defined outside of personalizations.
244
+
245
+ Also note that substitutions will not work with dynamic templates.
246
+
247
+ Example usage:
248
+
249
+ ```
250
+ mail(subject: 'default subject', 'email body', personalizations: [
251
+ { to: { email: 'example@example.com' }},
252
+ { to: { email: 'example2@example.com' }}
253
+ ])
254
+
255
+ ```
221
256
 
222
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data:{ variable_1: 'foo', variable_2: 'bar'})```
223
257
 
224
258
  ### Unsubscribe Links
225
259
 
226
- 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.
260
+ 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.
227
261
 
228
262
  * `<a href="%asm_group_unsubscribe_raw_url%">Unsubscribe</a>`
229
263
  * `<a href="%asm_global_unsubscribe_raw_url%">Unsubscribe from List</a>`
@@ -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,7 +210,7 @@ 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
@@ -170,9 +221,10 @@ module SendGridActionMailer
170
221
  sendgrid_mail.batch_id = mail['batch_id'].to_s
171
222
  end
172
223
  if mail['asm']
173
- asm = json_parse(mail['asm'].value)
174
- asm = asm.delete_if { |key, value| !key.to_s.match(/(group_id)|(groups_to_display)/) }
175
- 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')
176
228
  sendgrid_mail.asm = ASM.new(asm)
177
229
  end
178
230
  end
@@ -183,7 +235,7 @@ module SendGridActionMailer
183
235
 
184
236
  def add_mail_settings(sendgrid_mail, mail)
185
237
  if mail['mail_settings']
186
- settings = json_parse(mail['mail_settings'].value)
238
+ settings = mail['mail_settings'].unparsed_value || {}
187
239
  sendgrid_mail.mail_settings = MailSettings.new.tap do |m|
188
240
  if settings[:bcc]
189
241
  m.bcc = BccSettings.new(settings[:bcc])
@@ -206,7 +258,7 @@ module SendGridActionMailer
206
258
 
207
259
  def add_tracking_settings(sendgrid_mail, mail)
208
260
  if mail['tracking_settings']
209
- settings = json_parse(mail['tracking_settings'].value)
261
+ settings = mail['tracking_settings'].unparsed_value
210
262
  sendgrid_mail.tracking_settings = TrackingSettings.new.tap do |t|
211
263
  if settings[:click_tracking]
212
264
  t.click_tracking = ClickTracking.new(settings[:click_tracking])
@@ -228,7 +280,7 @@ module SendGridActionMailer
228
280
  result = client.mail._('send').post(request_body: email.to_json) # ლ(ಠ益ಠლ) that API
229
281
 
230
282
  if result.status_code && result.status_code.start_with?('4')
231
- message = JSON.parse(result.body).fetch('errors').pop.fetch('message')
283
+ message = !(result.body.empty?) ? JSON.parse(result.body).fetch('errors').pop.fetch('message') : 'Sendgrid API Error'
232
284
  full_message = "Sendgrid delivery failed with #{result.status_code} #{message}"
233
285
 
234
286
  settings[:raise_delivery_errors] ? raise(SendgridDeliveryError, full_message) : warn(full_message)
@@ -236,5 +288,17 @@ module SendGridActionMailer
236
288
 
237
289
  result
238
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
239
303
  end
240
304
  end
@@ -1,3 +1,3 @@
1
1
  module SendGridActionMailer
2
- VERSION = '2.4.0'.freeze
2
+ VERSION = '3.0.1'.freeze
3
3
  end
@@ -19,7 +19,7 @@ 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'
22
+ spec.add_dependency 'mail', '~> 2.7'
23
23
  spec.add_dependency 'sendgrid-ruby', '~> 6.0'
24
24
 
25
25
  spec.add_development_dependency 'appraisal', '~> 2.1.0'
@@ -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.4.0
4
+ version: 3.0.1
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-07-09 00:00:00.000000000 Z
13
+ date: 2020-04-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mail
@@ -18,14 +18,14 @@ 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
@@ -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 => "../"