sendgrid-ruby 6.1.4 → 6.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +11 -20
  6. data/CHANGELOG.md +45 -0
  7. data/CONTRIBUTING.md +4 -11
  8. data/Dockerfile +14 -0
  9. data/Gemfile +0 -1
  10. data/Makefile +9 -2
  11. data/README.md +0 -1
  12. data/examples/helpers/eventwebhook/example.rb +16 -0
  13. data/lib/rack/sendgrid_webhook_verification.rb +52 -0
  14. data/lib/sendgrid-ruby.rb +5 -1
  15. data/lib/sendgrid/base_interface.rb +36 -0
  16. data/lib/sendgrid/helpers/eventwebhook/eventwebhook.rb +52 -0
  17. data/lib/sendgrid/sendgrid.rb +20 -0
  18. data/lib/sendgrid/twilio_email.rb +21 -0
  19. data/lib/sendgrid/version.rb +1 -1
  20. data/sendgrid-ruby.gemspec +2 -0
  21. data/spec/fixtures/event_webhook.rb +16 -0
  22. data/spec/rack/sendgrid_webhook_verification_spec.rb +116 -0
  23. data/spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb +103 -0
  24. data/spec/sendgrid/sendgrid_spec.rb +11 -0
  25. data/spec/sendgrid/twilio_email_spec.rb +11 -0
  26. data/spec/spec_helper.rb +2 -0
  27. data/test/sendgrid/helpers/mail/test_mail.rb +1 -1
  28. data/test/sendgrid/test_sendgrid-ruby.rb +24 -59
  29. data/use-cases/README.md +16 -0
  30. data/use-cases/domain-authentication.md +5 -0
  31. data/use-cases/email-statistics.md +52 -0
  32. data/use-cases/legacy-templates.md +98 -0
  33. data/use-cases/sms.md +39 -0
  34. data/use-cases/transactional-templates.md +111 -0
  35. data/use-cases/twilio-email.md +13 -0
  36. data/use-cases/twilio-setup.md +54 -0
  37. metadata +57 -9
  38. data/USE_CASES.md +0 -377
  39. data/docker/Dockerfile +0 -12
  40. data/docker/README.md +0 -30
  41. data/lib/sendgrid/client.rb +0 -38
  42. data/test/prism.sh +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dee5a58da05e1ac621914725e55f8d8edd5fbe41998e63d96ae34a27b61e46c3
4
- data.tar.gz: bcafe9bf1024882418c847d5fcc2118c587b4b1275e63033592eb6fc84ab6676
3
+ metadata.gz: 0a99cbab593becca226765be0e10692ded5477764699344b3b93ca619aa3290e
4
+ data.tar.gz: 2db29c6f0abeef43197c19fd384a2760e42f0ba952ed490a3ba60efbab3a1261
5
5
  SHA512:
6
- metadata.gz: 5349c910cd270a5579f1aef22b860c9267210467115e17b15a873b2d2f9b2f826afa51272b8741035c9426da2bea72a81a0b1f127a3c1a1144afa775689f28c5
7
- data.tar.gz: 1cd1328b16c887ac2f1c9b7f5676c07c2bc07b37b8d09419a97b341c1361735608638b27b5eae1acaf99eef1b15eec338014523824ac77abe00fb5cbdb792d9d
6
+ metadata.gz: 4c9853763d323eef8a89334648df9cb8f8a3ed30687fedd463cffaec72aa6f4ca6627280a7c7805f8040001370c96441810e32fcec5b1528961b114734c85664
7
+ data.tar.gz: f46c413bb546de8f57eaa1bc4cb85ef73a585a372a5df1417c7511d79797f9b42ddfb2a7797550e831182a597fe5bdeebd95ce794d9dd505a1434d5ad4e929f0
@@ -16,6 +16,6 @@ ratings:
16
16
  - "**.rb"
17
17
  exclude_paths:
18
18
  - examples/
19
+ - gemfiles/
19
20
  - spec/
20
21
  - test/
21
- - gemfiles/
data/.gitignore CHANGED
@@ -39,3 +39,5 @@ Gemfile.lock
39
39
 
40
40
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
41
41
  .rvmrc
42
+
43
+ prism*
@@ -0,0 +1,6 @@
1
+ AllCops:
2
+ Exclude:
3
+ - examples/**/*
4
+ - gemfiles/**/*
5
+ - spec/**/*
6
+ - test/**/*
@@ -1,25 +1,17 @@
1
1
  language: ruby
2
- rvm:
3
- - ruby-head
4
- - 2.7
5
- - 2.6
6
- - 2.5
7
- - 2.4
8
- - jruby-9.2
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
- before_script:
13
- - mkdir prism
14
- - mkdir prism/bin
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,8 +19,7 @@ deploy:
27
19
  gem: sendgrid-ruby
28
20
  on:
29
21
  tags: true
30
- rvm: '2.4'
31
- condition: '$BUNDLE_GEMFILE == *"gemfiles/Sinatra_1.gemfile"'
22
+ condition: $version = ruby:2.4 && $BUNDLE_GEMFILE = *"gemfiles/Sinatra_1.gemfile"
32
23
 
33
24
  notifications:
34
25
  slack:
@@ -1,6 +1,51 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ [2020-07-22] Version 6.3.3
5
+ --------------------------
6
+ **Library - Chore**
7
+ - [PR #431](https://github.com/sendgrid/sendgrid-ruby/pull/431): migrate to new default sendgrid-oai branch. Thanks to [@eshanholtz](https://github.com/eshanholtz)!
8
+ - [PR #366](https://github.com/sendgrid/sendgrid-ruby/pull/366): add Rubocop configuration file. Thanks to [@RolandBurrows](https://github.com/RolandBurrows)!
9
+
10
+ **Library - Test**
11
+ - [PR #429](https://github.com/sendgrid/sendgrid-ruby/pull/429): fix the license test and actually run the test scripts. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
12
+
13
+ **Library - Docs**
14
+ - [PR #273](https://github.com/sendgrid/sendgrid-ruby/pull/273): Create a Use Cases Directory and Associated Files. Thanks to [@alanunruh](https://github.com/alanunruh)!
15
+
16
+
17
+ [2020-07-08] Version 6.3.2
18
+ --------------------------
19
+ **Library - Test**
20
+ - [PR #368](https://github.com/sendgrid/sendgrid-ruby/pull/368): add Simplecov Local Enhancements. Thanks to [@RolandBurrows](https://github.com/RolandBurrows)!
21
+
22
+
23
+ [2020-06-25] Version 6.3.1
24
+ --------------------------
25
+
26
+
27
+ [2020-06-24] Version 6.3.0
28
+ --------------------------
29
+ **Library - Feature**
30
+ - [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)!
31
+ - [PR #425](https://github.com/sendgrid/sendgrid-ruby/pull/425): verify signature from event webhook. Thanks to [@eshanholtz](https://github.com/eshanholtz)!
32
+
33
+ **Library - Fix**
34
+ - [PR #427](https://github.com/sendgrid/sendgrid-ruby/pull/427): drop the starkbank dependency. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
35
+
36
+
37
+ [2020-05-13] Version 6.2.1
38
+ --------------------------
39
+ **Library - Fix**
40
+ - [PR #421](https://github.com/sendgrid/sendgrid-ruby/pull/421): migrate to common prism setup. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
41
+
42
+
43
+ [2020-04-29] Version 6.2.0
44
+ --------------------------
45
+ **Library - Feature**
46
+ - [PR #417](https://github.com/sendgrid/sendgrid-ruby/pull/417): add support for Twilio Email. Thanks to [@childish-sambino](https://github.com/childish-sambino)!
47
+
48
+
4
49
  [2020-04-15] Version 6.1.4
5
50
  --------------------------
6
51
  **Library - Fix**
@@ -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](https://github.com/sendgrid/sendgrid-ruby/blob/master/ISSUE_TEMPLATE.md) (borrowed from [Ghost](https://github.com/TryGhost/Ghost/)). The template uses [GitHub flavored markdown](https://help.github.com/articles/github-flavored-markdown/) for formatting.
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
@@ -124,20 +124,13 @@ Tests for the mail send and Web API v3 endpoints.
124
124
 
125
125
  The Web API v3 client is `sendgrid-ruby.rb`
126
126
 
127
- <a name="testing"></a>
128
127
  ## Testing
129
128
 
130
- All PRs require passing tests before the PR will be reviewed.
129
+ All PRs require passing tests before the PR will be reviewed. All test files are in the [`tests`](https://github.com/sendgrid/sendgrid-ruby/tree/master/test) directory. For the purposes of contributing to this repo, please update the [`test_sendgrid-ruby.rb`](https://github.com/sendgrid/sendgrid-ruby/blob/master/test/test_sendgrid-ruby.rb) file with unit tests as you modify the code.
131
130
 
132
- All test files are in the [`tests`](https://github.com/sendgrid/sendgrid-ruby/tree/master/test) directory.
131
+ The integration tests require a Twilio SendGrid mock API in order to execute. We've simplified setting this up using Docker to run the tests. You will just need [Docker Desktop](https://docs.docker.com/get-docker/) and `make`.
133
132
 
134
- For the purposes of contributing to this repo, please update the [`test_sendgrid-ruby.rb`](https://github.com/sendgrid/sendgrid-ruby/blob/master/test/test_sendgrid-ruby.rb) file with unit tests as you modify the code.
135
-
136
- To run the tests:
137
-
138
- ```bash
139
- rake
140
- ```
133
+ Once these are available, simply execute the Docker test target to run all tests: `make test-docker`. This command can also be used to open an interactive shell into the container where this library is installed. To start a *bash* shell for example, use this command: `command=bash make test-docker`.
141
134
 
142
135
  <a name="style-guidelines-and-naming-conventions"></a>
143
136
  ## Style Guidelines & Naming Conventions
@@ -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
@@ -3,4 +3,3 @@ source 'http://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'ruby_http_client'
6
-
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
- bundle exec rake spec
7
+ bundle exec rake
8
+
9
+ test-integ: test
10
+
11
+ version ?= ruby:latest
12
+ test-docker:
13
+ curl -s https://raw.githubusercontent.com/sendgrid/sendgrid-oai/main/prism/prism.sh -o prism.sh
14
+ version=$(version) bash ./prism.sh
data/README.md CHANGED
@@ -205,7 +205,6 @@ We encourage contribution to our libraries (you might even score some nifty swag
205
205
 
206
206
  - [Feature Request](https://github.com/sendgrid/sendgrid-ruby/tree/master/CONTRIBUTING.md#feature_request)
207
207
  - [Bug Reports](https://github.com/sendgrid/sendgrid-ruby/tree/master/CONTRIBUTING.md#submit_a_bug_report)
208
- - [Sign the CLA to Create a Pull Request](https://github.com/sendgrid/sendgrid-ruby/tree/master/CONTRIBUTING.md#cla)
209
208
  - [Improvements to the Codebase](https://github.com/sendgrid/sendgrid-ruby/tree/master/CONTRIBUTING.md#improvements_to_the_codebase)
210
209
  - [Review Pull Requests](https://github.com/sendgrid/sendgrid-ruby/blob/master/CONTRIBUTING.md#code-reviews)
211
210
 
@@ -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
@@ -1,5 +1,8 @@
1
- require_relative 'sendgrid/client'
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
@@ -1,3 +1,3 @@
1
1
  module SendGrid
2
- VERSION = '6.1.4'
2
+ VERSION = '6.3.3'
3
3
  end
@@ -27,4 +27,6 @@ Gem::Specification.new do |spec|
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'
31
+ spec.add_development_dependency 'simplecov'
30
32
  end