sendgrid-actionmailer 2.5.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e7c4317fb02b1c622b8142161339d320a1a0b49e10e2f1c8cf98c9c649e432f
4
- data.tar.gz: 33772e1a2200cd9bdd239792b1e4c3339d13e662944afb3782399eeeaad7ac5e
3
+ metadata.gz: 65e252ac43443369106264d0b1b33c111184aede536c0b753798e91cd7c55e22
4
+ data.tar.gz: df787ee4c8c4c40b3a8ceeffb89fae8c162360a84960cb094e04dff096990250
5
5
  SHA512:
6
- metadata.gz: df22bdee0b6fbd56a2827d56b4115ec1cc62454e0ca8dc8b32bdd165699df16895a328c1b679868eee145424535b8b0f2ed0447e8e6f70e4154b6c962ed643c9
7
- data.tar.gz: 5ceb138422116c59a4dd3d76a0197a1fe4f80dbbcdaadedf5969e328bda9a4091a5bf15f268c715d0f928ff7e8b912c5ace8556b41cbefb408124a740ce48e45
6
+ metadata.gz: 74792717f19a0ca85d4c450faf2936e318d0d1885ec922a9522b43ac1a1911aa791f5790d6331a56a0c43d7ec190fc1fdfbfdc0033fc52494755c5ea560b0257
7
+ data.tar.gz: 45f55ecee835b2f49cff9fc16fc8845dd499ef9195f7e39737da6e83abb61d537b19293172758a7f682b3f4ba9388639d4052da11aff75841a581d52aec9e9b0
@@ -1,6 +1,7 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
+ - 2.7.1
4
5
  - 2.6.5
5
6
  - 2.5.7
6
7
  - 2.4.9
@@ -9,6 +10,4 @@ before_install:
9
10
  - gem update --system
10
11
  - gem install bundler
11
12
  gemfile:
12
- - gemfiles/mail_2.5.gemfile
13
- - gemfiles/mail_2.6.gemfile
14
13
  - 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,62 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.1.0 - 2020-8-03
4
+
5
+ ### Changes
6
+
7
+ - #81 Fix warnings with ruby 2.7
8
+ - #83 Allow string type mail.to
9
+ - #84 Content-ID values to fix inline attachments
10
+
11
+ ## 3.0.2 - 2020-4-20
12
+
13
+ ### Changes
14
+
15
+ - perform_send_request setting for testing perposes
16
+
17
+ ## 3.0.1 - 2020-4-3
18
+
19
+ ### Changes
20
+
21
+ - Validate error response body for empty string
22
+
23
+ ## 3.0.0 - 2020-3-2
24
+
25
+ ### Removed
26
+
27
+ - Compatibility with mail gems before version 2.7
28
+
29
+ ## 2.6.0 - 2020-1-23
30
+
31
+ ### Changes
32
+
33
+ - Dont send content types with dynamic templates (#69)
34
+
35
+ ## 2.5.0 - 2020-1-21
36
+
37
+ ### Changes
38
+
39
+ - Add personalizations field (#60)
40
+
41
+ ### Fixes
42
+
43
+ - Revert "Lazy load ActionMailer::Base" (#64)
44
+ - Yank 2.4.1
45
+
46
+ ## 2.4.2 - 2020-1-21
47
+
48
+ ### Fixes
49
+
50
+ - Revert "Lazy load ActionMailer::Base" (#64)
51
+ - Yank 2.4.1
52
+
53
+ ## 2.4.1 - 2020-1-20
54
+
55
+ ### Changed
56
+
57
+ - Update Travis CI settings to test on latest Ruby and mail gem version (#55)
58
+ - Lazy load ActionMailer::Base (#57)
59
+
3
60
  ## 2.4.0 - 2019-07-9
4
61
 
5
62
  ### 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,13 +215,13 @@ 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).
221
223
 
222
- ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data:{ variable_1: 'foo', variable_2: 'bar'})```
224
+ ```mail(to: 'example@email.com', subject: 'email subject', body: 'email body', dynamic_template_data: { variable_1: 'foo', variable_2: 'bar' })```
223
225
 
224
226
  ### personalizations (json)
225
227
 
@@ -246,19 +248,23 @@ Example usage:
246
248
 
247
249
  ```
248
250
  mail(subject: 'default subject', 'email body', personalizations: [
249
- { to: { email: 'example@example.com' }},
250
- { to: { email: 'example2@example.com' }}
251
+ { to: [{ email: 'example@example.com' }]},
252
+ { to: [{ email: 'example2@example.com' }]}
251
253
  ])
252
-
253
254
  ```
254
255
 
255
-
256
256
  ### Unsubscribe Links
257
257
 
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.
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.
259
259
 
260
260
  * `<a href="%asm_group_unsubscribe_raw_url%">Unsubscribe</a>`
261
261
  * `<a href="%asm_global_unsubscribe_raw_url%">Unsubscribe from List</a>`
262
262
  * `<a href="%asm_preferences_raw_url%">Manage Email Preferences</a>`
263
263
 
264
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
 
@@ -15,7 +16,7 @@ module SendGridActionMailer
15
16
 
16
17
  attr_accessor :settings, :api_key
17
18
 
18
- def initialize(**params)
19
+ def initialize(params = {})
19
20
  self.settings = DEFAULTS.merge(params)
20
21
  end
21
22
 
@@ -33,7 +34,11 @@ module SendGridActionMailer
33
34
  add_mail_settings(sendgrid_mail, mail)
34
35
  add_tracking_settings(sendgrid_mail, mail)
35
36
 
36
- 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
37
42
 
38
43
  settings[:return_response] ? response : self
39
44
  end
@@ -74,48 +79,50 @@ module SendGridActionMailer
74
79
  end
75
80
 
76
81
  def setup_personalization(mail, personalization_hash)
77
- p = Personalization.new
82
+ personalization = Personalization.new
83
+
84
+ personalization_hash = self.class.transform_keys(personalization_hash, &:to_s)
78
85
 
79
86
  (personalization_hash['to'] || []).each do |to|
80
- p.add_to Email.new(email: to['email'], name: to['name'])
87
+ personalization.add_to Email.new(email: to['email'], name: to['name'])
81
88
  end
82
89
  (personalization_hash['cc'] || []).each do |cc|
83
- p.add_cc Email.new(email: cc['email'], name: cc['name'])
90
+ personalization.add_cc Email.new(email: cc['email'], name: cc['name'])
84
91
  end
85
92
  (personalization_hash['bcc'] || []).each do |bcc|
86
- p.add_bcc Email.new(email: bcc['email'], name: bcc['name'])
93
+ personalization.add_bcc Email.new(email: bcc['email'], name: bcc['name'])
87
94
  end
88
95
  (personalization_hash['headers'] || []).each do |header_key, header_value|
89
- p.add_header Header.new(key: header_key, value: header_value)
96
+ personalization.add_header Header.new(key: header_key, value: header_value)
90
97
  end
91
98
  (personalization_hash['substitutions'] || {}).each do |sub_key, sub_value|
92
- p.add_substitution(Substitution.new(key: sub_key, value: sub_value))
99
+ personalization.add_substitution(Substitution.new(key: sub_key, value: sub_value))
93
100
  end
94
101
  (personalization_hash['custom_args'] || {}).each do |arg_key, arg_value|
95
- p.add_custom_arg(CustomArg.new(key: arg_key, value: arg_value))
102
+ personalization.add_custom_arg(CustomArg.new(key: arg_key, value: arg_value))
96
103
  end
97
104
  if personalization_hash['send_at']
98
- p.send_at = personalization_hash['send_at']
105
+ personalization.send_at = personalization_hash['send_at']
99
106
  end
100
107
  if personalization_hash['subject']
101
- p.subject = personalization_hash['subject']
108
+ personalization.subject = personalization_hash['subject']
102
109
  end
103
110
 
104
111
  if mail['dynamic_template_data'] || personalization_hash['dynamic_template_data']
105
112
  if mail['dynamic_template_data']
106
- data = json_parse(mail['dynamic_template_data'].value, false)
113
+ data = mail['dynamic_template_data'].unparsed_value
107
114
  data.merge!(personalization_hash['dynamic_template_data'] || {})
108
115
  else
109
116
  data = personalization_hash['dynamic_template_data']
110
117
  end
111
- p.add_dynamic_template_data(data)
118
+ personalization.add_dynamic_template_data(data)
112
119
  elsif mail['template_id'].nil?
113
- p.add_substitution(Substitution.new(key: "%asm_group_unsubscribe_raw_url%", value: "<%asm_group_unsubscribe_raw_url%>"))
114
- p.add_substitution(Substitution.new(key: "%asm_global_unsubscribe_raw_url%", value: "<%asm_global_unsubscribe_raw_url%>"))
115
- p.add_substitution(Substitution.new(key: "%asm_preferences_raw_url%", value: "<%asm_preferences_raw_url%>"))
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%>"))
116
123
  end
117
124
 
118
- p
125
+ return personalization
119
126
  end
120
127
 
121
128
  def to_attachment(part)
@@ -128,7 +135,7 @@ module SendGridActionMailer
128
135
  a.disposition = disposition unless disposition.nil?
129
136
 
130
137
  has_content_id = part.header && part.has_content_id?
131
- a.content_id = part.header['content_id'].value if has_content_id
138
+ a.content_id = part.header['content_id'].field.content_id if has_content_id
132
139
  end
133
140
  end
134
141
 
@@ -142,45 +149,49 @@ module SendGridActionMailer
142
149
  def add_api_key(sendgrid_mail, mail)
143
150
  self.api_key = settings.fetch(:api_key)
144
151
  if mail['delivery-method-options'] && mail['delivery-method-options'].value.include?('api_key')
145
- 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']
146
153
  end
147
154
  end
148
155
 
149
- def add_content(sendgrid_mail, mail)
150
- case mail.mime_type
151
- when 'text/plain'
152
- sendgrid_mail.add_content(to_content(:plain, mail.body.decoded))
153
- when 'text/html'
154
- sendgrid_mail.add_content(to_content(:html, mail.body.decoded))
155
- when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
156
- sendgrid_mail.add_content(to_content(:plain, mail.text_part.decoded)) if mail.text_part
157
- sendgrid_mail.add_content(to_content(:html, mail.html_part.decoded)) if mail.html_part
158
-
159
- mail.attachments.each do |part|
160
- sendgrid_mail.add_attachment(to_attachment(part))
161
- end
156
+ def add_attachments(sendgrid_mail, mail)
157
+ mail.attachments.each do |part|
158
+ sendgrid_mail.add_attachment(to_attachment(part))
162
159
  end
163
160
  end
164
161
 
165
- def json_parse(text, symbolize=true)
166
- JSON.parse(text.empty? ? '{}' : text.gsub(/:*\"*([\%a-zA-Z0-9_-]*)\"*(( *)=>\ *)/) { "\"#{$1}\":" }, symbolize_names: symbolize)
162
+ def add_content(sendgrid_mail, mail)
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)
178
+ end
179
+ end
167
180
  end
168
181
 
169
182
  def add_personalizations(sendgrid_mail, mail)
170
- if (mail.to && mail.to.any?) || (mail.cc && mail.cc.any?) || (mail.bcc && mail.bcc.any?)
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.empty?) || (mail.cc && !mail.cc.empty?) || (mail.bcc && !mail.bcc.empty?)
171
189
  personalization = setup_personalization(mail, {})
172
190
  to_emails(mail.to).each { |to| personalization.add_to(to) }
173
191
  to_emails(mail.cc).each { |cc| personalization.add_cc(cc) }
174
192
  to_emails(mail.bcc).each { |bcc| personalization.add_bcc(bcc) }
175
193
  sendgrid_mail.add_personalization(personalization)
176
194
  end
177
-
178
- if mail['personalizations']
179
- personalizations = json_parse('[' + mail['personalizations'].value + ']', false)
180
- personalizations.each do |p|
181
- sendgrid_mail.add_personalization(setup_personalization(mail, p))
182
- end
183
- end
184
195
  end
185
196
 
186
197
  def add_send_options(sendgrid_mail, mail)
@@ -188,12 +199,12 @@ module SendGridActionMailer
188
199
  sendgrid_mail.template_id = mail['template_id'].to_s
189
200
  end
190
201
  if mail['sections']
191
- json_parse(mail['sections'].value, false).each do |key, value|
202
+ mail['sections'].unparsed_value.each do |key, value|
192
203
  sendgrid_mail.add_section(Section.new(key: key, value: value))
193
204
  end
194
205
  end
195
206
  if mail['headers']
196
- json_parse(mail['headers'].value, false).each do |key, value|
207
+ mail['headers'].unparsed_value.each do |key, value|
197
208
  sendgrid_mail.add_header(Header.new(key: key, value: value))
198
209
  end
199
210
  end
@@ -203,7 +214,7 @@ module SendGridActionMailer
203
214
  end
204
215
  end
205
216
  if mail['custom_args']
206
- json_parse(mail['custom_args'].value, false).each do |key, value|
217
+ mail['custom_args'].unparsed_value.each do |key, value|
207
218
  sendgrid_mail.add_custom_arg(CustomArg.new(key: key, value: value))
208
219
  end
209
220
  end
@@ -214,10 +225,11 @@ module SendGridActionMailer
214
225
  sendgrid_mail.batch_id = mail['batch_id'].to_s
215
226
  end
216
227
  if mail['asm']
217
- asm = json_parse(mail['asm'].value)
218
- asm = asm.delete_if { |key, value| !key.to_s.match(/(group_id)|(groups_to_display)/) }
219
- if asm[:group_id]
220
- 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))
221
233
  end
222
234
  end
223
235
  if mail['ip_pool_name']
@@ -227,22 +239,22 @@ module SendGridActionMailer
227
239
 
228
240
  def add_mail_settings(sendgrid_mail, mail)
229
241
  if mail['mail_settings']
230
- settings = json_parse(mail['mail_settings'].value)
242
+ settings = mail['mail_settings'].unparsed_value || {}
231
243
  sendgrid_mail.mail_settings = MailSettings.new.tap do |m|
232
244
  if settings[:bcc]
233
- m.bcc = BccSettings.new(settings[:bcc])
245
+ m.bcc = BccSettings.new(**settings[:bcc])
234
246
  end
235
247
  if settings[:bypass_list_management]
236
- m.bypass_list_management = BypassListManagement.new(settings[:bypass_list_management])
248
+ m.bypass_list_management = BypassListManagement.new(**settings[:bypass_list_management])
237
249
  end
238
250
  if settings[:footer]
239
- m.footer = Footer.new(settings[:footer])
251
+ m.footer = Footer.new(**settings[:footer])
240
252
  end
241
253
  if settings[:sandbox_mode]
242
- m.sandbox_mode = SandBoxMode.new(settings[:sandbox_mode])
254
+ m.sandbox_mode = SandBoxMode.new(**settings[:sandbox_mode])
243
255
  end
244
256
  if settings[:spam_check]
245
- m.spam_check = SpamCheck.new(settings[:spam_check])
257
+ m.spam_check = SpamCheck.new(**settings[:spam_check])
246
258
  end
247
259
  end
248
260
  end
@@ -250,19 +262,19 @@ module SendGridActionMailer
250
262
 
251
263
  def add_tracking_settings(sendgrid_mail, mail)
252
264
  if mail['tracking_settings']
253
- settings = json_parse(mail['tracking_settings'].value)
265
+ settings = mail['tracking_settings'].unparsed_value
254
266
  sendgrid_mail.tracking_settings = TrackingSettings.new.tap do |t|
255
267
  if settings[:click_tracking]
256
- t.click_tracking = ClickTracking.new(settings[:click_tracking])
268
+ t.click_tracking = ClickTracking.new(**settings[:click_tracking])
257
269
  end
258
270
  if settings[:open_tracking]
259
- t.open_tracking = OpenTracking.new(settings[:open_tracking])
271
+ t.open_tracking = OpenTracking.new(**settings[:open_tracking])
260
272
  end
261
273
  if settings[:subscription_tracking]
262
- t.subscription_tracking = SubscriptionTracking.new(settings[:subscription_tracking])
274
+ t.subscription_tracking = SubscriptionTracking.new(**settings[:subscription_tracking])
263
275
  end
264
276
  if settings[:ganalytics]
265
- t.ganalytics = Ganalytics.new(settings[:ganalytics])
277
+ t.ganalytics = Ganalytics.new(**settings[:ganalytics])
266
278
  end
267
279
  end
268
280
  end
@@ -272,7 +284,7 @@ module SendGridActionMailer
272
284
  result = client.mail._('send').post(request_body: email.to_json) # ლ(ಠ益ಠლ) that API
273
285
 
274
286
  if result.status_code && result.status_code.start_with?('4')
275
- 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'
276
288
  full_message = "Sendgrid delivery failed with #{result.status_code} #{message}"
277
289
 
278
290
  settings[:raise_delivery_errors] ? raise(SendgridDeliveryError, full_message) : warn(full_message)
@@ -280,5 +292,17 @@ module SendGridActionMailer
280
292
 
281
293
  result
282
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
283
307
  end
284
308
  end
@@ -1,3 +1,3 @@
1
1
  module SendGridActionMailer
2
- VERSION = '2.5.0'.freeze
2
+ VERSION = '3.1.0'.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,12 +3,8 @@ require 'webmock/rspec'
3
3
 
4
4
  module SendGridActionMailer
5
5
  describe DeliveryMethod do
6
- def stringify_keys(hash)
7
- result = {}
8
- hash.each_key do |key|
9
- result[key.to_s] = hash[key]
10
- end
11
- result
6
+ def transform_keys(object, &block)
7
+ SendGridActionMailer::DeliveryMethod.transform_keys(object, &block)
12
8
  end
13
9
 
14
10
  subject(:mailer) do
@@ -63,6 +59,11 @@ module SendGridActionMailer
63
59
  m = DeliveryMethod.new(return_response: true)
64
60
  expect(m.settings[:return_response]).to eq(true)
65
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
66
67
  end
67
68
 
68
69
  describe '#deliver!' do
@@ -264,6 +265,20 @@ module SendGridActionMailer
264
265
  mailer.deliver!(mail)
265
266
  expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
266
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
267
282
  end
268
283
 
269
284
  context 'without dynamic template data or a template id' do
@@ -315,10 +330,10 @@ module SendGridActionMailer
315
330
  end
316
331
 
317
332
  it 'sets asm' do
318
- 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]}
319
334
  mail['asm'] = asm
320
335
  mailer.deliver!(mail)
321
- expect(client.sent_mail['asm']).to eq(asm)
336
+ expect(client.sent_mail['asm']).to eq(transform_keys(asm, &:to_s))
322
337
  end
323
338
 
324
339
  it 'sets ip_pool_name' do
@@ -327,93 +342,77 @@ module SendGridActionMailer
327
342
  expect(client.sent_mail['ip_pool_name']).to eq('marketing')
328
343
  end
329
344
 
330
- context 'parse object' do
331
- it "should parse 1.8 hash" do
332
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
333
- mail['asm'] = asm
334
- mailer.deliver!(mail)
335
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
336
- end
337
-
338
- it "should parse 1.9 hash" do
339
- asm = { group_id: 99, groups_to_display: [4,5,6,7,8]}
340
- mail['asm'] = asm
341
- mailer.deliver!(mail)
342
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
343
- end
344
-
345
- it "should parse json" do
346
- asm = {'group_id' => 99, 'groups_to_display' => [4,5,6,7,8]}
347
- mail['asm'] = asm.to_json
348
- mailer.deliver!(mail)
349
- expect(client.sent_mail['asm']).to eq({"group_id" => 99, "groups_to_display" => [4,5,6,7,8]})
350
- 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')
351
350
  end
352
351
 
353
352
  context 'mail_settings' do
354
353
  it 'sets bcc' do
355
- bcc = { 'bcc' => { 'enable' => true, 'email' => 'test@example.com' }}
354
+ bcc = { bcc: { enable: true, email: 'test@example.com' }}
356
355
  mail['mail_settings'] = bcc
357
356
  mailer.deliver!(mail)
358
- expect(client.sent_mail['mail_settings']).to eq(bcc)
357
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bcc, &:to_s))
359
358
  end
360
359
 
361
360
  it 'sets bypass_list_management' do
362
- bypass = { 'bypass_list_management' => { 'enable' => true }}
361
+ bypass = { bypass_list_management: { enable: true }}
363
362
  mail['mail_settings'] = bypass
364
363
  mailer.deliver!(mail)
365
- expect(client.sent_mail['mail_settings']).to eq(bypass)
364
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(bypass, &:to_s))
366
365
  end
367
366
 
368
367
  it 'sets footer' do
369
- 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>'}}
370
369
  mail['mail_settings'] = footer
371
370
  mailer.deliver!(mail)
372
- expect(client.sent_mail['mail_settings']).to eq(footer)
371
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(footer, &:to_s))
373
372
  end
374
373
 
375
374
  it 'sets sandbox_mode' do
376
- sandbox = {'sandbox_mode' => { 'enable' => true }}
375
+ sandbox = {sandbox_mode: { enable: true }}
377
376
  mail['mail_settings'] = sandbox
378
377
  mailer.deliver!(mail)
379
- expect(client.sent_mail['mail_settings']).to eq(sandbox)
378
+ expect(client.sent_mail['mail_settings']).to eq(transform_keys(sandbox, &:to_s))
380
379
  end
381
380
 
382
381
  it 'sets spam_check' do
383
- 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'}}
384
383
  mail['mail_settings'] = spam_check
385
384
  mailer.deliver!(mail)
386
- 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))
387
386
  end
388
387
  end
389
388
 
390
389
  context 'tracking_settings' do
391
390
  it 'sets click_tracking' do
392
- tracking = { 'click_tracking' => { 'enable' => false, 'enable_text' => false }}
393
- mail['tracking_settings'] = tracking
391
+ tracking = { click_tracking: { enable: false, enable_text: false }}
392
+ mail['tracking_settings'] = tracking.dup
394
393
  mailer.deliver!(mail)
395
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
394
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
396
395
  end
397
396
 
398
397
  it 'sets open_tracking' do
399
- 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' }}
400
399
  mail['tracking_settings'] = tracking
401
400
  mailer.deliver!(mail)
402
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
401
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
403
402
  end
404
403
 
405
404
  it 'sets subscription_tracking' do
406
- 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' }}
407
406
  mail['tracking_settings'] = tracking
408
407
  mailer.deliver!(mail)
409
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
408
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
410
409
  end
411
410
 
412
411
  it 'sets ganalytics' do
413
- 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' }}
414
413
  mail['tracking_settings'] = tracking
415
414
  mailer.deliver!(mail)
416
- expect(client.sent_mail['tracking_settings']).to eq(tracking)
415
+ expect(client.sent_mail['tracking_settings']).to eq(transform_keys(tracking, &:to_s))
417
416
  end
418
417
  end
419
418
 
@@ -426,19 +425,26 @@ module SendGridActionMailer
426
425
 
427
426
  it 'sets dynamic_template_data' do
428
427
  mailer.deliver!(mail)
429
- expect(client.sent_mail['personalizations'].first['dynamic_template_data']).to eq({'variable_1' => '1', 'variable_2' => '2'})
428
+ expect(client.sent_mail['personalizations'].first['dynamic_template_data']).to eq(template_data)
430
429
  end
431
430
 
432
431
  it 'does not set unsubscribe substitutions' do
433
432
  mailer.deliver!(mail)
434
433
  expect(client.sent_mail['personalizations'].first).to_not have_key('substitutions')
435
434
  end
436
- end
437
435
 
438
- it 'sets dynamic template data and sandbox_mode' do
439
- mail['mail_settings'] = '{}'
440
- mailer.deliver!(mail)
441
- expect(client.sent_mail['mail_settings']).to eq(nil)
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
442
448
  end
443
449
 
444
450
  it 'sets dynamic template data and sandbox_mode' do
@@ -548,6 +554,9 @@ module SendGridActionMailer
548
554
  expect(content['filename']).to eq('specs.rb')
549
555
  expect(content['type']).to eq('application/x-ruby')
550
556
  expect(content['content_id'].class).to eq(String)
557
+ expect(content['content_id']).to include("@")
558
+ expect(content['content_id']).not_to include("<")
559
+ expect(content['content_id']).not_to include(">")
551
560
  end
552
561
  end
553
562
 
@@ -656,20 +665,21 @@ module SendGridActionMailer
656
665
  end
657
666
 
658
667
  context 'with symbols used as keys' do
659
- let(:personalizations) do
660
- [
661
- {
662
- to: [
663
- { email: 'john1@example.com', name: 'John 1'}
664
- ]
665
- }
666
- ]
668
+ let(:personalizations) do
669
+ [
670
+ {
671
+ to: [
672
+ {email: 'sally1@example.com', name: 'Sally 1'},
673
+ {email: 'sally2@example.com', name: 'Sally 2'},
674
+ ]
675
+ }
676
+ ]
667
677
  end
668
678
 
669
679
  it 'still works' do
670
680
  mailer.deliver!(mail)
671
681
  expect(client.sent_mail['personalizations'].length).to eq(1)
672
- expected_to = personalizations[0][:to].map { |t| stringify_keys(t) }
682
+ expected_to = personalizations[0][:to].map { |t| transform_keys(t, &:to_s) }
673
683
  expect(client.sent_mail['personalizations'][0]['to']).to eq(expected_to)
674
684
  end
675
685
  end
@@ -703,7 +713,7 @@ module SendGridActionMailer
703
713
  { 'variable_3' => '1', 'variable_4' => '2' }
704
714
  end
705
715
 
706
- before { mail['dynamic_template_data'] = mail_template_data }
716
+ before { mail['dynamic_template_data'] = mail_template_data.dup }
707
717
 
708
718
  it 'sets dynamic_template_data where not also provided as a personalization' do
709
719
  mailer.deliver!(mail)
@@ -725,9 +735,9 @@ module SendGridActionMailer
725
735
  it 'adds that to address as a separate personalization' do
726
736
  mailer.deliver!(mail)
727
737
  expect(client.sent_mail['personalizations'].length).to eq(3)
728
- expect(client.sent_mail['personalizations'][0]['to']).to eq([{"email"=>"test@sendgrid.com"}])
729
- expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[0]['to'])
730
- expect(client.sent_mail['personalizations'][2]['to']).to eq(personalizations[1]['to'])
738
+ expect(client.sent_mail['personalizations'][0]['to']).to eq(personalizations[0]['to'])
739
+ expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[1]['to'])
740
+ expect(client.sent_mail['personalizations'][2]['to']).to eq([{"email"=>"test@sendgrid.com"}])
731
741
  end
732
742
  end
733
743
 
@@ -737,9 +747,9 @@ module SendGridActionMailer
737
747
  it 'adds that cc address as a separate personalization' do
738
748
  mailer.deliver!(mail)
739
749
  expect(client.sent_mail['personalizations'].length).to eq(3)
740
- expect(client.sent_mail['personalizations'][0]['cc']).to eq([{"email"=>"test@sendgrid.com"}])
741
- expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[0]['cc'])
742
- expect(client.sent_mail['personalizations'][2]['cc']).to eq(personalizations[1]['cc'])
750
+ expect(client.sent_mail['personalizations'][0]['cc']).to eq(personalizations[0]['cc'])
751
+ expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[1]['cc'])
752
+ expect(client.sent_mail['personalizations'][2]['cc']).to eq([{"email"=>"test@sendgrid.com"}])
743
753
  end
744
754
  end
745
755
 
@@ -749,9 +759,17 @@ module SendGridActionMailer
749
759
  it 'adds that bcc address as a separate personalization' do
750
760
  mailer.deliver!(mail)
751
761
  expect(client.sent_mail['personalizations'].length).to eq(3)
752
- expect(client.sent_mail['personalizations'][0]['bcc']).to eq([{"email"=>"test@sendgrid.com"}])
753
- expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[0]['bcc'])
754
- expect(client.sent_mail['personalizations'][2]['bcc']).to eq(personalizations[1]['bcc'])
762
+ expect(client.sent_mail['personalizations'][0]['bcc']).to eq(personalizations[0]['bcc'])
763
+ expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[1]['bcc'])
764
+ expect(client.sent_mail['personalizations'][2]['bcc']).to eq([{"email"=>"test@sendgrid.com"}])
765
+ end
766
+ end
767
+
768
+ context 'when perform_send_request false' do
769
+ it 'should not send and email and return json body' do
770
+ m = DeliveryMethod.new(perform_send_request: false, return_response: true, api_key: 'key')
771
+ response = m.deliver!(mail)
772
+ expect(response).to respond_to(:to_json)
755
773
  end
756
774
  end
757
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.5.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eddie Zaneski
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-01-21 00:00:00.000000000 Z
13
+ date: 2020-08-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
@@ -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 => "../"