sendgrid-ruby 6.1.4 → 6.3.3

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.
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