sendgrid-ruby 6.1.2 → 6.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +20 -20
- data/CHANGELOG.md +41 -0
- data/CONTRIBUTING.md +1 -3
- data/Dockerfile +14 -0
- data/Gemfile +0 -1
- data/Makefile +8 -1
- data/README.md +4 -2
- data/TROUBLESHOOTING.md +2 -0
- data/USE_CASES.md +58 -30
- data/examples/helpers/eventwebhook/example.rb +16 -0
- data/lib/rack/sendgrid_webhook_verification.rb +52 -0
- data/lib/sendgrid-ruby.rb +5 -1
- data/lib/sendgrid/base_interface.rb +36 -0
- data/lib/sendgrid/helpers/eventwebhook/eventwebhook.rb +52 -0
- data/lib/sendgrid/sendgrid.rb +20 -0
- data/lib/sendgrid/twilio_email.rb +21 -0
- data/lib/sendgrid/version.rb +1 -1
- data/sendgrid-ruby.gemspec +3 -2
- data/spec/fixtures/event_webhook.rb +16 -0
- data/spec/rack/sendgrid_webhook_verification_spec.rb +116 -0
- data/spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb +103 -0
- data/spec/sendgrid/sendgrid_spec.rb +11 -0
- data/spec/sendgrid/twilio_email_spec.rb +11 -0
- data/test/sendgrid/test_sendgrid-ruby.rb +3 -29
- metadata +38 -9
- data/lib/sendgrid/client.rb +0 -38
- data/test/prism.sh +0 -42
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 34e9f9d2222a7a622d3a92b44006854f282296230b5e08958bdc0c3983ce1bf0
|
|
4
|
+
data.tar.gz: d2d1daecf34261120b150a4c3d64fb48b90816e18dd3b053478751365e0ae426
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ce14fa4b6341a6dac4c09aa83f999463f1c07849b05e47e5c9a596c009ba39a6ca733193c6f8543adc5aa1c989d6651a48f21223c608bda1a95d61b6e0af42a0
|
|
7
|
+
data.tar.gz: 77b872b63c84354a2f01d4a1b2717e23212f5a59a1ef8b6ae427491aabd43bc165cbbf1657383786187751b6db372ac1358e818c2f4ebe7a29e3cb17fbebce48
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
-
|
|
3
|
-
- ruby
|
|
4
|
-
- 2.
|
|
5
|
-
- 2.
|
|
6
|
-
- 2.
|
|
7
|
-
- 2
|
|
8
|
-
|
|
2
|
+
env:
|
|
3
|
+
- version=ruby:2.7
|
|
4
|
+
- version=ruby:2.6
|
|
5
|
+
- version=ruby:2.5
|
|
6
|
+
- version=ruby:2.4
|
|
7
|
+
- version=jruby:9.2
|
|
8
|
+
|
|
9
9
|
gemfile:
|
|
10
10
|
- gemfiles/Sinatra_1.gemfile
|
|
11
11
|
- gemfiles/Sinatra_2.gemfile
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- export PATH=$PATH:$PWD/prism/bin/
|
|
16
|
-
- "./test/prism.sh"
|
|
17
|
-
install: make install
|
|
18
|
-
script: make test
|
|
19
|
-
matrix:
|
|
20
|
-
allow_failures:
|
|
21
|
-
- rvm: ruby-head
|
|
22
|
-
fast_finish: true
|
|
12
|
+
|
|
13
|
+
script: make test-docker
|
|
14
|
+
|
|
23
15
|
deploy:
|
|
24
16
|
provider: rubygems
|
|
25
17
|
api_key:
|
|
@@ -27,5 +19,13 @@ deploy:
|
|
|
27
19
|
gem: sendgrid-ruby
|
|
28
20
|
on:
|
|
29
21
|
tags: true
|
|
30
|
-
|
|
31
|
-
|
|
22
|
+
condition: $version = ruby:2.4 && $BUNDLE_GEMFILE = *"gemfiles/Sinatra_1.gemfile"
|
|
23
|
+
|
|
24
|
+
notifications:
|
|
25
|
+
slack:
|
|
26
|
+
if: branch = master
|
|
27
|
+
on_pull_requests: false
|
|
28
|
+
on_success: never
|
|
29
|
+
on_failure: change
|
|
30
|
+
rooms:
|
|
31
|
+
- secure: QwoVrGveeA1bo/26fO2A+OQHmUX69NLaC214qd18C1Z8ztYMHkd05/9+k9HFb+PSdPkGLSeYOPWAKJUqJWB7HfGINNGpRGIPFcmfB7vhvvLFnhud/SAdQPRZ+SCeZPdpZcjpVRLYENKv259ucGPBCPFXh1HfJF92R0IrKeW5CII=
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,47 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
|
+
[2020-06-25] Version 6.3.1
|
|
5
|
+
--------------------------
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
[2020-06-24] Version 6.3.0
|
|
9
|
+
--------------------------
|
|
10
|
+
**Library - Feature**
|
|
11
|
+
- [PR #428](https://github.com/sendgrid/sendgrid-ruby/pull/428): adds rack middleware to make request verification easier in rack apps. Thanks to [@philnash](https://github.com/philnash)!
|
|
12
|
+
- [PR #425](https://github.com/sendgrid/sendgrid-ruby/pull/425): verify signature from event webhook. Thanks to [@eshanholtz](https://github.com/eshanholtz)!
|
|
13
|
+
|
|
14
|
+
**Library - Fix**
|
|
15
|
+
- [PR #427](https://github.com/sendgrid/sendgrid-ruby/pull/427): drop the starkbank dependency. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
[2020-05-13] Version 6.2.1
|
|
19
|
+
--------------------------
|
|
20
|
+
**Library - Fix**
|
|
21
|
+
- [PR #421](https://github.com/sendgrid/sendgrid-ruby/pull/421): migrate to common prism setup. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
[2020-04-29] Version 6.2.0
|
|
25
|
+
--------------------------
|
|
26
|
+
**Library - Feature**
|
|
27
|
+
- [PR #417](https://github.com/sendgrid/sendgrid-ruby/pull/417): add support for Twilio Email. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
[2020-04-15] Version 6.1.4
|
|
31
|
+
--------------------------
|
|
32
|
+
**Library - Fix**
|
|
33
|
+
- [PR #416](https://github.com/sendgrid/sendgrid-ruby/pull/416): correct the User-Agent casing. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
[2020-04-01] Version 6.1.3
|
|
37
|
+
--------------------------
|
|
38
|
+
**Library - Docs**
|
|
39
|
+
- [PR #414](https://github.com/sendgrid/sendgrid-ruby/pull/414): support verbiage for login issues. Thanks to [@adamchasetaylor](https://github.com/adamchasetaylor)!
|
|
40
|
+
|
|
41
|
+
**Library - Chore**
|
|
42
|
+
- [PR #413](https://github.com/sendgrid/sendgrid-ruby/pull/413): upgrade rake dev dependency. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
|
|
43
|
+
|
|
44
|
+
|
|
4
45
|
[2020-03-18] Version 6.1.2
|
|
5
46
|
--------------------------
|
|
6
47
|
**Library - Chore**
|
data/CONTRIBUTING.md
CHANGED
|
@@ -47,7 +47,7 @@ Before you decide to create a new issue, please try the following:
|
|
|
47
47
|
|
|
48
48
|
### Please use our Bug Report Template
|
|
49
49
|
|
|
50
|
-
In order to make the process easier, we've included a [sample bug report template](
|
|
50
|
+
In order to make the process easier, we've included a [sample bug report template](ISSUE_TEMPLATE.md).
|
|
51
51
|
|
|
52
52
|
<a name="improvements-to-the-codebase"></a>
|
|
53
53
|
## Improvements to the Codebase
|
|
@@ -206,8 +206,6 @@ Please run your code through:
|
|
|
206
206
|
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
|
|
207
207
|
with a clear title and description against the `master` branch. All tests must be passing before we will review the PR.
|
|
208
208
|
|
|
209
|
-
If you have any additional questions, please feel free to [email](mailto:dx@sendgrid.com) us or create an issue in this repo.
|
|
210
|
-
|
|
211
209
|
<a name="code-reviews"></a>
|
|
212
210
|
## Code Reviews
|
|
213
211
|
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ARG version=ruby:latest
|
|
2
|
+
FROM $version
|
|
3
|
+
|
|
4
|
+
# Needed for jruby
|
|
5
|
+
RUN apt-get update \
|
|
6
|
+
&& apt-get install -y make git
|
|
7
|
+
|
|
8
|
+
COPY prism/prism/nginx/cert.crt /usr/local/share/ca-certificates/cert.crt
|
|
9
|
+
RUN update-ca-certificates
|
|
10
|
+
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
COPY . .
|
|
13
|
+
|
|
14
|
+
RUN make install
|
data/Gemfile
CHANGED
data/Makefile
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
.PHONY: install test
|
|
1
|
+
.PHONY: install test test-integ test-docker
|
|
2
2
|
|
|
3
3
|
install:
|
|
4
4
|
gem install bundler:2.1.2; bundle install
|
|
5
5
|
|
|
6
6
|
test:
|
|
7
7
|
bundle exec rake spec
|
|
8
|
+
|
|
9
|
+
test-integ: test
|
|
10
|
+
|
|
11
|
+
version ?= ruby:latest
|
|
12
|
+
test-docker:
|
|
13
|
+
curl -s https://raw.githubusercontent.com/sendgrid/sendgrid-oai/master/prism/prism.sh -o prism.sh
|
|
14
|
+
version=$(version) bash ./prism.sh
|
data/README.md
CHANGED
|
@@ -217,9 +217,11 @@ Please see our [troubleshooting guide](https://github.com/sendgrid/sendgrid-ruby
|
|
|
217
217
|
<a name="about"></a>
|
|
218
218
|
# About
|
|
219
219
|
|
|
220
|
-
sendgrid-ruby is
|
|
220
|
+
sendgrid-ruby is maintained and funded by Twilio SendGrid, Inc. The names and logos for sendgrid-ruby are trademarks of Twilio SendGrid, Inc.
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
If you need help installing or using the library, please check the [Twilio SendGrid Support Help Center](https://support.sendgrid.com).
|
|
223
|
+
|
|
224
|
+
If you've instead found a bug in the library or would like new features added, go ahead and open issues or pull requests against this repo!
|
|
223
225
|
|
|
224
226
|
<a name="license"></a>
|
|
225
227
|
# License
|
data/TROUBLESHOOTING.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
If you have an issue logging into your Twilio SendGrid account, please read this [document](https://sendgrid.com/docs/ui/account-and-settings/troubleshooting-login/). For any questions regarding login issues, please contact our [support team](https://support.sendgrid.com).
|
|
2
|
+
|
|
1
3
|
If you have a non-library Twilio SendGrid issue, please contact our [support team](https://support.sendgrid.com).
|
|
2
4
|
|
|
3
5
|
If you can't find a solution below, please open an [issue](https://github.com/sendgrid/sendgrid-ruby/issues).
|
data/USE_CASES.md
CHANGED
|
@@ -11,14 +11,8 @@ This documentation provides examples for specific use cases. Please [open an iss
|
|
|
11
11
|
* [Adding Attachments](#adding-attachments)
|
|
12
12
|
* [How to Setup a Domain Authentication](#how-to-setup-a-domain-authentication)
|
|
13
13
|
* [How to View Email Statistics](#how-to-view-email-statistics)
|
|
14
|
-
* [Send
|
|
15
|
-
|
|
16
|
-
* [2. Update Your Environment Variables](#2-update-your-environment-variables)
|
|
17
|
-
* [Mac](#mac)
|
|
18
|
-
* [Windows](#windows)
|
|
19
|
-
* [3. Install the Twilio Helper Library](#3-install-the-twilio-helper-library)
|
|
20
|
-
* [4. Setup Work](#4-setup-work)
|
|
21
|
-
* [5. Send an SMS](#5-send-an-sms)
|
|
14
|
+
* [Send an Email With Twilio Email (Pilot)](#send-an-email-with-twilio-email-pilot)
|
|
15
|
+
* [Send an SMS Message](#send-an-sms-message)
|
|
22
16
|
|
|
23
17
|
<a name="transactional-templates"></a>
|
|
24
18
|
# Transactional Templates
|
|
@@ -299,59 +293,98 @@ end
|
|
|
299
293
|
|
|
300
294
|
```
|
|
301
295
|
|
|
302
|
-
|
|
303
|
-
# Send a SMS Message
|
|
296
|
+
# Send an Email With Twilio Email (Pilot)
|
|
304
297
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
## 1. Obtain a Free Twilio Account
|
|
298
|
+
### 1. Obtain a Free Twilio Account
|
|
308
299
|
|
|
309
300
|
Sign up for a free Twilio account [here](https://www.twilio.com/try-twilio?source=sendgrid-ruby).
|
|
310
301
|
|
|
311
|
-
|
|
302
|
+
### 2. Set Up Your Environment Variables
|
|
303
|
+
|
|
304
|
+
The Twilio API allows for authentication using with either an API key/secret or your Account SID/Auth Token. You can create an API key [here](https://twil.io/get-api-key) or obtain your Account SID and Auth Token [here](https://twil.io/console).
|
|
312
305
|
|
|
313
|
-
|
|
306
|
+
Once you have those, follow the steps below based on your operating system.
|
|
314
307
|
|
|
315
|
-
|
|
308
|
+
#### Linux/Mac
|
|
316
309
|
|
|
317
310
|
```bash
|
|
311
|
+
echo "export TWILIO_API_KEY='YOUR_TWILIO_API_KEY'" > twilio.env
|
|
312
|
+
echo "export TWILIO_API_SECRET='YOUR_TWILIO_API_SECRET'" >> twilio.env
|
|
313
|
+
|
|
314
|
+
# or
|
|
315
|
+
|
|
318
316
|
echo "export TWILIO_ACCOUNT_SID='YOUR_TWILIO_ACCOUNT_SID'" > twilio.env
|
|
319
317
|
echo "export TWILIO_AUTH_TOKEN='YOUR_TWILIO_AUTH_TOKEN'" >> twilio.env
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Then:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
320
323
|
echo "twilio.env" >> .gitignore
|
|
321
324
|
source ./twilio.env
|
|
322
325
|
```
|
|
323
326
|
|
|
324
|
-
|
|
327
|
+
#### Windows
|
|
325
328
|
|
|
326
329
|
Temporarily set the environment variable (accessible only during the current CLI session):
|
|
327
330
|
|
|
328
331
|
```bash
|
|
332
|
+
set TWILIO_API_KEY=YOUR_TWILIO_API_KEY
|
|
333
|
+
set TWILIO_API_SECRET=YOUR_TWILIO_API_SECRET
|
|
334
|
+
|
|
335
|
+
: or
|
|
336
|
+
|
|
329
337
|
set TWILIO_ACCOUNT_SID=YOUR_TWILIO_ACCOUNT_SID
|
|
330
338
|
set TWILIO_AUTH_TOKEN=YOUR_TWILIO_AUTH_TOKEN
|
|
331
339
|
```
|
|
332
340
|
|
|
333
|
-
|
|
341
|
+
Or permanently set the environment variable (accessible in all subsequent CLI sessions):
|
|
334
342
|
|
|
335
343
|
```bash
|
|
344
|
+
setx TWILIO_API_KEY "YOUR_TWILIO_API_KEY"
|
|
345
|
+
setx TWILIO_API_SECRET "YOUR_TWILIO_API_SECRET"
|
|
346
|
+
|
|
347
|
+
: or
|
|
348
|
+
|
|
336
349
|
setx TWILIO_ACCOUNT_SID "YOUR_TWILIO_ACCOUNT_SID"
|
|
337
350
|
setx TWILIO_AUTH_TOKEN "YOUR_TWILIO_AUTH_TOKEN"
|
|
338
351
|
```
|
|
339
352
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
To install using [Bundler][bundler] grab the latest stable version:
|
|
353
|
+
### 3. Initialize the Twilio Email Client
|
|
343
354
|
|
|
344
355
|
```ruby
|
|
345
|
-
|
|
356
|
+
mail_client = TwilioEmail::API(username: ENV['TWILIO_API_KEY'], password: ENV['TWILIO_API_SECRET'])
|
|
357
|
+
|
|
358
|
+
# or
|
|
359
|
+
|
|
360
|
+
mail_client = TwilioEmail::API(username: ENV['TWILIO_ACCOUNT_SID'], password: ENV['TWILIO_AUTH_TOKEN'])
|
|
346
361
|
```
|
|
347
362
|
|
|
348
|
-
|
|
363
|
+
This client has the same interface as the `SendGrid::API` client.
|
|
364
|
+
|
|
365
|
+
# Send an SMS Message
|
|
366
|
+
|
|
367
|
+
First, follow the above steps for creating a Twilio account and setting up environment variables with the proper credentials.
|
|
368
|
+
|
|
369
|
+
Then, install the Twilio Helper Library. Add this line to your application's Gemfile:
|
|
370
|
+
|
|
371
|
+
```bash
|
|
372
|
+
gem 'twilio-ruby'
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
And then execute:
|
|
349
376
|
|
|
350
377
|
```bash
|
|
351
|
-
|
|
378
|
+
bundle
|
|
352
379
|
```
|
|
353
380
|
|
|
354
|
-
|
|
381
|
+
Or install it yourself using:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
gem install twilio-ruby
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Finally, send a message.
|
|
355
388
|
|
|
356
389
|
```ruby
|
|
357
390
|
require 'twilio-ruby'
|
|
@@ -362,11 +395,6 @@ auth_token = ENV['TWILIO_AUTH_TOKEN']
|
|
|
362
395
|
|
|
363
396
|
# set up a client to talk to the Twilio REST API
|
|
364
397
|
@client = Twilio::REST::Client.new account_sid, auth_token
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
## 5. Send an SMS
|
|
368
|
-
|
|
369
|
-
```ruby
|
|
370
398
|
@client.api.account.messages.create(
|
|
371
399
|
from: '+14159341234',
|
|
372
400
|
to: '+16105557069',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'sengrid-ruby'
|
|
2
|
+
include SendGrid
|
|
3
|
+
|
|
4
|
+
def is_valid_signature(request)
|
|
5
|
+
public_key = 'base64-encoded public key'
|
|
6
|
+
|
|
7
|
+
event_webhook = SendGrid::EventWebhook.new
|
|
8
|
+
ec_public_key = event_webhook.convert_public_key_to_ecdsa(public_key)
|
|
9
|
+
|
|
10
|
+
event_webhook.verify_signature(
|
|
11
|
+
ec_public_key,
|
|
12
|
+
request.body.read,
|
|
13
|
+
request.env[SendGrid::EventWebhookHeader::SIGNATURE],
|
|
14
|
+
request.env[SendGrid::EventWebhookHeader::TIMESTAMP]
|
|
15
|
+
)
|
|
16
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rack
|
|
4
|
+
# Middleware that verifies webhooks from SendGrid using the EventWebhook
|
|
5
|
+
# verifier.
|
|
6
|
+
#
|
|
7
|
+
# The middleware takes a public key with which to set up the request
|
|
8
|
+
# validator and any number of paths. When a path matches the incoming request
|
|
9
|
+
# path, the request will be verified using the signature and timestamp of the
|
|
10
|
+
# request.
|
|
11
|
+
#
|
|
12
|
+
# Example:
|
|
13
|
+
#
|
|
14
|
+
# require 'rack'
|
|
15
|
+
# use Rack::SendGridWebhookVerification, ENV['PUBLIC_KEY'], /\/emails/
|
|
16
|
+
#
|
|
17
|
+
# The above appends this middleware to the stack, using a public key saved in
|
|
18
|
+
# the ENV and only against paths that match /\/emails/. If the request
|
|
19
|
+
# validates then it gets passed on to the action as normal. If the request
|
|
20
|
+
# doesn't validate then the middleware responds immediately with a 403 status.
|
|
21
|
+
class SendGridWebhookVerification
|
|
22
|
+
def initialize(app, public_key, *paths)
|
|
23
|
+
@app = app
|
|
24
|
+
@public_key = public_key
|
|
25
|
+
@path_regex = Regexp.union(paths)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def call(env)
|
|
29
|
+
return @app.call(env) unless env['PATH_INFO'].match(@path_regex)
|
|
30
|
+
request = Rack::Request.new(env)
|
|
31
|
+
|
|
32
|
+
event_webhook = SendGrid::EventWebhook.new
|
|
33
|
+
ec_public_key = event_webhook.convert_public_key_to_ecdsa(@public_key)
|
|
34
|
+
verified = event_webhook.verify_signature(
|
|
35
|
+
ec_public_key,
|
|
36
|
+
request.body.read,
|
|
37
|
+
request.env[SendGrid::EventWebhookHeader::SIGNATURE],
|
|
38
|
+
request.env[SendGrid::EventWebhookHeader::TIMESTAMP]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if verified
|
|
42
|
+
return @app.call(env)
|
|
43
|
+
else
|
|
44
|
+
return [
|
|
45
|
+
403,
|
|
46
|
+
{ 'Content-Type' => 'text/plain' },
|
|
47
|
+
['SendGrid Request Verification Failed.']
|
|
48
|
+
]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
data/lib/sendgrid-ruby.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
require_relative 'sendgrid/
|
|
1
|
+
require_relative 'sendgrid/base_interface'
|
|
2
|
+
require_relative 'sendgrid/sendgrid'
|
|
3
|
+
require_relative 'sendgrid/twilio_email'
|
|
2
4
|
require_relative 'sendgrid/version'
|
|
5
|
+
require_relative 'sendgrid/helpers/eventwebhook/eventwebhook'
|
|
3
6
|
require_relative 'sendgrid/helpers/ip_management/ip_management'
|
|
4
7
|
require_relative 'sendgrid/helpers/mail/asm'
|
|
5
8
|
require_relative 'sendgrid/helpers/mail/attachment'
|
|
@@ -27,3 +30,4 @@ require_relative 'sendgrid/helpers/stats/email_stats'
|
|
|
27
30
|
require_relative 'sendgrid/helpers/stats/stats_response'
|
|
28
31
|
require_relative 'sendgrid/helpers/stats/metrics'
|
|
29
32
|
require_relative 'sendgrid/helpers/permissions/scope'
|
|
33
|
+
require_relative 'rack/sendgrid_webhook_verification'
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'ruby_http_client'
|
|
2
|
+
require_relative 'version'
|
|
3
|
+
|
|
4
|
+
# Initialize the HTTP client
|
|
5
|
+
class BaseInterface
|
|
6
|
+
attr_accessor :client
|
|
7
|
+
attr_reader :request_headers, :host, :version, :impersonate_subuser
|
|
8
|
+
# * *Args* :
|
|
9
|
+
# - +auth+ -> authorization header value
|
|
10
|
+
# - +host+ -> the base URL for the API
|
|
11
|
+
# - +request_headers+ -> any headers that you want to be globally applied
|
|
12
|
+
# - +version+ -> the version of the API you wish to access,
|
|
13
|
+
# currently only "v3" is supported
|
|
14
|
+
# - +impersonate_subuser+ -> the subuser to impersonate, will be passed
|
|
15
|
+
# in the "On-Behalf-Of" header
|
|
16
|
+
#
|
|
17
|
+
def initialize(auth:, host:, request_headers: nil, version: nil, impersonate_subuser: nil)
|
|
18
|
+
@auth = auth
|
|
19
|
+
@host = host
|
|
20
|
+
@version = version ? version : 'v3'
|
|
21
|
+
@impersonate_subuser = impersonate_subuser
|
|
22
|
+
@user_agent = "sendgrid/#{SendGrid::VERSION};ruby"
|
|
23
|
+
@request_headers = JSON.parse('
|
|
24
|
+
{
|
|
25
|
+
"Authorization": "' + @auth + '",
|
|
26
|
+
"Accept": "application/json",
|
|
27
|
+
"User-Agent": "' + @user_agent + '"
|
|
28
|
+
}
|
|
29
|
+
')
|
|
30
|
+
@request_headers['On-Behalf-Of'] = @impersonate_subuser if @impersonate_subuser
|
|
31
|
+
|
|
32
|
+
@request_headers = @request_headers.merge(request_headers) if request_headers
|
|
33
|
+
@client = SendGrid::Client.new(host: "#{@host}/#{@version}",
|
|
34
|
+
request_headers: @request_headers)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'digest'
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
module SendGrid
|
|
6
|
+
# This class allows you to use the Event Webhook feature. Read the docs for
|
|
7
|
+
# more details: https://sendgrid.com/docs/for-developers/tracking-events/event
|
|
8
|
+
class EventWebhook
|
|
9
|
+
# * *Args* :
|
|
10
|
+
# - +public_key+ -> verification key under Mail Settings
|
|
11
|
+
#
|
|
12
|
+
def convert_public_key_to_ecdsa(public_key)
|
|
13
|
+
verify_engine
|
|
14
|
+
OpenSSL::PKey::EC.new(Base64.decode64(public_key))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# * *Args* :
|
|
18
|
+
# - +public_key+ -> elliptic curve public key
|
|
19
|
+
# - +payload+ -> event payload in the request body
|
|
20
|
+
# - +signature+ -> signature value obtained from the 'X-Twilio-Email-Event-Webhook-Signature' header
|
|
21
|
+
# - +timestamp+ -> timestamp value obtained from the 'X-Twilio-Email-Event-Webhook-Timestamp' header
|
|
22
|
+
def verify_signature(public_key, payload, signature, timestamp)
|
|
23
|
+
verify_engine
|
|
24
|
+
timestamped_playload = "#{timestamp}#{payload}"
|
|
25
|
+
payload_digest = Digest::SHA256.digest(timestamped_playload)
|
|
26
|
+
decoded_signature = Base64.decode64(signature)
|
|
27
|
+
public_key.dsa_verify_asn1(payload_digest, decoded_signature)
|
|
28
|
+
rescue
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def verify_engine
|
|
33
|
+
# JRuby does not fully support ECDSA: https://github.com/jruby/jruby-openssl/issues/193
|
|
34
|
+
if RUBY_PLATFORM == "java"
|
|
35
|
+
raise NotSupportedError, "Event Webhook verification is not supported by JRuby"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Error < ::RuntimeError
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class NotSupportedError < Error
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# This class lists headers that get posted to the webhook. Read the docs for
|
|
47
|
+
# more details: https://sendgrid.com/docs/for-developers/tracking-events/event
|
|
48
|
+
class EventWebhookHeader
|
|
49
|
+
SIGNATURE = "HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE"
|
|
50
|
+
TIMESTAMP = "HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Quickly and easily access the Twilio SendGrid API.
|
|
2
|
+
module SendGrid
|
|
3
|
+
class API < BaseInterface
|
|
4
|
+
# * *Args* :
|
|
5
|
+
# - +api_key+ -> your Twilio SendGrid API key
|
|
6
|
+
# - +host+ -> the base URL for the API
|
|
7
|
+
# - +request_headers+ -> any headers that you want to be globally applied
|
|
8
|
+
# - +version+ -> the version of the API you wish to access,
|
|
9
|
+
# currently only "v3" is supported
|
|
10
|
+
# - +impersonate_subuser+ -> the subuser to impersonate, will be passed
|
|
11
|
+
# in the "On-Behalf-Of" header
|
|
12
|
+
#
|
|
13
|
+
def initialize(api_key:, host: nil, request_headers: nil, version: nil, impersonate_subuser: nil)
|
|
14
|
+
auth = "Bearer #{api_key}"
|
|
15
|
+
host = 'https://api.sendgrid.com' unless host
|
|
16
|
+
|
|
17
|
+
super(auth: auth, host: host, request_headers: request_headers, version: version, impersonate_subuser: impersonate_subuser)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Quickly and easily access the Twilio Email API.
|
|
2
|
+
module TwilioEmail
|
|
3
|
+
class API < BaseInterface
|
|
4
|
+
# * *Args* :
|
|
5
|
+
# - +username+ -> your Twilio Email API key SID or Account SID
|
|
6
|
+
# - +password+ -> your Twilio Email API key secret or Account Auth Token
|
|
7
|
+
# - +host+ -> the base URL for the API
|
|
8
|
+
# - +request_headers+ -> any headers that you want to be globally applied
|
|
9
|
+
# - +version+ -> the version of the API you wish to access,
|
|
10
|
+
# currently only "v3" is supported
|
|
11
|
+
# - +impersonate_subuser+ -> the subuser to impersonate, will be passed
|
|
12
|
+
# in the "On-Behalf-Of" header
|
|
13
|
+
#
|
|
14
|
+
def initialize(username:, password:, host: nil, request_headers: nil, version: nil, impersonate_subuser: nil)
|
|
15
|
+
auth = "Basic #{Base64.strict_encode64("#{username}:#{password}")}"
|
|
16
|
+
host = 'https://email.twilio.com' unless host
|
|
17
|
+
|
|
18
|
+
super(auth: auth, host: host, request_headers: request_headers, version: version, impersonate_subuser: impersonate_subuser)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/sendgrid/version.rb
CHANGED
data/sendgrid-ruby.gemspec
CHANGED
|
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
|
7
7
|
spec.name = 'sendgrid-ruby'
|
|
8
8
|
spec.version = SendGrid::VERSION
|
|
9
9
|
spec.authors = ['Elmer Thomas', 'Robin Johnson', 'Eddie Zaneski']
|
|
10
|
-
spec.email = '
|
|
10
|
+
spec.email = 'help@twilio.com'
|
|
11
11
|
spec.summary = 'Official Twilio SendGrid Gem'
|
|
12
12
|
spec.description = 'Official Twilio SendGrid Gem to Interact with Twilio SendGrids API in native Ruby'
|
|
13
13
|
spec.homepage = 'http://github.com/sendgrid/sendgrid-ruby'
|
|
@@ -21,10 +21,11 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
spec.require_paths = ['lib']
|
|
22
22
|
spec.add_dependency 'ruby_http_client', '~> 3.4'
|
|
23
23
|
spec.add_development_dependency 'sinatra', '>= 1.4.7', '< 3'
|
|
24
|
-
spec.add_development_dependency 'rake', '~> 0'
|
|
24
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
25
25
|
spec.add_development_dependency 'rspec'
|
|
26
26
|
spec.add_development_dependency 'pry'
|
|
27
27
|
spec.add_development_dependency 'faker'
|
|
28
28
|
spec.add_development_dependency 'rubocop'
|
|
29
29
|
spec.add_development_dependency 'minitest', '~> 5.9'
|
|
30
|
+
spec.add_development_dependency 'rack'
|
|
30
31
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module Fixtures
|
|
4
|
+
module EventWebhook
|
|
5
|
+
PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEDr2LjtURuePQzplybdC+u4CwrqDqBaWjcMMsTbhdbcwHBcepxo7yAQGhHPTnlvFYPAZFceEu/1FwCM/QmGUhA=='
|
|
6
|
+
FAILING_PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqTxd43gyp8IOEto2LdIfjRQrIbsd4SXZkLW6jDutdhXSJCWHw8REntlo7aNDthvj+y7GjUuFDb/R1NGe1OPzpA=='
|
|
7
|
+
SIGNATURE = 'MEUCIQCtIHJeH93Y+qpYeWrySphQgpNGNr/U+UyUlBkU6n7RAwIgJTz2C+8a8xonZGi6BpSzoQsbVRamr2nlxFDWYNH2j/0='
|
|
8
|
+
FAILING_SIGNATURE = 'MEUCIQCtIHJeH93Y+qpYeWrySphQgpNGNr/U+UyUlBkU6n7RAwIgJTz2C+8a8xonZGi6BpSzoQsbVRamr2nlxFDWYNH3j/0='
|
|
9
|
+
TIMESTAMP = '1588788367'
|
|
10
|
+
PAYLOAD = {
|
|
11
|
+
'category'=>'example_payload',
|
|
12
|
+
'event'=>'test_event',
|
|
13
|
+
'message_id'=>'message_id',
|
|
14
|
+
}.to_json
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
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', /\/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', /\/email/, /\/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, /\/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, /\/email/, /\/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
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
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{ verify(
|
|
75
|
+
Fixtures::EventWebhook::PUBLIC_KEY,
|
|
76
|
+
Fixtures::EventWebhook::PAYLOAD,
|
|
77
|
+
Fixtures::EventWebhook::SIGNATURE,
|
|
78
|
+
Fixtures::EventWebhook::TIMESTAMP
|
|
79
|
+
)}.to raise_error(SendGrid::EventWebhook::NotSupportedError)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe SendGrid::EventWebhookHeader do
|
|
86
|
+
it 'sets the signature header constant' do
|
|
87
|
+
expect(SendGrid::EventWebhookHeader::SIGNATURE).to eq("HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'sets the timestamp header constant' do
|
|
91
|
+
expect(SendGrid::EventWebhookHeader::TIMESTAMP).to eq("HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP")
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def verify(public_key, payload, signature, timestamp)
|
|
96
|
+
ew = SendGrid::EventWebhook.new
|
|
97
|
+
ec_public_key = ew.convert_public_key_to_ecdsa(public_key)
|
|
98
|
+
ew.verify_signature(ec_public_key, payload, signature, timestamp)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def skip_jruby
|
|
102
|
+
RUBY_PLATFORM == 'java'
|
|
103
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe SendGrid::API do
|
|
4
|
+
describe '.new' do
|
|
5
|
+
it 'initializes correctly' do
|
|
6
|
+
mail_client = SendGrid::API.new(api_key: 'fake_key')
|
|
7
|
+
expect(mail_client.request_headers['Authorization']).to eq('Bearer fake_key')
|
|
8
|
+
expect(mail_client.host).to eq('https://api.sendgrid.com')
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe TwilioEmail::API do
|
|
4
|
+
describe '.new' do
|
|
5
|
+
it 'initializes correctly' do
|
|
6
|
+
mail_client = TwilioEmail::API.new(username: 'username', password: 'password')
|
|
7
|
+
expect(mail_client.request_headers['Authorization']).to eq('Basic dXNlcm5hbWU6cGFzc3dvcmQ=')
|
|
8
|
+
expect(mail_client.host).to eq('https://email.twilio.com')
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -5,34 +5,8 @@ require 'minitest/unit'
|
|
|
5
5
|
|
|
6
6
|
class TestAPI < MiniTest::Test
|
|
7
7
|
|
|
8
|
-
unless File.exist?('/usr/local/bin/prism') || File.exist?(File.join(Dir.pwd, 'prism/bin/prism'))
|
|
9
|
-
if RUBY_PLATFORM =~ /mswin|mingw/
|
|
10
|
-
puts 'Please download the Windows binary (https://github.com/stoplightio/prism/releases) and place it in your /usr/local/bin directory'
|
|
11
|
-
else
|
|
12
|
-
puts 'Installing Prism'
|
|
13
|
-
IO.popen(['curl', '-s', 'https://raw.githubusercontent.com/stoplightio/prism/master/install.sh']) do |io|
|
|
14
|
-
out = io.read
|
|
15
|
-
unless system(out)
|
|
16
|
-
puts "Error downloading the prism binary, you can try downloading directly here (https://github.com/stoplightio/prism/releases) and place in your /usr/local/bin directory, #{out}"
|
|
17
|
-
exit
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
puts 'Activating Prism (~20 seconds)'
|
|
24
|
-
@@prism_pid = spawn('prism run --mock --list --spec https://raw.githubusercontent.com/sendgrid/sendgrid-oai/master/oai_stoplight.json', [:out, :err] => '/dev/null')
|
|
25
|
-
sleep(15)
|
|
26
|
-
puts 'Prism started'
|
|
27
|
-
|
|
28
8
|
def setup
|
|
29
|
-
|
|
30
|
-
@sg = SendGrid::API.new(api_key: "SENDGRID_API_KEY", host: host)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
Minitest.after_run do
|
|
34
|
-
Process.kill('TERM', @@prism_pid)
|
|
35
|
-
puts 'Prism shut down'
|
|
9
|
+
@sg = SendGrid::API.new(api_key: "SENDGRID_API_KEY")
|
|
36
10
|
end
|
|
37
11
|
|
|
38
12
|
def test_init
|
|
@@ -51,14 +25,14 @@ class TestAPI < MiniTest::Test
|
|
|
51
25
|
"Authorization": "Bearer SENDGRID_API_KEY",
|
|
52
26
|
"Accept": "application/json",
|
|
53
27
|
"X-Test": "test",
|
|
54
|
-
"User-
|
|
28
|
+
"User-Agent": "' + user_agent + '",
|
|
55
29
|
"On-Behalf-Of": "' + subuser + '"
|
|
56
30
|
}
|
|
57
31
|
')
|
|
58
32
|
assert_equal(test_headers, sg.request_headers)
|
|
59
33
|
assert_equal("v3", sg.version)
|
|
60
34
|
assert_equal(subuser, sg.impersonate_subuser)
|
|
61
|
-
assert_equal("6.1
|
|
35
|
+
assert_equal("6.3.1", SendGrid::VERSION)
|
|
62
36
|
assert_instance_of(SendGrid::Client, sg.client)
|
|
63
37
|
end
|
|
64
38
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sendgrid-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.1
|
|
4
|
+
version: 6.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Elmer Thomas
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2020-
|
|
13
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: ruby_http_client
|
|
@@ -52,14 +52,14 @@ dependencies:
|
|
|
52
52
|
requirements:
|
|
53
53
|
- - "~>"
|
|
54
54
|
- !ruby/object:Gem::Version
|
|
55
|
-
version: '0'
|
|
55
|
+
version: '13.0'
|
|
56
56
|
type: :development
|
|
57
57
|
prerelease: false
|
|
58
58
|
version_requirements: !ruby/object:Gem::Requirement
|
|
59
59
|
requirements:
|
|
60
60
|
- - "~>"
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: '0'
|
|
62
|
+
version: '13.0'
|
|
63
63
|
- !ruby/object:Gem::Dependency
|
|
64
64
|
name: rspec
|
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -130,9 +130,23 @@ dependencies:
|
|
|
130
130
|
- - "~>"
|
|
131
131
|
- !ruby/object:Gem::Version
|
|
132
132
|
version: '5.9'
|
|
133
|
+
- !ruby/object:Gem::Dependency
|
|
134
|
+
name: rack
|
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '0'
|
|
140
|
+
type: :development
|
|
141
|
+
prerelease: false
|
|
142
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
133
147
|
description: Official Twilio SendGrid Gem to Interact with Twilio SendGrids API in
|
|
134
148
|
native Ruby
|
|
135
|
-
email:
|
|
149
|
+
email: help@twilio.com
|
|
136
150
|
executables: []
|
|
137
151
|
extensions: []
|
|
138
152
|
extra_rdoc_files: []
|
|
@@ -144,6 +158,7 @@ files:
|
|
|
144
158
|
- CHANGELOG.md
|
|
145
159
|
- CODE_OF_CONDUCT.md
|
|
146
160
|
- CONTRIBUTING.md
|
|
161
|
+
- Dockerfile
|
|
147
162
|
- Gemfile
|
|
148
163
|
- ISSUE_TEMPLATE.md
|
|
149
164
|
- LICENSE.md
|
|
@@ -169,6 +184,7 @@ files:
|
|
|
169
184
|
- examples/contactdb/contactdb.rb
|
|
170
185
|
- examples/devices/devices.rb
|
|
171
186
|
- examples/geo/geo.rb
|
|
187
|
+
- examples/helpers/eventwebhook/example.rb
|
|
172
188
|
- examples/helpers/mail/example.rb
|
|
173
189
|
- examples/helpers/settings/example.rb
|
|
174
190
|
- examples/helpers/stats/example.rb
|
|
@@ -188,8 +204,10 @@ files:
|
|
|
188
204
|
- examples/user/user.rb
|
|
189
205
|
- gemfiles/Sinatra_1.gemfile
|
|
190
206
|
- gemfiles/Sinatra_2.gemfile
|
|
207
|
+
- lib/rack/sendgrid_webhook_verification.rb
|
|
191
208
|
- lib/sendgrid-ruby.rb
|
|
192
|
-
- lib/sendgrid/
|
|
209
|
+
- lib/sendgrid/base_interface.rb
|
|
210
|
+
- lib/sendgrid/helpers/eventwebhook/eventwebhook.rb
|
|
193
211
|
- lib/sendgrid/helpers/inbound/README.md
|
|
194
212
|
- lib/sendgrid/helpers/inbound/app.rb
|
|
195
213
|
- lib/sendgrid/helpers/inbound/config.yml
|
|
@@ -232,9 +250,14 @@ files:
|
|
|
232
250
|
- lib/sendgrid/helpers/stats/email_stats.rb
|
|
233
251
|
- lib/sendgrid/helpers/stats/metrics.rb
|
|
234
252
|
- lib/sendgrid/helpers/stats/stats_response.rb
|
|
253
|
+
- lib/sendgrid/sendgrid.rb
|
|
254
|
+
- lib/sendgrid/twilio_email.rb
|
|
235
255
|
- lib/sendgrid/version.rb
|
|
236
256
|
- mail_helper_v3.md
|
|
237
257
|
- sendgrid-ruby.gemspec
|
|
258
|
+
- spec/fixtures/event_webhook.rb
|
|
259
|
+
- spec/rack/sendgrid_webhook_verification_spec.rb
|
|
260
|
+
- spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb
|
|
238
261
|
- spec/sendgrid/helpers/ip_management/ip_management_spec.rb
|
|
239
262
|
- spec/sendgrid/helpers/settings/mail_settings_dto_spec.rb
|
|
240
263
|
- spec/sendgrid/helpers/settings/partner_settings_dto_spec.rb
|
|
@@ -244,8 +267,9 @@ files:
|
|
|
244
267
|
- spec/sendgrid/helpers/stats/email_stats_spec.rb
|
|
245
268
|
- spec/sendgrid/helpers/stats/metrics_spec.rb
|
|
246
269
|
- spec/sendgrid/helpers/stats/stats_response_spec.rb
|
|
270
|
+
- spec/sendgrid/sendgrid_spec.rb
|
|
271
|
+
- spec/sendgrid/twilio_email_spec.rb
|
|
247
272
|
- spec/spec_helper.rb
|
|
248
|
-
- test/prism.sh
|
|
249
273
|
- test/sendgrid/helpers/mail/test_attachment.rb
|
|
250
274
|
- test/sendgrid/helpers/mail/test_category.rb
|
|
251
275
|
- test/sendgrid/helpers/mail/test_email.rb
|
|
@@ -272,11 +296,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
272
296
|
- !ruby/object:Gem::Version
|
|
273
297
|
version: '0'
|
|
274
298
|
requirements: []
|
|
275
|
-
|
|
299
|
+
rubyforge_project:
|
|
300
|
+
rubygems_version: 2.7.7
|
|
276
301
|
signing_key:
|
|
277
302
|
specification_version: 4
|
|
278
303
|
summary: Official Twilio SendGrid Gem
|
|
279
304
|
test_files:
|
|
305
|
+
- spec/fixtures/event_webhook.rb
|
|
306
|
+
- spec/rack/sendgrid_webhook_verification_spec.rb
|
|
307
|
+
- spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb
|
|
280
308
|
- spec/sendgrid/helpers/ip_management/ip_management_spec.rb
|
|
281
309
|
- spec/sendgrid/helpers/settings/mail_settings_dto_spec.rb
|
|
282
310
|
- spec/sendgrid/helpers/settings/partner_settings_dto_spec.rb
|
|
@@ -286,8 +314,9 @@ test_files:
|
|
|
286
314
|
- spec/sendgrid/helpers/stats/email_stats_spec.rb
|
|
287
315
|
- spec/sendgrid/helpers/stats/metrics_spec.rb
|
|
288
316
|
- spec/sendgrid/helpers/stats/stats_response_spec.rb
|
|
317
|
+
- spec/sendgrid/sendgrid_spec.rb
|
|
318
|
+
- spec/sendgrid/twilio_email_spec.rb
|
|
289
319
|
- spec/spec_helper.rb
|
|
290
|
-
- test/prism.sh
|
|
291
320
|
- test/sendgrid/helpers/mail/test_attachment.rb
|
|
292
321
|
- test/sendgrid/helpers/mail/test_category.rb
|
|
293
322
|
- test/sendgrid/helpers/mail/test_email.rb
|
data/lib/sendgrid/client.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Quickly and easily access the Twilio SendGrid API.
|
|
2
|
-
require 'ruby_http_client'
|
|
3
|
-
require_relative 'version'
|
|
4
|
-
|
|
5
|
-
module SendGrid
|
|
6
|
-
# Initialize the HTTP client
|
|
7
|
-
class API
|
|
8
|
-
attr_accessor :client
|
|
9
|
-
attr_reader :request_headers, :host, :version, :impersonate_subuser
|
|
10
|
-
# * *Args* :
|
|
11
|
-
# - +api_key+ -> your Twilio SendGrid API key
|
|
12
|
-
# - +host+ -> the base URL for the API
|
|
13
|
-
# - +request_headers+ -> any headers that you want to be globally applied
|
|
14
|
-
# - +version+ -> the version of the API you wish to access,
|
|
15
|
-
# currently only "v3" is supported
|
|
16
|
-
#
|
|
17
|
-
def initialize(api_key: '', host: nil, request_headers: nil, version: nil, impersonate_subuser: nil)
|
|
18
|
-
@api_key = api_key
|
|
19
|
-
@host = host ? host : 'https://api.sendgrid.com'
|
|
20
|
-
@version = version ? version : 'v3'
|
|
21
|
-
@impersonate_subuser = impersonate_subuser
|
|
22
|
-
@user_agent = "sendgrid/#{SendGrid::VERSION};ruby"
|
|
23
|
-
@request_headers = JSON.parse('
|
|
24
|
-
{
|
|
25
|
-
"Authorization": "Bearer ' + @api_key + '",
|
|
26
|
-
"Accept": "application/json",
|
|
27
|
-
"User-agent": "' + @user_agent + '"
|
|
28
|
-
}
|
|
29
|
-
')
|
|
30
|
-
@request_headers['On-Behalf-Of'] = @impersonate_subuser if @impersonate_subuser
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@request_headers = @request_headers.merge(request_headers) if request_headers
|
|
34
|
-
@client = Client.new(host: "#{@host}/#{@version}",
|
|
35
|
-
request_headers: @request_headers)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/test/prism.sh
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
install () {
|
|
4
|
-
|
|
5
|
-
set -eu
|
|
6
|
-
|
|
7
|
-
UNAME=$(uname)
|
|
8
|
-
ARCH=$(uname -m)
|
|
9
|
-
if [ "$UNAME" != "Linux" ] && [ "$UNAME" != "Darwin" ] && [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "i686" ]; then
|
|
10
|
-
echo "Sorry, OS/Architecture not supported: ${UNAME}/${ARCH}. Download binary from https://github.com/stoplightio/prism/releases"
|
|
11
|
-
exit 1
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
if [ "$UNAME" = "Darwin" ] ; then
|
|
15
|
-
OSX_ARCH=$(uname -m)
|
|
16
|
-
if [ "${OSX_ARCH}" = "x86_64" ] ; then
|
|
17
|
-
PLATFORM="darwin_amd64"
|
|
18
|
-
fi
|
|
19
|
-
elif [ "$UNAME" = "Linux" ] ; then
|
|
20
|
-
LINUX_ARCH=$(uname -m)
|
|
21
|
-
if [ "${LINUX_ARCH}" = "i686" ] ; then
|
|
22
|
-
PLATFORM="linux_386"
|
|
23
|
-
elif [ "${LINUX_ARCH}" = "x86_64" ] ; then
|
|
24
|
-
PLATFORM="linux_amd64"
|
|
25
|
-
fi
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
#LATEST=$(curl -s https://api.github.com/repos/stoplightio/prism/tags | grep -Eo '"name":.*?[^\\]",' | head -n 1 | sed 's/[," ]//g' | cut -d ':' -f 2)
|
|
29
|
-
LATEST="v0.2.7"
|
|
30
|
-
URL="https://github.com/stoplightio/prism/releases/download/$LATEST/prism_$PLATFORM"
|
|
31
|
-
DEST=./prism/bin/prism
|
|
32
|
-
|
|
33
|
-
if [ -z $LATEST ] ; then
|
|
34
|
-
echo "Error requesting. Download binary from ${URL}"
|
|
35
|
-
exit 1
|
|
36
|
-
else
|
|
37
|
-
curl -L $URL -o $DEST
|
|
38
|
-
chmod +x $DEST
|
|
39
|
-
fi
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
install
|