sendgrid-ruby 5.3.0 → 6.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/pr-lint.yml +15 -0
- data/.github/workflows/test-and-deploy.yml +120 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +127 -0
- data/CHANGELOG.md +261 -8
- data/CODE_OF_CONDUCT.md +57 -25
- data/CONTRIBUTING.md +24 -71
- data/Dockerfile +14 -0
- data/FIRST_TIMERS.md +53 -0
- data/Gemfile +0 -1
- data/LICENSE +21 -0
- data/Makefile +14 -0
- data/PULL_REQUEST_TEMPLATE.md +31 -0
- data/README.md +39 -43
- data/Rakefile +3 -4
- data/TROUBLESHOOTING.md +41 -21
- data/UPGRADE.md +5 -0
- data/USAGE.md +1231 -1122
- data/examples/accesssettings/accesssettings.rb +9 -12
- data/examples/alerts/alerts.rb +8 -11
- data/examples/apikeys/apikeys.rb +12 -15
- data/examples/asm/asm.rb +27 -30
- data/examples/browsers/browsers.rb +0 -3
- data/examples/campaigns/campaigns.rb +29 -32
- data/examples/categories/categories.rb +0 -3
- data/examples/clients/clients.rb +1 -4
- data/examples/contactdb/contactdb.rb +63 -66
- data/examples/dataresidency/setregion.rb +48 -0
- data/examples/devices/devices.rb +0 -3
- data/examples/emailactivity/emailactivity.rb +52 -0
- data/examples/geo/geo.rb +0 -3
- data/examples/helpers/eventwebhook/example.rb +16 -0
- data/examples/helpers/mail/example.rb +30 -19
- data/examples/helpers/settings/example.rb +1 -1
- data/examples/helpers/stats/example.rb +4 -4
- data/examples/ips/ips.rb +31 -21
- data/examples/mail/mail.rb +73 -76
- data/examples/mailboxproviders/mailboxproviders.rb +0 -3
- data/examples/mailsettings/mailsettings.rb +21 -24
- data/examples/partnersettings/partnersettings.rb +3 -6
- data/examples/scopes/scopes.rb +49 -5
- data/examples/{whitelabel/whitelabel.rb → senderauthentication/senderauthentication.rb} +68 -71
- data/examples/senders/senders.rb +28 -31
- data/examples/stats/stats.rb +0 -3
- data/examples/subusers/subusers.rb +17 -20
- data/examples/suppression/suppression.rb +23 -26
- data/examples/templates/templates.rb +29 -31
- data/examples/trackingsettings/trackingsettings.rb +14 -17
- data/examples/user/user.rb +41 -44
- data/lib/rack/sendgrid_webhook_verification.rb +55 -0
- data/lib/sendgrid/base_interface.rb +57 -0
- data/lib/sendgrid/helpers/eventwebhook/eventwebhook.rb +50 -0
- data/lib/sendgrid/helpers/inbound/README.md +26 -9
- data/lib/sendgrid/helpers/inbound/app.rb +15 -3
- data/lib/sendgrid/helpers/inbound/public/index.html +2 -2
- data/lib/sendgrid/helpers/inbound/sample_data/default_data.txt +2 -2
- data/lib/sendgrid/helpers/inbound/sample_data/raw_data.txt +2 -2
- data/lib/sendgrid/helpers/inbound/sample_data/raw_data_with_attachments.txt +2 -2
- data/lib/sendgrid/helpers/inbound/send.rb +5 -5
- data/lib/sendgrid/helpers/ip_management/ip_management.rb +17 -0
- data/lib/sendgrid/helpers/mail/README.md +4 -4
- data/lib/sendgrid/helpers/mail/asm.rb +4 -18
- data/lib/sendgrid/helpers/mail/attachment.rb +30 -38
- data/lib/sendgrid/helpers/mail/bcc_settings.rb +4 -18
- data/lib/sendgrid/helpers/mail/bypass_list_management.rb +6 -18
- data/lib/sendgrid/helpers/mail/category.rb +2 -12
- data/lib/sendgrid/helpers/mail/click_tracking.rb +4 -18
- data/lib/sendgrid/helpers/mail/content.rb +4 -18
- data/lib/sendgrid/helpers/mail/custom_arg.rb +4 -10
- data/lib/sendgrid/helpers/mail/email.rb +10 -20
- data/lib/sendgrid/helpers/mail/footer.rb +5 -27
- data/lib/sendgrid/helpers/mail/ganalytics.rb +9 -55
- data/lib/sendgrid/helpers/mail/header.rb +4 -10
- data/lib/sendgrid/helpers/mail/mail.rb +37 -87
- data/lib/sendgrid/helpers/mail/mail_settings.rb +7 -25
- data/lib/sendgrid/helpers/mail/open_tracking.rb +4 -18
- data/lib/sendgrid/helpers/mail/personalization.rb +38 -27
- data/lib/sendgrid/helpers/mail/section.rb +4 -10
- data/lib/sendgrid/helpers/mail/spam_check.rb +5 -27
- data/lib/sendgrid/helpers/mail/subscription_tracking.rb +6 -36
- data/lib/sendgrid/helpers/mail/substitution.rb +4 -10
- data/lib/sendgrid/helpers/mail/tracking_settings.rb +6 -20
- data/lib/sendgrid/helpers/permissions/scope.rb +28 -0
- data/lib/sendgrid/helpers/permissions/scopes.yml +309 -0
- data/lib/sendgrid/helpers/settings/README.md +3 -3
- data/lib/sendgrid/helpers/settings/settings.rb +1 -1
- data/lib/sendgrid/helpers/settings/tracking_settings_dto.rb +3 -5
- data/lib/sendgrid/helpers/stats/metrics.rb +5 -7
- data/lib/sendgrid/helpers/stats/stats_response.rb +1 -3
- data/lib/sendgrid/sendgrid.rb +21 -0
- data/lib/sendgrid/twilio_email.rb +21 -0
- data/lib/sendgrid/version.rb +1 -1
- data/lib/sendgrid-ruby.rb +7 -1
- data/mail_helper_v3.md +21 -21
- data/sendgrid-ruby.gemspec +12 -12
- data/spec/fixtures/event_webhook.rb +22 -0
- data/spec/rack/sendgrid_webhook_verification_spec.rb +142 -0
- data/spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb +105 -0
- data/spec/sendgrid/helpers/ip_management/ip_management_spec.rb +12 -0
- data/spec/sendgrid/helpers/settings/mail_settings_dto_spec.rb +3 -3
- data/spec/sendgrid/helpers/settings/partner_settings_dto_spec.rb +3 -3
- data/spec/sendgrid/helpers/settings/settings_spec.rb +2 -2
- data/spec/sendgrid/helpers/settings/tracking_settings_dto_spec.rb +3 -3
- data/spec/sendgrid/helpers/settings/user_settings_dto_spec.rb +3 -3
- data/spec/sendgrid/helpers/stats/email_stats_spec.rb +22 -23
- data/spec/sendgrid/helpers/stats/metrics_spec.rb +19 -20
- data/spec/sendgrid/helpers/stats/stats_response_spec.rb +22 -23
- data/spec/sendgrid/sendgrid_spec.rb +11 -0
- data/spec/sendgrid/twilio_email_spec.rb +11 -0
- data/spec/spec_helper.rb +3 -1
- data/static/img/github-fork.png +0 -0
- data/static/img/github-sign-up.png +0 -0
- data/test/sendgrid/helpers/mail/test_attachment.rb +33 -0
- data/test/sendgrid/helpers/mail/test_category.rb +0 -2
- data/test/sendgrid/helpers/mail/test_data_residency.rb +44 -0
- data/test/sendgrid/helpers/mail/test_email.rb +17 -10
- data/test/sendgrid/helpers/mail/test_mail.rb +126 -119
- data/test/sendgrid/helpers/mail/test_personalizations.rb +145 -92
- data/test/sendgrid/permissions/test_scopes.rb +36 -0
- data/test/sendgrid/test_sendgrid-ruby.rb +1961 -1979
- data/twilio_sendgrid_logo.png +0 -0
- data/use-cases/README.md +17 -0
- data/use-cases/domain-authentication.md +5 -0
- data/use-cases/email-statistics.md +52 -0
- data/use-cases/legacy-templates.md +98 -0
- data/use-cases/personalizations.md +34 -0
- data/use-cases/sms.md +39 -0
- data/use-cases/transactional-templates.md +111 -0
- data/use-cases/twilio-email.md +13 -0
- data/use-cases/twilio-setup.md +54 -0
- metadata +99 -45
- data/.codeclimate.yml +0 -21
- data/.github/ISSUE_TEMPLATE +0 -17
- data/.github/PULL_REQUEST_TEMPLATE +0 -24
- data/.travis.yml +0 -29
- data/LICENSE.txt +0 -22
- data/USE_CASES.md +0 -147
- data/docker/Dockerfile +0 -12
- data/docker/README.md +0 -30
- data/lib/sendgrid/client.rb +0 -35
- data/test/prism.sh +0 -42
data/mail_helper_v3.md
CHANGED
@@ -2,18 +2,18 @@ Hello!
|
|
2
2
|
|
3
3
|
It is now time to implement the final piece of our v2 to v3 migration. Before we dig into writing the code, we would love to get feedback on the following proposed interfaces.
|
4
4
|
|
5
|
-
We are starting with the use cases below for the first iteration. (we have completed this work on [our C# library](https://github.com/sendgrid/sendgrid-csharp/blob/
|
5
|
+
We are starting with the use cases below for the first iteration. (we have completed this work on [our C# library](https://github.com/sendgrid/sendgrid-csharp/blob/HEAD/USE_CASES.md), you can check that out for a sneak peek of where we are heading).
|
6
6
|
|
7
7
|
# Send a Single Email to a Single Recipient
|
8
8
|
|
9
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
9
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
10
10
|
|
11
11
|
```ruby
|
12
12
|
require 'sendgrid-ruby'
|
13
13
|
|
14
14
|
from = SendGrid::Email.new('test@example.com', 'Example User')
|
15
15
|
to = SendGrid::Email.new('test@example.com', 'Example User')
|
16
|
-
subject = 'Sending with SendGrid is Fun'
|
16
|
+
subject = 'Sending with Twilio SendGrid is Fun'
|
17
17
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
18
18
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
19
19
|
msg = SendGrid::Mail.create(from: from,
|
@@ -37,7 +37,7 @@ puts response.headers
|
|
37
37
|
|
38
38
|
# Send a Single Email to Multiple Recipients
|
39
39
|
|
40
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
40
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
41
41
|
|
42
42
|
```ruby
|
43
43
|
require 'sendgrid-ruby'
|
@@ -48,7 +48,7 @@ tos = [
|
|
48
48
|
SendGrid::Email.new('test2@example.com', 'Example User2'),
|
49
49
|
SendGrid::Email.new('test3@example.com', 'Example User3')
|
50
50
|
];
|
51
|
-
subject = 'Sending with SendGrid is Fun'
|
51
|
+
subject = 'Sending with Twilio SendGrid is Fun'
|
52
52
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
53
53
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
54
54
|
msg = SendGrid::Mail.create(from: from,
|
@@ -72,7 +72,7 @@ puts response.headers
|
|
72
72
|
|
73
73
|
# Send Multiple Emails to Multiple Recipients
|
74
74
|
|
75
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
75
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
76
76
|
|
77
77
|
```ruby
|
78
78
|
require 'sendgrid-ruby'
|
@@ -84,9 +84,9 @@ tos = [
|
|
84
84
|
SendGrid::Email.new('test3@example.com', 'Example User3')
|
85
85
|
];
|
86
86
|
subjects = [
|
87
|
-
'Sending with SendGrid is Fun',
|
88
|
-
'Sending with SendGrid is Super Fun',
|
89
|
-
'Sending with SendGrid is Super Duper Fun'
|
87
|
+
'Sending with Twilio SendGrid is Fun',
|
88
|
+
'Sending with Twilio SendGrid is Super Fun',
|
89
|
+
'Sending with Twilio SendGrid is Super Duper Fun'
|
90
90
|
];
|
91
91
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
92
92
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
@@ -119,14 +119,14 @@ puts response.headers
|
|
119
119
|
|
120
120
|
# Kitchen Sink - an example with all settings used
|
121
121
|
|
122
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
122
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
123
123
|
|
124
124
|
```ruby
|
125
125
|
client = SendGrid::Client.new(api_key: ENV['SENDGRID_API_KEY'])
|
126
126
|
|
127
127
|
from = SendGrid::Email.new('test@example.com', 'Example User')
|
128
128
|
to = SendGrid::Email.new('test@example.com', 'Example User')
|
129
|
-
subject = 'Sending with SendGrid is Fun'
|
129
|
+
subject = 'Sending with Twilio SendGrid is Fun'
|
130
130
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
131
131
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
132
132
|
msg = SendGrid::Message.new(from, to, subject, plain_text_content, html_content)
|
@@ -233,11 +233,11 @@ msg.set_send_at(1461775052, 1)
|
|
233
233
|
|
234
234
|
msg.set_subject('this subject overrides the Global Subject on the second Personalization', 1)
|
235
235
|
|
236
|
-
# The values below this comment are global to entire message
|
236
|
+
# The values below this comment are global to the entire message
|
237
237
|
|
238
238
|
msg.set_from(SendGrid::Email.new('test0@example.com', 'Example User0'))
|
239
239
|
|
240
|
-
msg.set_global_subject('Sending with SendGrid is Fun');
|
240
|
+
msg.set_global_subject('Sending with Twilio SendGrid is Fun');
|
241
241
|
|
242
242
|
msg.add_content(MimeType::Text, 'and easy to do anywhere, even with Ruby')
|
243
243
|
msg.add_content(MimeType::Html, '<strong>and easy to do anywhere, even with Ruby</strong>')
|
@@ -263,7 +263,7 @@ attachments = [
|
|
263
263
|
'base64 encoded content',
|
264
264
|
'image/png',
|
265
265
|
'inline',
|
266
|
-
'Banner 2'),
|
266
|
+
'Banner 2'),
|
267
267
|
]
|
268
268
|
msg.add_attachments(attachments)
|
269
269
|
|
@@ -279,7 +279,7 @@ msg.set_global_headers(global_headers)
|
|
279
279
|
msg.add_section('%section1%', 'Substitution for Section 1 Tag')
|
280
280
|
sections = [
|
281
281
|
'%section2%' => 'Substitution for Section 2 Tag',
|
282
|
-
'%section3%' => 'Substitution for Section 3 Tag'
|
282
|
+
'%section3%' => 'Substitution for Section 3 Tag'
|
283
283
|
]
|
284
284
|
msg.add_sections(sections)
|
285
285
|
|
@@ -295,14 +295,14 @@ puts response.headers
|
|
295
295
|
|
296
296
|
# Attachments
|
297
297
|
|
298
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
298
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
299
299
|
|
300
300
|
```ruby
|
301
301
|
client = SendGrid::Client.new(api_key: ENV['SENDGRID_API_KEY'])
|
302
302
|
|
303
303
|
from = SendGrid::Email.new('test@example.com', 'Example User')
|
304
304
|
to = SendGrid::Email.new('test@example.com', 'Example User')
|
305
|
-
subject = 'Sending with SendGrid is Fun'
|
305
|
+
subject = 'Sending with Twilio SendGrid is Fun'
|
306
306
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
307
307
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
308
308
|
msg = SendGrid::Message.new(from, to, subject, plain_text_content, html_content)
|
@@ -326,9 +326,9 @@ puts response.headers
|
|
326
326
|
|
327
327
|
# Transactional Templates
|
328
328
|
|
329
|
-
The following code assumes you are storing the API key in an [environment variable (recommended)](
|
329
|
+
The following code assumes you are storing the API key in an [environment variable (recommended)](TROUBLESHOOTING.md#environment-variables-and-your-sendgrid-api-key). If you don't have your key stored in an environment variable, you can assign it directly to `api_key` for testing purposes.
|
330
330
|
|
331
|
-
For this example, we assume you have created a [transactional template](https://sendgrid.com/docs/User_Guide/Transactional_Templates/index.html). Following is the template content we used for testing.
|
331
|
+
For this example, we assume you have created a [legacy transactional template](https://sendgrid.com/docs/User_Guide/Transactional_Templates/index.html) in the UI or via the API. Following is the template content we used for testing.
|
332
332
|
|
333
333
|
Template ID (replace with your own):
|
334
334
|
|
@@ -347,7 +347,7 @@ Template Body:
|
|
347
347
|
```html
|
348
348
|
<html>
|
349
349
|
<head>
|
350
|
-
|
350
|
+
<title></title>
|
351
351
|
</head>
|
352
352
|
<body>
|
353
353
|
Hello -name-,
|
@@ -367,7 +367,7 @@ client = SendGrid::Client.new(api_key: ENV['SENDGRID_API_KEY'])
|
|
367
367
|
|
368
368
|
from = SendGrid::Email.new('test@example.com', 'Example User')
|
369
369
|
to = SendGrid::Email.new('test@example.com', 'Example User')
|
370
|
-
subject = 'Sending with SendGrid is Fun'
|
370
|
+
subject = 'Sending with Twilio SendGrid is Fun'
|
371
371
|
plain_text_content = 'and easy to do anywhere, even with Ruby'
|
372
372
|
html_content = '<strong>and easy to do anywhere, even with Ruby</strong>'
|
373
373
|
msg = SendGrid::Message.new(from, to, subject, plain_text_content, html_content)
|
data/sendgrid-ruby.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'sendgrid/version'
|
5
4
|
|
@@ -7,24 +6,25 @@ Gem::Specification.new do |spec|
|
|
7
6
|
spec.name = 'sendgrid-ruby'
|
8
7
|
spec.version = SendGrid::VERSION
|
9
8
|
spec.authors = ['Elmer Thomas', 'Robin Johnson', 'Eddie Zaneski']
|
10
|
-
spec.email = '
|
11
|
-
spec.summary = 'Official SendGrid Gem'
|
12
|
-
spec.description = 'Official SendGrid Gem to Interact with SendGrids API in native Ruby'
|
9
|
+
spec.email = 'help@twilio.com'
|
10
|
+
spec.summary = 'Official Twilio SendGrid Gem'
|
11
|
+
spec.description = 'Official Twilio SendGrid Gem to Interact with Twilio SendGrids API in native Ruby'
|
13
12
|
spec.homepage = 'http://github.com/sendgrid/sendgrid-ruby'
|
14
13
|
|
15
14
|
spec.required_ruby_version = '>= 2.2'
|
16
15
|
|
17
|
-
spec.license
|
16
|
+
spec.license = 'MIT'
|
18
17
|
spec.files = `git ls-files -z`.split("\x0")
|
19
18
|
spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
|
20
19
|
spec.test_files = spec.files.grep(/^(test|spec|features)/)
|
21
20
|
spec.require_paths = ['lib']
|
22
|
-
spec.add_dependency 'ruby_http_client', '~> 3.
|
23
|
-
spec.add_dependency 'sinatra', '>= 1.4.7', '< 3'
|
24
|
-
spec.add_development_dependency 'rake', '~> 0'
|
25
|
-
spec.add_development_dependency 'rspec'
|
26
|
-
spec.add_development_dependency 'pry'
|
21
|
+
spec.add_dependency 'ruby_http_client', '~> 3.4'
|
27
22
|
spec.add_development_dependency 'faker'
|
28
|
-
spec.add_development_dependency 'rubocop'
|
29
23
|
spec.add_development_dependency 'minitest', '~> 5.9'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
spec.add_development_dependency 'rack'
|
26
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
27
|
+
spec.add_development_dependency 'rspec'
|
28
|
+
spec.add_development_dependency 'simplecov', '~> 0.18.5'
|
29
|
+
spec.add_development_dependency 'sinatra', '>= 1.4.7', '< 3'
|
30
30
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module Fixtures
|
4
|
+
module EventWebhook
|
5
|
+
PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE83T4O/n84iotIvIW4mdBgQ/7dAfSmpqIM8kF9mN1flpVKS3GRqe62gw+2fNNRaINXvVpiglSI8eNEc6wEA3F+g=='.freeze
|
6
|
+
FAILING_PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqTxd43gyp8IOEto2LdIfjRQrIbsd4SXZkLW6jDutdhXSJCWHw8REntlo7aNDthvj+y7GjUuFDb/R1NGe1OPzpA=='.freeze
|
7
|
+
SIGNATURE = 'MEUCIGHQVtGj+Y3LkG9fLcxf3qfI10QysgDWmMOVmxG0u6ZUAiEAyBiXDWzM+uOe5W0JuG+luQAbPIqHh89M15TluLtEZtM='.freeze
|
8
|
+
FAILING_SIGNATURE = 'MEUCIQCtIHJeH93Y+qpYeWrySphQgpNGNr/U+UyUlBkU6n7RAwIgJTz2C+8a8xonZGi6BpSzoQsbVRamr2nlxFDWYNH3j/0='.freeze
|
9
|
+
TIMESTAMP = '1600112502'.freeze
|
10
|
+
PAYLOAD = "#{[
|
11
|
+
{
|
12
|
+
email: 'hello@world.com',
|
13
|
+
event: 'dropped',
|
14
|
+
reason: 'Bounced Address',
|
15
|
+
sg_event_id: 'ZHJvcC0xMDk5NDkxOS1MUnpYbF9OSFN0T0doUTRrb2ZTbV9BLTA',
|
16
|
+
sg_message_id: 'LRzXl_NHStOGhQ4kofSm_A.filterdrecv-p3mdw1-756b745b58-kmzbl-18-5F5FC76C-9.0',
|
17
|
+
'smtp-id': '<LRzXl_NHStOGhQ4kofSm_A@ismtpd0039p1iad1.sendgrid.net>',
|
18
|
+
timestamp: 1_600_112_492
|
19
|
+
}
|
20
|
+
].to_json}\r\n".freeze # Be sure to include the trailing carriage return and newline!
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack/mock'
|
3
|
+
require './spec/fixtures/event_webhook'
|
4
|
+
|
5
|
+
unless RUBY_PLATFORM == 'java'
|
6
|
+
describe Rack::SendGridWebhookVerification do
|
7
|
+
let(:public_key) { Fixtures::EventWebhook::PUBLIC_KEY }
|
8
|
+
before do
|
9
|
+
@app = ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['Hello']] }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'new' do
|
13
|
+
it 'should initialize with an app, public key and a path' do
|
14
|
+
expect do
|
15
|
+
Rack::SendGridWebhookVerification.new(@app, 'ABC', %r{/email})
|
16
|
+
end.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should initialize with an app, public key and paths' do
|
20
|
+
expect do
|
21
|
+
Rack::SendGridWebhookVerification.new(@app, 'ABC', %r{/email}, %r{/event})
|
22
|
+
end.not_to raise_error
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'calling against one path' do
|
27
|
+
let(:middleware) { Rack::SendGridWebhookVerification.new(@app, public_key, %r{/email}) }
|
28
|
+
|
29
|
+
it "should not intercept when the path doesn't match" do
|
30
|
+
expect(SendGrid::EventWebhook).to_not receive(:new)
|
31
|
+
request = Rack::MockRequest.env_for('/login')
|
32
|
+
status, headers, body = middleware.call(request)
|
33
|
+
expect(status).to eq(200)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should allow a request through if it is verified' do
|
37
|
+
options = {
|
38
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
39
|
+
'Content-Type' => "application/json"
|
40
|
+
}
|
41
|
+
options[SendGrid::EventWebhookHeader::SIGNATURE] = Fixtures::EventWebhook::SIGNATURE
|
42
|
+
options[SendGrid::EventWebhookHeader::TIMESTAMP] = Fixtures::EventWebhook::TIMESTAMP
|
43
|
+
request = Rack::MockRequest.env_for('/email', options)
|
44
|
+
status, headers, body = middleware.call(request)
|
45
|
+
expect(status).to eq(200)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should short circuit a request to 403 if there is no signature or timestamp' do
|
49
|
+
options = {
|
50
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
51
|
+
'Content-Type' => "application/json"
|
52
|
+
}
|
53
|
+
request = Rack::MockRequest.env_for('/email', options)
|
54
|
+
status, headers, body = middleware.call(request)
|
55
|
+
expect(status).to eq(403)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should short circuit a request to 403 if the signature is incorrect' do
|
59
|
+
options = {
|
60
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
61
|
+
'Content-Type' => "application/json"
|
62
|
+
}
|
63
|
+
options[SendGrid::EventWebhookHeader::SIGNATURE] = Fixtures::EventWebhook::FAILING_SIGNATURE
|
64
|
+
options[SendGrid::EventWebhookHeader::TIMESTAMP] = Fixtures::EventWebhook::TIMESTAMP
|
65
|
+
request = Rack::MockRequest.env_for('/email', options)
|
66
|
+
status, headers, body = middleware.call(request)
|
67
|
+
expect(status).to eq(403)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should short circuit a request to 403 if the payload is incorrect' do
|
71
|
+
options = {
|
72
|
+
:input => 'payload',
|
73
|
+
'Content-Type' => "application/json"
|
74
|
+
}
|
75
|
+
options[SendGrid::EventWebhookHeader::SIGNATURE] = Fixtures::EventWebhook::SIGNATURE
|
76
|
+
options[SendGrid::EventWebhookHeader::TIMESTAMP] = Fixtures::EventWebhook::TIMESTAMP
|
77
|
+
request = Rack::MockRequest.env_for('/email', options)
|
78
|
+
status, headers, body = middleware.call(request)
|
79
|
+
expect(status).to eq(403)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'calling with multiple paths' do
|
84
|
+
let(:middleware) { Rack::SendGridWebhookVerification.new(@app, public_key, %r{/email}, %r{/events}) }
|
85
|
+
|
86
|
+
it "should not intercept when the path doesn't match" do
|
87
|
+
expect(SendGrid::EventWebhook).to_not receive(:new)
|
88
|
+
request = Rack::MockRequest.env_for('/sms_events')
|
89
|
+
status, headers, body = middleware.call(request)
|
90
|
+
expect(status).to eq(200)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should allow a request through if it is verified' do
|
94
|
+
options = {
|
95
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
96
|
+
'Content-Type' => "application/json"
|
97
|
+
}
|
98
|
+
options[SendGrid::EventWebhookHeader::SIGNATURE] = Fixtures::EventWebhook::SIGNATURE
|
99
|
+
options[SendGrid::EventWebhookHeader::TIMESTAMP] = Fixtures::EventWebhook::TIMESTAMP
|
100
|
+
request = Rack::MockRequest.env_for('/events', options)
|
101
|
+
status, headers, body = middleware.call(request)
|
102
|
+
expect(status).to eq(200)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should short circuit a request to 403 if there is no signature or timestamp' do
|
106
|
+
options = {
|
107
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
108
|
+
'Content-Type' => "application/json"
|
109
|
+
}
|
110
|
+
request = Rack::MockRequest.env_for('/events', options)
|
111
|
+
status, headers, body = middleware.call(request)
|
112
|
+
expect(status).to eq(403)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'request body which passed to an app' do
|
117
|
+
before do
|
118
|
+
@payload = nil
|
119
|
+
@spy_app = lambda do |env|
|
120
|
+
@payload = Rack::Request.new(env).body
|
121
|
+
[200, { 'Content-Type' => 'text/plain' }, ['Hello']]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
let(:middleware) { Rack::SendGridWebhookVerification.new(@spy_app, public_key, %r{/email}) }
|
126
|
+
|
127
|
+
it 'keeps orignal reading position' do
|
128
|
+
options = {
|
129
|
+
:input => Fixtures::EventWebhook::PAYLOAD,
|
130
|
+
'Content-Type' => "application/json"
|
131
|
+
}
|
132
|
+
options[SendGrid::EventWebhookHeader::SIGNATURE] = Fixtures::EventWebhook::SIGNATURE
|
133
|
+
options[SendGrid::EventWebhookHeader::TIMESTAMP] = Fixtures::EventWebhook::TIMESTAMP
|
134
|
+
request = Rack::MockRequest.env_for('/email', options)
|
135
|
+
status, headers, body = middleware.call(request)
|
136
|
+
expect(status).to eq(200)
|
137
|
+
expect(@payload).not_to be_nil
|
138
|
+
expect(@payload.pos).to be_zero
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require './spec/fixtures/event_webhook'
|
3
|
+
|
4
|
+
describe SendGrid::EventWebhook do
|
5
|
+
describe '.verify_signature' do
|
6
|
+
it 'verifies a valid signature' do
|
7
|
+
unless skip_jruby
|
8
|
+
expect(verify(
|
9
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
10
|
+
Fixtures::EventWebhook::PAYLOAD,
|
11
|
+
Fixtures::EventWebhook::SIGNATURE,
|
12
|
+
Fixtures::EventWebhook::TIMESTAMP
|
13
|
+
)).to be true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'rejects a bad key' do
|
18
|
+
unless skip_jruby
|
19
|
+
expect(verify(
|
20
|
+
Fixtures::EventWebhook::FAILING_PUBLIC_KEY,
|
21
|
+
Fixtures::EventWebhook::PAYLOAD,
|
22
|
+
Fixtures::EventWebhook::SIGNATURE,
|
23
|
+
Fixtures::EventWebhook::TIMESTAMP
|
24
|
+
)).to be false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'rejects a bad payload' do
|
29
|
+
unless skip_jruby
|
30
|
+
expect(verify(
|
31
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
32
|
+
'payload',
|
33
|
+
Fixtures::EventWebhook::SIGNATURE,
|
34
|
+
Fixtures::EventWebhook::TIMESTAMP
|
35
|
+
)).to be false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'rejects a bad signature' do
|
40
|
+
unless skip_jruby
|
41
|
+
expect(verify(
|
42
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
43
|
+
Fixtures::EventWebhook::PAYLOAD,
|
44
|
+
Fixtures::EventWebhook::FAILING_SIGNATURE,
|
45
|
+
Fixtures::EventWebhook::TIMESTAMP
|
46
|
+
)).to be false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'rejects a bad timestamp' do
|
51
|
+
unless skip_jruby
|
52
|
+
expect(verify(
|
53
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
54
|
+
Fixtures::EventWebhook::PAYLOAD,
|
55
|
+
Fixtures::EventWebhook::SIGNATURE,
|
56
|
+
'timestamp'
|
57
|
+
)).to be false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'rejects a missing signature' do
|
62
|
+
unless skip_jruby
|
63
|
+
expect(verify(
|
64
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
65
|
+
Fixtures::EventWebhook::PAYLOAD,
|
66
|
+
nil,
|
67
|
+
Fixtures::EventWebhook::TIMESTAMP
|
68
|
+
)).to be false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'throws an error when using jruby' do
|
73
|
+
if skip_jruby
|
74
|
+
expect do
|
75
|
+
verify(
|
76
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
77
|
+
Fixtures::EventWebhook::PAYLOAD,
|
78
|
+
Fixtures::EventWebhook::SIGNATURE,
|
79
|
+
Fixtures::EventWebhook::TIMESTAMP
|
80
|
+
)
|
81
|
+
end.to raise_error(SendGrid::EventWebhook::NotSupportedError)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe SendGrid::EventWebhookHeader do
|
88
|
+
it 'sets the signature header constant' do
|
89
|
+
expect(SendGrid::EventWebhookHeader::SIGNATURE).to eq("HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE")
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'sets the timestamp header constant' do
|
93
|
+
expect(SendGrid::EventWebhookHeader::TIMESTAMP).to eq("HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def verify(public_key, payload, signature, timestamp)
|
98
|
+
ew = SendGrid::EventWebhook.new
|
99
|
+
ec_public_key = ew.convert_public_key_to_ecdsa(public_key)
|
100
|
+
ew.verify_signature(ec_public_key, payload, signature, timestamp)
|
101
|
+
end
|
102
|
+
|
103
|
+
def skip_jruby
|
104
|
+
RUBY_PLATFORM == 'java'
|
105
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SendGrid::IpManagement do
|
4
|
+
let(:sendgrid_client) { SendGrid::API.new(api_key: 'fake_key').client }
|
5
|
+
let(:ip_management) { SendGrid::IpManagement.new(sendgrid_client: sendgrid_client) }
|
6
|
+
|
7
|
+
describe '.new' do
|
8
|
+
it 'initializes correctly' do
|
9
|
+
expect(ip_management).to be_a SendGrid::IpManagement
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -4,7 +4,7 @@ describe SendGrid::MailSettingsDto do
|
|
4
4
|
let(:sendgrid_client) { SendGrid::API.new(api_key: 'fake_key').client }
|
5
5
|
let(:mail_settings) { SendGrid::MailSettingsDto }
|
6
6
|
let(:setting_name) { 'bcc' }
|
7
|
-
let(:setting_params) { {email: Faker::Internet.email, enabled: rand(1..100).even?} }
|
7
|
+
let(:setting_params) { { email: Faker::Internet.email, enabled: rand(1..100).even? } }
|
8
8
|
|
9
9
|
it { should respond_to :bcc }
|
10
10
|
it { should respond_to :address_whitelist }
|
@@ -19,14 +19,14 @@ describe SendGrid::MailSettingsDto do
|
|
19
19
|
describe '.fetch' do
|
20
20
|
it 'calls get on sendgrid_client' do
|
21
21
|
args = { sendgrid_client: sendgrid_client, name: setting_name, query_params: {} }
|
22
|
-
expect(mail_settings.fetch(args)).to be_a SendGrid::Response
|
22
|
+
expect(mail_settings.fetch(**args)).to be_a SendGrid::Response
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
describe '.update' do
|
27
27
|
it 'calls patch on sendgrid_client' do
|
28
28
|
args = { sendgrid_client: sendgrid_client, name: setting_name, request_body: setting_params }
|
29
|
-
expect(mail_settings.update(args)).to be_a SendGrid::Response
|
29
|
+
expect(mail_settings.update(**args)).to be_a SendGrid::Response
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -4,21 +4,21 @@ describe SendGrid::PartnerSettingsDto do
|
|
4
4
|
let(:sendgrid_client) { SendGrid::API.new(api_key: 'fake_key').client }
|
5
5
|
let(:partner_settings) { SendGrid::PartnerSettingsDto }
|
6
6
|
let(:setting_name) { 'new_relic' }
|
7
|
-
let(:setting_params) { {license_key: 'key', enabled: rand(1..100).even?} }
|
7
|
+
let(:setting_params) { { license_key: 'key', enabled: rand(1..100).even? } }
|
8
8
|
|
9
9
|
it { should respond_to :new_relic }
|
10
10
|
|
11
11
|
describe '.fetch' do
|
12
12
|
it 'calls get on sendgrid_client' do
|
13
13
|
args = { sendgrid_client: sendgrid_client, name: setting_name, query_params: {} }
|
14
|
-
expect(partner_settings.fetch(args)).to be_a SendGrid::Response
|
14
|
+
expect(partner_settings.fetch(**args)).to be_a SendGrid::Response
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
describe '.update' do
|
19
19
|
it 'calls patch on sendgrid_client' do
|
20
20
|
args = { sendgrid_client: sendgrid_client, name: setting_name, request_body: setting_params }
|
21
|
-
expect(partner_settings.update(args)).to be_a SendGrid::Response
|
21
|
+
expect(partner_settings.update(**args)).to be_a SendGrid::Response
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -18,8 +18,8 @@ describe SendGrid::Settings do
|
|
18
18
|
|
19
19
|
describe '.update_bcc' do
|
20
20
|
it 'updates bcc' do
|
21
|
-
bcc_response = settings.update_bcc(enabled: true, email:
|
21
|
+
bcc_response = settings.update_bcc(enabled: true, email: 'email@example.com')
|
22
22
|
expect(bcc_response).to be_a SendGrid::Response
|
23
23
|
end
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
@@ -4,7 +4,7 @@ describe SendGrid::TrackingSettingsDto do
|
|
4
4
|
let(:sendgrid_client) { SendGrid::API.new(api_key: 'fake_key').client }
|
5
5
|
let(:tracking_settings) { SendGrid::TrackingSettingsDto }
|
6
6
|
let(:setting_name) { 'open_tracking' }
|
7
|
-
let(:setting_params) { {enabled: rand(1..100).even?} }
|
7
|
+
let(:setting_params) { { enabled: rand(1..100).even? } }
|
8
8
|
|
9
9
|
it { should respond_to :open_tracking }
|
10
10
|
it { should respond_to :click_tracking }
|
@@ -14,14 +14,14 @@ describe SendGrid::TrackingSettingsDto do
|
|
14
14
|
describe '.fetch' do
|
15
15
|
it 'calls get on sendgrid_client' do
|
16
16
|
args = { sendgrid_client: sendgrid_client, name: setting_name, query_params: {} }
|
17
|
-
expect(tracking_settings.fetch(args)).to be_a SendGrid::Response
|
17
|
+
expect(tracking_settings.fetch(**args)).to be_a SendGrid::Response
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '.update' do
|
22
22
|
it 'calls patch on sendgrid_client' do
|
23
23
|
args = { sendgrid_client: sendgrid_client, name: setting_name, request_body: setting_params }
|
24
|
-
expect(tracking_settings.update(args)).to be_a SendGrid::Response
|
24
|
+
expect(tracking_settings.update(**args)).to be_a SendGrid::Response
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -4,21 +4,21 @@ describe SendGrid::UserSettingsDto do
|
|
4
4
|
let(:sendgrid_client) { SendGrid::API.new(api_key: 'fake_key').client }
|
5
5
|
let(:user_settings) { SendGrid::UserSettingsDto }
|
6
6
|
let(:setting_name) { 'enforced_tls' }
|
7
|
-
let(:setting_params) { {require_tls: rand(1..100).even?} }
|
7
|
+
let(:setting_params) { { require_tls: rand(1..100).even? } }
|
8
8
|
|
9
9
|
it { should respond_to :enforced_tls }
|
10
10
|
|
11
11
|
describe '.fetch' do
|
12
12
|
it 'calls get on sendgrid_client' do
|
13
13
|
args = { sendgrid_client: sendgrid_client, name: setting_name, query_params: {} }
|
14
|
-
expect(user_settings.fetch(args)).to be_a SendGrid::Response
|
14
|
+
expect(user_settings.fetch(**args)).to be_a SendGrid::Response
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
describe '.update' do
|
19
19
|
it 'calls patch on sendgrid_client' do
|
20
20
|
args = { sendgrid_client: sendgrid_client, name: setting_name, request_body: setting_params }
|
21
|
-
expect(user_settings.update(args)).to be_a SendGrid::Response
|
21
|
+
expect(user_settings.update(**args)).to be_a SendGrid::Response
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -7,37 +7,36 @@ describe SendGrid::EmailStats do
|
|
7
7
|
|
8
8
|
let(:sample_response) do
|
9
9
|
[{
|
10
|
-
|
11
|
-
|
12
|
-
{
|
10
|
+
'date' => '2017-10-01',
|
11
|
+
'stats' => [
|
12
|
+
{ 'metrics' =>
|
13
13
|
{
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}
|
31
|
-
}
|
14
|
+
'blocks' => 101,
|
15
|
+
'bounce_drops' => 102,
|
16
|
+
'bounces' => 103,
|
17
|
+
'clicks' => 104,
|
18
|
+
'deferred' => 105,
|
19
|
+
'delivered' => 106,
|
20
|
+
'invalid_emails' => 107,
|
21
|
+
'opens' => 108,
|
22
|
+
'processed' => 109,
|
23
|
+
'requests' => 110,
|
24
|
+
'spam_report_drops' => 111,
|
25
|
+
'spam_reports' => 112,
|
26
|
+
'unique_clicks' => 113,
|
27
|
+
'unique_opens' => 114,
|
28
|
+
'unsubscribe_drops' => 115,
|
29
|
+
'unsubscribes' => 116
|
30
|
+
} }
|
32
31
|
]
|
33
32
|
}]
|
34
33
|
end
|
35
34
|
|
36
35
|
let(:error_response) do
|
37
36
|
{
|
38
|
-
|
37
|
+
'errors' => [
|
39
38
|
{
|
40
|
-
|
39
|
+
'message' => 'end_date should be a YYYY-MM-DD formatted date'
|
41
40
|
}
|
42
41
|
]
|
43
42
|
}
|