sendgrid-actionmailer 2.4.2 → 3.0.2

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
  SHA256:
3
- metadata.gz: 94259db52788333029d0c8fc9160c054a0e0bef5fc40b0ff4a2f825c9a337e54
4
- data.tar.gz: eee118a0ebb96bf3c098f6c5ec7a28ec832c2b116b4060d7ef25df18ef36d063
3
+ metadata.gz: 776fb071876f8748d9d6ab2ae7d304b18d60023afb9e6747aa9b2e5c11757dbb
4
+ data.tar.gz: 2ac9f378ca1372c581f10d24d1861a6b6b7fe3cbaddd9c5b6fc53f3d4f441ec8
5
5
  SHA512:
6
- metadata.gz: 1cb7d6f1972707fa631f27512ab36cc219373ca36725b666d05dab7ea128d270f8454cb30d45b0bc4b7d2f0460ca1ae380a2af3410c585d919461b0994d51cf1
7
- data.tar.gz: f2852025eecc5f5087a7e8b41df7cae42f93b4978acf3fb4c8a613f2a3f30eefa83b300affc72234b3f398505bab759a977473ee71a4cc8766c4eb27a3762263
6
+ metadata.gz: fb8c6ed35b214301a578d48b6d241c0a85366ff33767283da5e8d09c33210d960b62477c0de1df8397f144d0e70a95e83ea73c473502a7aa0ed8e949babe1ba7
7
+ data.tar.gz: 3830c481b115beffd21d53a4140d3a1d6de73ff4fe2952cbdafb63b3133b663a464d0075def2934b61112ab5a791d5c31796a86f1d2eeb25deb54ea3af3a1fdb
@@ -9,6 +9,4 @@ 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,54 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.0.2 - 2020-4-20
4
+
5
+ ### Changes
6
+
7
+ - perform_send_request setting for testing perposes
8
+
9
+ ## 3.0.1 - 2020-4-3
10
+
11
+ ### Changes
12
+
13
+ - Validate error response body for empty string
14
+
15
+ ## 3.0.0 - 2020-3-2
16
+
17
+ ### Removed
18
+
19
+ - Compatibility with mail gems before version 2.7
20
+
21
+ ## 2.6.0 - 2020-1-23
22
+
23
+ ### Changes
24
+
25
+ - Dont send content types with dynamic templates (#69)
26
+
27
+ ## 2.5.0 - 2020-1-21
28
+
29
+ ### Changes
30
+
31
+ - Add personalizations field (#60)
32
+
33
+ ### Fixes
34
+
35
+ - Revert "Lazy load ActionMailer::Base" (#64)
36
+ - Yank 2.4.1
37
+
38
+ ## 2.4.2 - 2020-1-21
39
+
40
+ ### Fixes
41
+
42
+ - Revert "Lazy load ActionMailer::Base" (#64)
43
+ - Yank 2.4.1
44
+
45
+ ## 2.4.1 - 2020-1-20
46
+
47
+ ### Changed
48
+
49
+ - Update Travis CI settings to test on latest Ruby and mail gem version (#55)
50
+ - Lazy load ActionMailer::Base (#57)
51
+
3
52
  ## 2.4.0 - 2019-07-9
4
53
 
5
54
  ### Changed
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,20 +215,56 @@ 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. Variables are available within templates using [{{handlebar syntax}}](https://sendgrid.com/docs/for-developers/sending-email/using-handlebars).
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.
221
246
 
222
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data:{ variable_1: 'foo', variable_2: 'bar'})```
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
+ ```
223
255
 
224
256
  ### Unsubscribe Links
225
257
 
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.
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.
227
259
 
228
260
  * `<a href="%asm_group_unsubscribe_raw_url%">Unsubscribe</a>`
229
261
  * `<a href="%asm_global_unsubscribe_raw_url%">Unsubscribe from List</a>`
230
262
  * `<a href="%asm_preferences_raw_url%">Manage Email Preferences</a>`
231
263
 
232
264
  Note: This feature, and substitutions in general, do not work in combination with dynamic templates.
265
+
266
+ ## Testing
267
+
268
+ The setting `perform_send_request` is available to disable sending for testing purposes. Setting perform_send_request false and return_response true enables the testing of the JSON API payload.
269
+
270
+
@@ -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,18 +25,20 @@ 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
- response = perform_send_request(sendgrid_mail)
37
+ if (settings[:perform_send_request] == false)
38
+ response = sendgrid_mail
39
+ else
40
+ response = perform_send_request(sendgrid_mail)
41
+ end
39
42
 
40
43
  settings[:return_response] ? response : self
41
44
  end
@@ -75,20 +78,51 @@ module SendGridActionMailer
75
78
  end
76
79
  end
77
80
 
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) }
81
+ def setup_personalization(mail, personalization_hash)
82
+ personalization = Personalization.new
83
+
84
+ personalization_hash = self.class.transform_keys(personalization_hash, &:to_s)
85
+
86
+ (personalization_hash['to'] || []).each do |to|
87
+ personalization.add_to Email.new(email: to['email'], name: to['name'])
88
+ end
89
+ (personalization_hash['cc'] || []).each do |cc|
90
+ personalization.add_cc Email.new(email: cc['email'], name: cc['name'])
91
+ end
92
+ (personalization_hash['bcc'] || []).each do |bcc|
93
+ personalization.add_bcc Email.new(email: bcc['email'], name: bcc['name'])
94
+ end
95
+ (personalization_hash['headers'] || []).each do |header_key, header_value|
96
+ personalization.add_header Header.new(key: header_key, value: header_value)
97
+ end
98
+ (personalization_hash['substitutions'] || {}).each do |sub_key, sub_value|
99
+ personalization.add_substitution(Substitution.new(key: sub_key, value: sub_value))
100
+ end
101
+ (personalization_hash['custom_args'] || {}).each do |arg_key, arg_value|
102
+ personalization.add_custom_arg(CustomArg.new(key: arg_key, value: arg_value))
103
+ end
104
+ if personalization_hash['send_at']
105
+ personalization.send_at = personalization_hash['send_at']
106
+ end
107
+ if personalization_hash['subject']
108
+ personalization.subject = personalization_hash['subject']
109
+ end
83
110
 
111
+ if mail['dynamic_template_data'] || personalization_hash['dynamic_template_data']
84
112
  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%>"))
113
+ data = mail['dynamic_template_data'].unparsed_value
114
+ data.merge!(personalization_hash['dynamic_template_data'] || {})
115
+ else
116
+ data = personalization_hash['dynamic_template_data']
90
117
  end
118
+ personalization.add_dynamic_template_data(data)
119
+ elsif mail['template_id'].nil?
120
+ personalization.add_substitution(Substitution.new(key: "%asm_group_unsubscribe_raw_url%", value: "<%asm_group_unsubscribe_raw_url%>"))
121
+ personalization.add_substitution(Substitution.new(key: "%asm_global_unsubscribe_raw_url%", value: "<%asm_global_unsubscribe_raw_url%>"))
122
+ personalization.add_substitution(Substitution.new(key: "%asm_preferences_raw_url%", value: "<%asm_preferences_raw_url%>"))
91
123
  end
124
+
125
+ return personalization
92
126
  end
93
127
 
94
128
  def to_attachment(part)
@@ -115,28 +149,49 @@ module SendGridActionMailer
115
149
  def add_api_key(sendgrid_mail, mail)
116
150
  self.api_key = settings.fetch(:api_key)
117
151
  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']
152
+ self.api_key = mail['delivery-method-options'].unparsed_value['api_key']
153
+ end
154
+ end
155
+
156
+ def add_attachments(sendgrid_mail, mail)
157
+ mail.attachments.each do |part|
158
+ sendgrid_mail.add_attachment(to_attachment(part))
119
159
  end
120
160
  end
121
161
 
122
162
  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))
163
+ if mail['template_id']
164
+ # We are sending a template, so we don't need to add any content outside
165
+ # of attachments
166
+ add_attachments(sendgrid_mail, mail)
167
+ else
168
+ case mail.mime_type
169
+ when 'text/plain'
170
+ sendgrid_mail.add_content(to_content(:plain, mail.body.decoded))
171
+ when 'text/html'
172
+ sendgrid_mail.add_content(to_content(:html, mail.body.decoded))
173
+ when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
174
+ sendgrid_mail.add_content(to_content(:plain, mail.text_part.decoded)) if mail.text_part
175
+ sendgrid_mail.add_content(to_content(:html, mail.html_part.decoded)) if mail.html_part
176
+
177
+ add_attachments(sendgrid_mail, mail)
134
178
  end
135
179
  end
136
180
  end
137
181
 
138
- def json_parse(text, symbolize=true)
139
- JSON.parse(text.empty? ? '{}' : text.gsub(/:*\"*([\%a-zA-Z0-9_-]*)\"*(( *)=>\ *)/) { "\"#{$1}\":" }, symbolize_names: symbolize)
182
+ def add_personalizations(sendgrid_mail, mail)
183
+ if mail['personalizations']
184
+ mail['personalizations'].unparsed_value.each do |p|
185
+ sendgrid_mail.add_personalization(setup_personalization(mail, p))
186
+ end
187
+ end
188
+ if (mail.to && mail.to.any?) || (mail.cc && mail.cc.any?) || (mail.bcc && mail.bcc.any?)
189
+ personalization = setup_personalization(mail, {})
190
+ to_emails(mail.to).each { |to| personalization.add_to(to) }
191
+ to_emails(mail.cc).each { |cc| personalization.add_cc(cc) }
192
+ to_emails(mail.bcc).each { |bcc| personalization.add_bcc(bcc) }
193
+ sendgrid_mail.add_personalization(personalization)
194
+ end
140
195
  end
141
196
 
142
197
  def add_send_options(sendgrid_mail, mail)
@@ -144,12 +199,12 @@ module SendGridActionMailer
144
199
  sendgrid_mail.template_id = mail['template_id'].to_s
145
200
  end
146
201
  if mail['sections']
147
- json_parse(mail['sections'].value, false).each do |key, value|
202
+ mail['sections'].unparsed_value.each do |key, value|
148
203
  sendgrid_mail.add_section(Section.new(key: key, value: value))
149
204
  end
150
205
  end
151
206
  if mail['headers']
152
- json_parse(mail['headers'].value, false).each do |key, value|
207
+ mail['headers'].unparsed_value.each do |key, value|
153
208
  sendgrid_mail.add_header(Header.new(key: key, value: value))
154
209
  end
155
210
  end
@@ -159,7 +214,7 @@ module SendGridActionMailer
159
214
  end
160
215
  end
161
216
  if mail['custom_args']
162
- json_parse(mail['custom_args'].value, false).each do |key, value|
217
+ mail['custom_args'].unparsed_value.each do |key, value|
163
218
  sendgrid_mail.add_custom_arg(CustomArg.new(key: key, value: value))
164
219
  end
165
220
  end
@@ -170,10 +225,11 @@ module SendGridActionMailer
170
225
  sendgrid_mail.batch_id = mail['batch_id'].to_s
171
226
  end
172
227
  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]
176
- sendgrid_mail.asm = ASM.new(asm)
228
+ asm = mail['asm'].unparsed_value
229
+ asm = asm.delete_if { |key, value|
230
+ !key.to_s.match(/(group_id)|(groups_to_display)/) }
231
+ if asm.keys.map(&:to_s).include?('group_id')
232
+ sendgrid_mail.asm = ASM.new(self.class.transform_keys(asm, &:to_sym))
177
233
  end
178
234
  end
179
235
  if mail['ip_pool_name']
@@ -183,7 +239,7 @@ module SendGridActionMailer
183
239
 
184
240
  def add_mail_settings(sendgrid_mail, mail)
185
241
  if mail['mail_settings']
186
- settings = json_parse(mail['mail_settings'].value)
242
+ settings = mail['mail_settings'].unparsed_value || {}
187
243
  sendgrid_mail.mail_settings = MailSettings.new.tap do |m|
188
244
  if settings[:bcc]
189
245
  m.bcc = BccSettings.new(settings[:bcc])
@@ -206,7 +262,7 @@ module SendGridActionMailer
206
262
 
207
263
  def add_tracking_settings(sendgrid_mail, mail)
208
264
  if mail['tracking_settings']
209
- settings = json_parse(mail['tracking_settings'].value)
265
+ settings = mail['tracking_settings'].unparsed_value
210
266
  sendgrid_mail.tracking_settings = TrackingSettings.new.tap do |t|
211
267
  if settings[:click_tracking]
212
268
  t.click_tracking = ClickTracking.new(settings[:click_tracking])
@@ -228,7 +284,7 @@ module SendGridActionMailer
228
284
  result = client.mail._('send').post(request_body: email.to_json) # ლ(ಠ益ಠლ) that API
229
285
 
230
286
  if result.status_code && result.status_code.start_with?('4')
231
- message = !!(result.body) ? JSON.parse(result.body).fetch('errors').pop.fetch('message') : 'Sendgrid API Error'
287
+ message = !(result.body.empty?) ? JSON.parse(result.body).fetch('errors').pop.fetch('message') : 'Sendgrid API Error'
232
288
  full_message = "Sendgrid delivery failed with #{result.status_code} #{message}"
233
289
 
234
290
  settings[:raise_delivery_errors] ? raise(SendgridDeliveryError, full_message) : warn(full_message)
@@ -236,5 +292,17 @@ module SendGridActionMailer
236
292
 
237
293
  result
238
294
  end
295
+
296
+ # Recursive key transformation based on Rails deep_transform_values
297
+ def self.transform_keys(object, &block)
298
+ case object
299
+ when Hash
300
+ object.map { |key, value| [yield(key), transform_keys(value, &block)] }.to_h
301
+ when Array
302
+ object.map { |e| transform_keys(e, &block) }
303
+ else
304
+ object
305
+ end
306
+ end
239
307
  end
240
308
  end
@@ -1,3 +1,3 @@
1
1
  module SendGridActionMailer
2
- VERSION = '2.4.2'.freeze
2
+ VERSION = '3.0.2'.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
@@ -55,6 +59,11 @@ module SendGridActionMailer
55
59
  m = DeliveryMethod.new(return_response: true)
56
60
  expect(m.settings[:return_response]).to eq(true)
57
61
  end
62
+
63
+ it 'sets perform_deliveries' do
64
+ m = DeliveryMethod.new(perform_send_request: false)
65
+ expect(m.settings[:perform_send_request]).to eq(false)
66
+ end
58
67
  end
59
68
 
60
69
  describe '#deliver!' do
@@ -242,13 +251,51 @@ module SendGridActionMailer
242
251
  ])
243
252
  end
244
253
 
245
- context 'send options' do
246
- it 'sets a template_id' do
254
+ context 'template_id' do
255
+ before do
247
256
  mail['template_id'] = '1'
257
+ end
258
+
259
+ it 'sets a template_id' do
248
260
  mailer.deliver!(mail)
249
261
  expect(client.sent_mail['template_id']).to eq('1')
250
262
  end
251
263
 
264
+ it 'does not set unsubscribe substitutions' do
265
+ mailer.deliver!(mail)
266
+ expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
267
+ end
268
+
269
+ it 'does not set send a content type' do
270
+ mailer.deliver!(mail)
271
+ expect(client.sent_mail['content']).to eq(nil)
272
+ end
273
+
274
+ it 'does not set send a content type even if body is given' do
275
+ # This matches the default behavior of ActionMail. body must be
276
+ # specified and content_type defaults to text/plain.
277
+ mail.body = 'I heard you like pineapple.'
278
+ mail.content_type = 'text/plain'
279
+ mailer.deliver!(mail)
280
+ expect(client.sent_mail['content']).to eq(nil)
281
+ end
282
+ end
283
+
284
+ context 'without dynamic template data or a template id' do
285
+ it 'sets unsubscribe substitutions' do
286
+ mailer.deliver!(mail)
287
+ expect(client.sent_mail['personalizations'].first).to have_key('substitutions')
288
+ substitutions = client.sent_mail['personalizations'].first['substitutions']
289
+ expect(substitutions).to eq({
290
+ '%asm_group_unsubscribe_raw_url%' => '<%asm_group_unsubscribe_raw_url%>',
291
+ '%asm_global_unsubscribe_raw_url%' => '<%asm_global_unsubscribe_raw_url%>',
292
+ '%asm_preferences_raw_url%' => '<%asm_preferences_raw_url%>'
293
+ })
294
+ end
295
+ end
296
+
297
+ context 'send options' do
298
+
252
299
  it 'sets sections' do
253
300
  mail['sections'] = {'%foo%' => 'bar'}
254
301
  mailer.deliver!(mail)
@@ -283,10 +330,10 @@ module SendGridActionMailer
283
330
  end
284
331
 
285
332
  it 'sets asm' do
286
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
333
+ asm = {group_id: 99, groups_to_display: [4,5,6,7,8]}
287
334
  mail['asm'] = asm
288
335
  mailer.deliver!(mail)
289
- expect(client.sent_mail['asm']).to eq(asm)
336
+ expect(client.sent_mail['asm']).to eq(transform_keys(asm, &:to_s))
290
337
  end
291
338
 
292
339
  it 'sets ip_pool_name' do
@@ -295,109 +342,109 @@ module SendGridActionMailer
295
342
  expect(client.sent_mail['ip_pool_name']).to eq('marketing')
296
343
  end
297
344
 
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
345
+ it 'should not change values inside custom args' do
346
+ custom_args = { 'text' => 'line with a => in it' }
347
+ mail['custom_args'] = custom_args
348
+ mailer.deliver!(mail)
349
+ expect(client.sent_mail['custom_args']).to eq('text' => 'line with a => in it')
319
350
  end
320
351
 
321
352
  context 'mail_settings' do
322
353
  it 'sets bcc' do
323
- bcc = { 'bcc' => { 'enable' => true, 'email' => 'test@example.com' }}
354
+ bcc = { bcc: { enable: true, email: 'test@example.com' }}
324
355
  mail['mail_settings'] = bcc
325
356
  mailer.deliver!(mail)
326
- expect(client.sent_mail['mail_settings']).to eq(bcc)
357
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bcc, &:to_s))
327
358
  end
328
359
 
329
360
  it 'sets bypass_list_management' do
330
- bypass = { 'bypass_list_management' => { 'enable' => true }}
361
+ bypass = { bypass_list_management: { enable: true }}
331
362
  mail['mail_settings'] = bypass
332
363
  mailer.deliver!(mail)
333
- expect(client.sent_mail['mail_settings']).to eq(bypass)
364
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bypass, &:to_s))
334
365
  end
335
366
 
336
367
  it 'sets footer' do
337
- footer = {'footer' => { 'enable' => true, 'text' => 'Footer Text', 'html' => '<html><body>Footer Text</body></html>'}}
368
+ footer = {footer: { enable: true, text: 'Footer Text', html: '<html><body>Footer Text</body></html>'}}
338
369
  mail['mail_settings'] = footer
339
370
  mailer.deliver!(mail)
340
- expect(client.sent_mail['mail_settings']).to eq(footer)
371
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(footer, &:to_s))
341
372
  end
342
373
 
343
374
  it 'sets sandbox_mode' do
344
- sandbox = {'sandbox_mode' => { 'enable' => true }}
375
+ sandbox = {sandbox_mode: { enable: true }}
345
376
  mail['mail_settings'] = sandbox
346
377
  mailer.deliver!(mail)
347
- expect(client.sent_mail['mail_settings']).to eq(sandbox)
378
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(sandbox, &:to_s))
348
379
  end
349
380
 
350
381
  it 'sets spam_check' do
351
- spam_check = {'spam_check' => { 'enable' => true, 'threshold' => 1, 'post_to_url' => 'https://spamcatcher.sendgrid.com'}}
382
+ spam_check = {spam_check: { enable: true, threshold: 1, post_to_url: 'https://spamcatcher.sendgrid.com'}}
352
383
  mail['mail_settings'] = spam_check
353
384
  mailer.deliver!(mail)
354
- expect(client.sent_mail['mail_settings']).to eq(spam_check)
385
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(spam_check, &:to_s))
355
386
  end
356
387
  end
357
388
 
358
389
  context 'tracking_settings' do
359
390
  it 'sets click_tracking' do
360
- tracking = { 'click_tracking' => { 'enable' => false, 'enable_text' => false }}
361
- mail['tracking_settings'] = tracking
391
+ tracking = { click_tracking: { enable: false, enable_text: false }}
392
+ mail['tracking_settings'] = tracking.dup
362
393
  mailer.deliver!(mail)
363
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
394
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
364
395
  end
365
396
 
366
397
  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' }}
398
+ tracking = { open_tracking: { enable: true, substitution_tag: 'Optional tag to replace with the open image in the body of the message' }}
368
399
  mail['tracking_settings'] = tracking
369
400
  mailer.deliver!(mail)
370
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
401
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
371
402
  end
372
403
 
373
404
  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' }}
405
+ 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
406
  mail['tracking_settings'] = tracking
376
407
  mailer.deliver!(mail)
377
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
408
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
378
409
  end
379
410
 
380
411
  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' }}
412
+ 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
413
  mail['tracking_settings'] = tracking
383
414
  mailer.deliver!(mail)
384
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
415
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
385
416
  end
386
417
  end
387
418
 
388
419
  context 'dynamic template data' do
420
+ let(:template_data) do
421
+ { variable_1: '1', variable_2: '2' }
422
+ end
423
+
424
+ before { mail['dynamic_template_data'] = template_data }
425
+
389
426
  it 'sets dynamic_template_data' do
390
- template_data = { variable_1: '1', variable_2: '2' }
391
- mail['dynamic_template_data'] = template_data
392
427
  mailer.deliver!(mail)
393
428
  expect(client.sent_mail['personalizations'].first['dynamic_template_data']).to eq(template_data)
394
429
  end
395
- end
396
430
 
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)
431
+ it 'does not set unsubscribe substitutions' do
432
+ mailer.deliver!(mail)
433
+ expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
434
+ end
435
+
436
+ context 'containing what looks like hash syntax' do
437
+ let(:template_data) do
438
+ { hint: 'Just use => instead of :' }
439
+ end
440
+
441
+ it 'does not change values inside dynamic template data' do
442
+ mailer.deliver!(mail)
443
+ expect(
444
+ client.sent_mail['personalizations'].first['dynamic_template_data']
445
+ ).to eq(template_data)
446
+ end
447
+ end
401
448
  end
402
449
 
403
450
  it 'sets dynamic template data and sandbox_mode' do
@@ -509,6 +556,220 @@ module SendGridActionMailer
509
556
  expect(content['content_id'].class).to eq(String)
510
557
  end
511
558
  end
559
+
560
+ context 'with personalizations' do
561
+ let(:personalizations) do
562
+ [
563
+ {
564
+ 'to' => [
565
+ {'email' => 'john1@example.com', 'name' => 'John 1'},
566
+ {'email' => 'john2@example.com', 'name' => 'John 2'},
567
+ ]
568
+ },
569
+ {
570
+ 'to' => [
571
+ {'email' => 'john3@example.com', 'name' => 'John 3'},
572
+ {'email' => 'john4@example.com'}
573
+ ],
574
+ 'cc' => [
575
+ {'email' => 'cc@example.com'}
576
+ ],
577
+ 'bcc' => [
578
+ {'email' => 'bcc@example.com'}
579
+ ],
580
+ 'substitutions' => {
581
+ '%fname%' => 'Bob'
582
+ },
583
+ 'subject' => 'personalized subject',
584
+ 'send_at' => 1443636843,
585
+ 'custom_args' => {
586
+ 'user_id' => '343'
587
+ },
588
+ 'headers' => {
589
+ 'X-Test' => true
590
+ }
591
+ }
592
+ ]
593
+ end
594
+
595
+ before do
596
+ mail.to = nil
597
+ mail.cc = nil
598
+ mail.bcc = nil
599
+ mail['personalizations'] = personalizations
600
+ end
601
+
602
+ it 'sets the provided to address personalizations' do
603
+ mailer.deliver!(mail)
604
+ expect(client.sent_mail['personalizations'].length).to eq(2)
605
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(personalizations[0]['to'])
606
+ expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[1]['to'])
607
+ end
608
+
609
+ it 'sets the provided cc address personalizations' do
610
+ mailer.deliver!(mail)
611
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('cc')
612
+ expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[1]['cc'])
613
+ end
614
+
615
+ it 'sets the provided bcc address personalizations' do
616
+ mailer.deliver!(mail)
617
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('bcc')
618
+ expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[1]['bcc'])
619
+ end
620
+
621
+ it 'sets the provided subject personalizations' do
622
+ mailer.deliver!(mail)
623
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('subject')
624
+ expect(client.sent_mail['personalizations'][1]['subject']).to eq(personalizations[1]['subject'])
625
+ end
626
+
627
+ it 'sets the provided headers personalizations' do
628
+ mailer.deliver!(mail)
629
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('headers')
630
+ expect(client.sent_mail['personalizations'][1]['headers']).to eq(personalizations[1]['headers'])
631
+ end
632
+
633
+ it 'sets the provided custom_arg personalizations' do
634
+ mailer.deliver!(mail)
635
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('custom_args')
636
+ expect(client.sent_mail['personalizations'][1]['custom_args']).to eq(personalizations[1]['custom_args'])
637
+ end
638
+
639
+ it 'sets the provided send_at personalizations' do
640
+ mailer.deliver!(mail)
641
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('send_at')
642
+ expect(client.sent_mail['personalizations'][1]['send_at']).to eq(personalizations[1]['send_at'])
643
+ end
644
+
645
+ it 'sets the provided substitution personalizations' do
646
+ mailer.deliver!(mail)
647
+ expect(client.sent_mail['personalizations'][1]['substitutions']).to include(personalizations[1]['substitutions'])
648
+ end
649
+
650
+ it 'adds to the unsubscribe link substitutions' do
651
+ mailer.deliver!(mail)
652
+ expect(client.sent_mail['personalizations'][0]['substitutions']).to eq({
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
+ expect(client.sent_mail['personalizations'][1]['substitutions']).to include({
658
+ '%asm_group_unsubscribe_raw_url%' => '<%asm_group_unsubscribe_raw_url%>',
659
+ '%asm_global_unsubscribe_raw_url%' => '<%asm_global_unsubscribe_raw_url%>',
660
+ '%asm_preferences_raw_url%' => '<%asm_preferences_raw_url%>'
661
+ })
662
+ end
663
+
664
+ context 'with symbols used as keys' do
665
+ let(:personalizations) do
666
+ [
667
+ {
668
+ to: [
669
+ {email: 'sally1@example.com', name: 'Sally 1'},
670
+ {email: 'sally2@example.com', name: 'Sally 2'},
671
+ ]
672
+ }
673
+ ]
674
+ end
675
+
676
+ it 'still works' do
677
+ mailer.deliver!(mail)
678
+ expect(client.sent_mail['personalizations'].length).to eq(1)
679
+ expected_to = personalizations[0][:to].map { |t| transform_keys(t, &:to_s) }
680
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(expected_to)
681
+ end
682
+ end
683
+
684
+ context 'dynamic template data passed into a personalizaiton' do
685
+ let(:personalization_data) do
686
+ {
687
+ 'variable_1' => '1', 'variable_2' => '2'
688
+ }
689
+ end
690
+
691
+ let(:personalizations_with_dynamic_data) do
692
+ personalizations.tap do |p|
693
+ p[1]['dynamic_template_data'] = personalization_data
694
+ end
695
+ end
696
+
697
+ before do
698
+ mail['personalizations'] = nil
699
+ mail['personalizations'] = personalizations_with_dynamic_data
700
+ end
701
+
702
+ it 'sets the provided dynamic template data personalizations' do
703
+ mailer.deliver!(mail)
704
+ expect(client.sent_mail['personalizations'][0]).to_not have_key('dynamic_template_data')
705
+ expect(client.sent_mail['personalizations'][1]['dynamic_template_data']).to eq(personalization_data)
706
+ end
707
+
708
+ context 'dynamic template data is also set on the mail object' do
709
+ let(:mail_template_data) do
710
+ { 'variable_3' => '1', 'variable_4' => '2' }
711
+ end
712
+
713
+ before { mail['dynamic_template_data'] = mail_template_data.dup }
714
+
715
+ it 'sets dynamic_template_data where not also provided as a personalization' do
716
+ mailer.deliver!(mail)
717
+ expect(client.sent_mail['personalizations'][0]['dynamic_template_data']).to eq(mail_template_data)
718
+ end
719
+
720
+ it 'merges the template data with a personalizations dynamic data' do
721
+ mailer.deliver!(mail)
722
+ expect(client.sent_mail['personalizations'][1]['dynamic_template_data']).to eq(
723
+ mail_template_data.merge(personalization_data)
724
+ )
725
+ end
726
+ end
727
+ end
728
+
729
+ context 'when to is set on mail object' do
730
+ before { mail.to = 'test@sendgrid.com' }
731
+
732
+ it 'adds that to address as a separate personalization' do
733
+ mailer.deliver!(mail)
734
+ expect(client.sent_mail['personalizations'].length).to eq(3)
735
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(personalizations[0]['to'])
736
+ expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[1]['to'])
737
+ expect(client.sent_mail['personalizations'][2]['to']).to eq([{"email"=>"test@sendgrid.com"}])
738
+ end
739
+ end
740
+
741
+ context 'when cc is set on mail object' do
742
+ before { mail.cc = 'test@sendgrid.com' }
743
+
744
+ it 'adds that cc address as a separate personalization' do
745
+ mailer.deliver!(mail)
746
+ expect(client.sent_mail['personalizations'].length).to eq(3)
747
+ expect(client.sent_mail['personalizations'][0]['cc']).to eq(personalizations[0]['cc'])
748
+ expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[1]['cc'])
749
+ expect(client.sent_mail['personalizations'][2]['cc']).to eq([{"email"=>"test@sendgrid.com"}])
750
+ end
751
+ end
752
+
753
+ context 'when bcc is set on mail object' do
754
+ before { mail.bcc = 'test@sendgrid.com' }
755
+
756
+ it 'adds that bcc address as a separate personalization' do
757
+ mailer.deliver!(mail)
758
+ expect(client.sent_mail['personalizations'].length).to eq(3)
759
+ expect(client.sent_mail['personalizations'][0]['bcc']).to eq(personalizations[0]['bcc'])
760
+ expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[1]['bcc'])
761
+ expect(client.sent_mail['personalizations'][2]['bcc']).to eq([{"email"=>"test@sendgrid.com"}])
762
+ end
763
+ end
764
+
765
+ context 'when perform_send_request false' do
766
+ it 'should not send and email and return json body' do
767
+ m = DeliveryMethod.new(perform_send_request: false, return_response: true, api_key: 'key')
768
+ response = m.deliver!(mail)
769
+ expect(response).to respond_to(:to_json)
770
+ end
771
+ end
772
+ end
512
773
  end
513
774
  end
514
775
  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.2
4
+ version: 3.0.2
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: 2020-01-21 00:00:00.000000000 Z
13
+ date: 2020-04-20 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
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "mail", "2.5.5"
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.6"
6
-
7
- gemspec :path => "../"