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 +4 -4
- data/.travis.yml +1 -2
- data/Appraisals +0 -8
- data/CHANGELOG.md +57 -0
- data/README.md +29 -23
- data/lib/sendgrid_actionmailer.rb +85 -61
- data/lib/sendgrid_actionmailer/version.rb +1 -1
- data/sendgrid-actionmailer.gemspec +1 -1
- data/spec/lib/sendgrid_actionmailer_spec.rb +91 -73
- metadata +4 -6
- data/gemfiles/mail_2.5.gemfile +0 -7
- data/gemfiles/mail_2.6.gemfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65e252ac43443369106264d0b1b33c111184aede536c0b753798e91cd7c55e22
|
4
|
+
data.tar.gz: df787ee4c8c4c40b3a8ceeffb89fae8c162360a84960cb094e04dff096990250
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74792717f19a0ca85d4c450faf2936e318d0d1885ec922a9522b43ac1a1911aa791f5790d6331a56a0c43d7ec190fc1fdfbfdc0033fc52494755c5ea560b0257
|
7
|
+
data.tar.gz: 45f55ecee835b2f49cff9fc16fc8845dd499ef9195f7e39737da6e83abb61d537b19293172758a7f682b3f4ba9388639d4052da11aff75841a581d52aec9e9b0
|
data/.travis.yml
CHANGED
@@ -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
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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',
|
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',
|
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',
|
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',
|
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
|
-
#####
|
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',
|
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',
|
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',
|
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',
|
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).
|
221
223
|
|
222
|
-
```mail(to: 'example@email.com', subject: 'email subject', body: 'email body',
|
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.
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
87
|
+
personalization.add_to Email.new(email: to['email'], name: to['name'])
|
81
88
|
end
|
82
89
|
(personalization_hash['cc'] || []).each do |cc|
|
83
|
-
|
90
|
+
personalization.add_cc Email.new(email: cc['email'], name: cc['name'])
|
84
91
|
end
|
85
92
|
(personalization_hash['bcc'] || []).each do |bcc|
|
86
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
102
|
+
personalization.add_custom_arg(CustomArg.new(key: arg_key, value: arg_value))
|
96
103
|
end
|
97
104
|
if personalization_hash['send_at']
|
98
|
-
|
105
|
+
personalization.send_at = personalization_hash['send_at']
|
99
106
|
end
|
100
107
|
if personalization_hash['subject']
|
101
|
-
|
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 =
|
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
|
-
|
118
|
+
personalization.add_dynamic_template_data(data)
|
112
119
|
elsif mail['template_id'].nil?
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
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'].
|
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 =
|
152
|
+
self.api_key = mail['delivery-method-options'].unparsed_value['api_key']
|
146
153
|
end
|
147
154
|
end
|
148
155
|
|
149
|
-
def
|
150
|
-
|
151
|
-
|
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
|
166
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
218
|
-
asm = asm.delete_if { |key, value|
|
219
|
-
|
220
|
-
|
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 =
|
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 =
|
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 =
|
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
|
@@ -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.
|
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
|
7
|
-
|
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 = {
|
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
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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 = {
|
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(
|
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
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
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|
|
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([
|
729
|
-
expect(client.sent_mail['personalizations'][1]['to']).to eq(personalizations[
|
730
|
-
expect(client.sent_mail['personalizations'][2]['to']).to eq(
|
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([
|
741
|
-
expect(client.sent_mail['personalizations'][1]['cc']).to eq(personalizations[
|
742
|
-
expect(client.sent_mail['personalizations'][2]['cc']).to eq(
|
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([
|
753
|
-
expect(client.sent_mail['personalizations'][1]['bcc']).to eq(personalizations[
|
754
|
-
expect(client.sent_mail['personalizations'][2]['bcc']).to eq(
|
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:
|
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-
|
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.
|
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.
|
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
|
data/gemfiles/mail_2.5.gemfile
DELETED