sendgrid-ruby 1.1.6 → 6.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. checksums.yaml +5 -5
  2. data/.env_sample +1 -3
  3. data/.github/ISSUE_TEMPLATE/config.yml +10 -0
  4. data/.github/workflows/test-and-deploy.yml +120 -0
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +5 -27
  7. data/.rubocop_todo.yml +127 -0
  8. data/CHANGELOG.md +417 -1
  9. data/CODE_OF_CONDUCT.md +73 -0
  10. data/CONTRIBUTING.md +202 -0
  11. data/Dockerfile +14 -0
  12. data/FIRST_TIMERS.md +79 -0
  13. data/Gemfile +4 -4
  14. data/ISSUE_TEMPLATE.md +30 -0
  15. data/LICENSE +21 -0
  16. data/Makefile +14 -0
  17. data/PULL_REQUEST_TEMPLATE.md +31 -0
  18. data/README.md +153 -229
  19. data/Rakefile +9 -3
  20. data/TROUBLESHOOTING.md +151 -0
  21. data/UPGRADE.md +5 -0
  22. data/USAGE.md +5144 -0
  23. data/config.ru +4 -0
  24. data/examples/accesssettings/accesssettings.rb +80 -0
  25. data/examples/alerts/alerts.rb +59 -0
  26. data/examples/apikeys/apikeys.rb +81 -0
  27. data/examples/asm/asm.rb +170 -0
  28. data/examples/browsers/browsers.rb +13 -0
  29. data/examples/campaigns/campaigns.rb +150 -0
  30. data/examples/categories/categories.rb +33 -0
  31. data/examples/clients/clients.rb +24 -0
  32. data/examples/contactdb/contactdb.rb +392 -0
  33. data/examples/devices/devices.rb +13 -0
  34. data/examples/emailactivity/emailactivity.rb +52 -0
  35. data/examples/geo/geo.rb +13 -0
  36. data/examples/helpers/eventwebhook/example.rb +16 -0
  37. data/examples/helpers/mail/example.rb +158 -0
  38. data/examples/helpers/settings/example.rb +23 -0
  39. data/examples/helpers/stats/example.rb +42 -0
  40. data/examples/ips/ips.rb +164 -0
  41. data/examples/mail/mail.rb +170 -0
  42. data/examples/mailboxproviders/mailboxproviders.rb +13 -0
  43. data/examples/mailsettings/mailsettings.rb +216 -0
  44. data/examples/partnersettings/partnersettings.rb +36 -0
  45. data/examples/scopes/scopes.rb +59 -0
  46. data/examples/senderauthentication/senderauthentication.rb +307 -0
  47. data/examples/senders/senders.rb +95 -0
  48. data/examples/stats/stats.rb +13 -0
  49. data/examples/subusers/subusers.rb +166 -0
  50. data/examples/suppression/suppression.rb +198 -0
  51. data/examples/templates/templates.rb +127 -0
  52. data/examples/trackingsettings/trackingsettings.rb +107 -0
  53. data/examples/user/user.rb +290 -0
  54. data/gemfiles/Sinatra_1.gemfile +6 -0
  55. data/gemfiles/Sinatra_2.gemfile +6 -0
  56. data/lib/rack/sendgrid_webhook_verification.rb +55 -0
  57. data/lib/sendgrid/base_interface.rb +40 -0
  58. data/lib/sendgrid/helpers/eventwebhook/eventwebhook.rb +50 -0
  59. data/lib/sendgrid/helpers/inbound/README.md +98 -0
  60. data/lib/sendgrid/helpers/inbound/app.rb +32 -0
  61. data/lib/sendgrid/helpers/inbound/config.yml +26 -0
  62. data/lib/sendgrid/helpers/inbound/public/index.html +10 -0
  63. data/lib/sendgrid/helpers/inbound/sample_data/default_data.txt +58 -0
  64. data/lib/sendgrid/helpers/inbound/sample_data/raw_data.txt +57 -0
  65. data/lib/sendgrid/helpers/inbound/sample_data/raw_data_with_attachments.txt +298 -0
  66. data/lib/sendgrid/helpers/inbound/send.rb +26 -0
  67. data/lib/sendgrid/helpers/ip_management/ip_management.rb +17 -0
  68. data/lib/sendgrid/helpers/mail/README.md +14 -0
  69. data/lib/sendgrid/helpers/mail/asm.rb +19 -0
  70. data/lib/sendgrid/helpers/mail/attachment.rb +55 -0
  71. data/lib/sendgrid/helpers/mail/bcc_settings.rb +19 -0
  72. data/lib/sendgrid/helpers/mail/bypass_list_management.rb +31 -0
  73. data/lib/sendgrid/helpers/mail/category.rb +18 -0
  74. data/lib/sendgrid/helpers/mail/click_tracking.rb +19 -0
  75. data/lib/sendgrid/helpers/mail/content.rb +19 -0
  76. data/lib/sendgrid/helpers/mail/custom_arg.rb +18 -0
  77. data/lib/sendgrid/helpers/mail/email.rb +32 -0
  78. data/lib/sendgrid/helpers/mail/footer.rb +21 -0
  79. data/lib/sendgrid/helpers/mail/ganalytics.rb +28 -0
  80. data/lib/sendgrid/helpers/mail/header.rb +18 -0
  81. data/lib/sendgrid/helpers/mail/mail.rb +122 -0
  82. data/lib/sendgrid/helpers/mail/mail_settings.rb +45 -0
  83. data/lib/sendgrid/helpers/mail/open_tracking.rb +19 -0
  84. data/lib/sendgrid/helpers/mail/personalization.rb +93 -0
  85. data/lib/sendgrid/helpers/mail/section.rb +18 -0
  86. data/lib/sendgrid/helpers/mail/spam_check.rb +21 -0
  87. data/lib/sendgrid/helpers/mail/subscription_tracking.rb +23 -0
  88. data/lib/sendgrid/helpers/mail/substitution.rb +18 -0
  89. data/lib/sendgrid/helpers/mail/tracking_settings.rb +39 -0
  90. data/lib/sendgrid/helpers/permissions/scope.rb +28 -0
  91. data/lib/sendgrid/helpers/permissions/scopes.yml +309 -0
  92. data/lib/sendgrid/helpers/settings/README.md +14 -0
  93. data/lib/sendgrid/helpers/settings/mail_settings_dto.rb +13 -0
  94. data/lib/sendgrid/helpers/settings/partner_settings_dto.rb +13 -0
  95. data/lib/sendgrid/helpers/settings/settings.rb +28 -0
  96. data/lib/sendgrid/helpers/settings/tracking_settings_dto.rb +22 -0
  97. data/lib/sendgrid/helpers/settings/user_settings_dto.rb +13 -0
  98. data/lib/sendgrid/helpers/stats/email_stats.rb +46 -0
  99. data/lib/sendgrid/helpers/stats/metrics.rb +33 -0
  100. data/lib/sendgrid/helpers/stats/stats_response.rb +29 -0
  101. data/lib/sendgrid/sendgrid.rb +21 -0
  102. data/lib/sendgrid/twilio_email.rb +21 -0
  103. data/lib/sendgrid/version.rb +1 -1
  104. data/lib/sendgrid-ruby.rb +32 -7
  105. data/mail_helper_v3.md +390 -0
  106. data/sendgrid-ruby.gemspec +16 -20
  107. data/spec/fixtures/event_webhook.rb +22 -0
  108. data/spec/rack/sendgrid_webhook_verification_spec.rb +142 -0
  109. data/spec/sendgrid/helpers/eventwebhook/eventwebhook_spec.rb +105 -0
  110. data/spec/sendgrid/helpers/ip_management/ip_management_spec.rb +12 -0
  111. data/spec/sendgrid/helpers/settings/mail_settings_dto_spec.rb +32 -0
  112. data/spec/sendgrid/helpers/settings/partner_settings_dto_spec.rb +24 -0
  113. data/spec/sendgrid/helpers/settings/settings_spec.rb +25 -0
  114. data/spec/sendgrid/helpers/settings/tracking_settings_dto_spec.rb +27 -0
  115. data/spec/sendgrid/helpers/settings/user_settings_dto_spec.rb +24 -0
  116. data/spec/sendgrid/helpers/stats/email_stats_spec.rb +111 -0
  117. data/spec/sendgrid/helpers/stats/metrics_spec.rb +45 -0
  118. data/spec/sendgrid/helpers/stats/stats_response_spec.rb +75 -0
  119. data/spec/sendgrid/sendgrid_spec.rb +11 -0
  120. data/spec/sendgrid/twilio_email_spec.rb +11 -0
  121. data/spec/spec_helper.rb +12 -1
  122. data/static/img/github-fork.png +0 -0
  123. data/static/img/github-sign-up.png +0 -0
  124. data/test/sendgrid/helpers/mail/test_attachment.rb +33 -0
  125. data/test/sendgrid/helpers/mail/test_category.rb +25 -0
  126. data/test/sendgrid/helpers/mail/test_email.rb +41 -0
  127. data/test/sendgrid/helpers/mail/test_mail.rb +260 -0
  128. data/test/sendgrid/helpers/mail/test_personalizations.rb +214 -0
  129. data/test/sendgrid/permissions/test_scopes.rb +36 -0
  130. data/test/sendgrid/test_sendgrid-ruby.rb +2729 -0
  131. data/twilio_sendgrid_logo.png +0 -0
  132. data/use-cases/README.md +17 -0
  133. data/use-cases/domain-authentication.md +5 -0
  134. data/use-cases/email-statistics.md +52 -0
  135. data/use-cases/legacy-templates.md +98 -0
  136. data/use-cases/personalizations.md +34 -0
  137. data/use-cases/sms.md +39 -0
  138. data/use-cases/transactional-templates.md +111 -0
  139. data/use-cases/twilio-email.md +13 -0
  140. data/use-cases/twilio-setup.md +54 -0
  141. metadata +187 -112
  142. data/.rspec +0 -2
  143. data/.travis.yml +0 -20
  144. data/FETCH_HEAD +0 -0
  145. data/Guardfile +0 -10
  146. data/LICENSE.txt +0 -22
  147. data/example.rb +0 -41
  148. data/lib/sendgrid/client.rb +0 -62
  149. data/lib/sendgrid/exceptions.rb +0 -7
  150. data/lib/sendgrid/mail.rb +0 -182
  151. data/lib/sendgrid/recipient.rb +0 -29
  152. data/lib/sendgrid/response.rb +0 -14
  153. data/lib/sendgrid/template.rb +0 -26
  154. data/lib/sendgrid/template_mailer.rb +0 -59
  155. data/spec/lib/sendgrid/client_spec.rb +0 -87
  156. data/spec/lib/sendgrid/mail_spec.rb +0 -151
  157. data/spec/lib/sendgrid/recipient_spec.rb +0 -91
  158. data/spec/lib/sendgrid/template_mailer_spec.rb +0 -86
  159. data/spec/lib/sendgrid/template_spec.rb +0 -61
  160. data/spec/lib/sendgrid_spec.rb +0 -7
@@ -0,0 +1,290 @@
1
+ require 'sendgrid-ruby'
2
+
3
+ sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
4
+
5
+ ##################################################
6
+ # Get a user's account information. #
7
+ # GET /user/account #
8
+
9
+ response = sg.client.user.account.get
10
+ puts response.status_code
11
+ puts response.body
12
+ puts response.headers
13
+
14
+ ##################################################
15
+ # Retrieve your credit balance #
16
+ # GET /user/credits #
17
+
18
+ response = sg.client.user.credits.get
19
+ puts response.status_code
20
+ puts response.body
21
+ puts response.headers
22
+
23
+ ##################################################
24
+ # Update your account email address #
25
+ # PUT /user/email #
26
+
27
+ data = JSON.parse('{
28
+ "email": "example@example.com"
29
+ }')
30
+ response = sg.client.user.email.put(request_body: data)
31
+ puts response.status_code
32
+ puts response.body
33
+ puts response.headers
34
+
35
+ ##################################################
36
+ # Retrieve your account email address #
37
+ # GET /user/email #
38
+
39
+ response = sg.client.user.email.get
40
+ puts response.status_code
41
+ puts response.body
42
+ puts response.headers
43
+
44
+ ##################################################
45
+ # Update your password #
46
+ # PUT /user/password #
47
+
48
+ data = JSON.parse('{
49
+ "new_password": "new_password",
50
+ "old_password": "old_password"
51
+ }')
52
+ response = sg.client.user.password.put(request_body: data)
53
+ puts response.status_code
54
+ puts response.body
55
+ puts response.headers
56
+
57
+ ##################################################
58
+ # Update a user's profile #
59
+ # PATCH /user/profile #
60
+
61
+ data = JSON.parse('{
62
+ "city": "Orange",
63
+ "first_name": "Example",
64
+ "last_name": "User"
65
+ }')
66
+ response = sg.client.user.profile.patch(request_body: data)
67
+ puts response.status_code
68
+ puts response.body
69
+ puts response.headers
70
+
71
+ ##################################################
72
+ # Get a user's profile #
73
+ # GET /user/profile #
74
+
75
+ response = sg.client.user.profile.get
76
+ puts response.status_code
77
+ puts response.body
78
+ puts response.headers
79
+
80
+ ##################################################
81
+ # Cancel or pause a scheduled send #
82
+ # POST /user/scheduled_sends #
83
+
84
+ data = JSON.parse('{
85
+ "batch_id": "YOUR_BATCH_ID",
86
+ "status": "pause"
87
+ }')
88
+ response = sg.client.user.scheduled_sends.post(request_body: data)
89
+ puts response.status_code
90
+ puts response.body
91
+ puts response.headers
92
+
93
+ ##################################################
94
+ # Retrieve all scheduled sends #
95
+ # GET /user/scheduled_sends #
96
+
97
+ response = sg.client.user.scheduled_sends.get
98
+ puts response.status_code
99
+ puts response.body
100
+ puts response.headers
101
+
102
+ ##################################################
103
+ # Update user scheduled send information #
104
+ # PATCH /user/scheduled_sends/{batch_id} #
105
+
106
+ data = JSON.parse('{
107
+ "status": "pause"
108
+ }')
109
+ batch_id = 'test_url_param'
110
+ response = sg.client.user.scheduled_sends._(batch_id).patch(request_body: data)
111
+ puts response.status_code
112
+ puts response.body
113
+ puts response.headers
114
+
115
+ ##################################################
116
+ # Retrieve scheduled send #
117
+ # GET /user/scheduled_sends/{batch_id} #
118
+
119
+ batch_id = 'test_url_param'
120
+ response = sg.client.user.scheduled_sends._(batch_id).get
121
+ puts response.status_code
122
+ puts response.body
123
+ puts response.headers
124
+
125
+ ##################################################
126
+ # Delete a cancellation or pause of a scheduled send #
127
+ # DELETE /user/scheduled_sends/{batch_id} #
128
+
129
+ batch_id = 'test_url_param'
130
+ response = sg.client.user.scheduled_sends._(batch_id).delete
131
+ puts response.status_code
132
+ puts response.body
133
+ puts response.headers
134
+
135
+ ##################################################
136
+ # Update Enforced TLS settings #
137
+ # PATCH /user/settings/enforced_tls #
138
+
139
+ data = JSON.parse('{
140
+ "require_tls": true,
141
+ "require_valid_cert": false
142
+ }')
143
+ response = sg.client.user.settings.enforced_tls.patch(request_body: data)
144
+ puts response.status_code
145
+ puts response.body
146
+ puts response.headers
147
+
148
+ ##################################################
149
+ # Retrieve current Enforced TLS settings. #
150
+ # GET /user/settings/enforced_tls #
151
+
152
+ response = sg.client.user.settings.enforced_tls.get
153
+ puts response.status_code
154
+ puts response.body
155
+ puts response.headers
156
+
157
+ ##################################################
158
+ # Update your username #
159
+ # PUT /user/username #
160
+
161
+ data = JSON.parse('{
162
+ "username": "test_username"
163
+ }')
164
+ response = sg.client.user.username.put(request_body: data)
165
+ puts response.status_code
166
+ puts response.body
167
+ puts response.headers
168
+
169
+ ##################################################
170
+ # Retrieve your username #
171
+ # GET /user/username #
172
+
173
+ response = sg.client.user.username.get
174
+ puts response.status_code
175
+ puts response.body
176
+ puts response.headers
177
+
178
+ ##################################################
179
+ # Update Event Notification Settings #
180
+ # PATCH /user/webhooks/event/settings #
181
+
182
+ data = JSON.parse('{
183
+ "bounce": true,
184
+ "click": true,
185
+ "deferred": true,
186
+ "delivered": true,
187
+ "dropped": true,
188
+ "enabled": true,
189
+ "group_resubscribe": true,
190
+ "group_unsubscribe": true,
191
+ "open": true,
192
+ "processed": true,
193
+ "spam_report": true,
194
+ "unsubscribe": true,
195
+ "url": "url"
196
+ }')
197
+ response = sg.client.user.webhooks.event.settings.patch(request_body: data)
198
+ puts response.status_code
199
+ puts response.body
200
+ puts response.headers
201
+
202
+ ##################################################
203
+ # Retrieve Event Webhook settings #
204
+ # GET /user/webhooks/event/settings #
205
+
206
+ response = sg.client.user.webhooks.event.settings.get
207
+ puts response.status_code
208
+ puts response.body
209
+ puts response.headers
210
+
211
+ ##################################################
212
+ # Test Event Notification Settings #
213
+ # POST /user/webhooks/event/test #
214
+
215
+ data = JSON.parse('{
216
+ "url": "url"
217
+ }')
218
+ response = sg.client.user.webhooks.event.test.post(request_body: data)
219
+ puts response.status_code
220
+ puts response.body
221
+ puts response.headers
222
+
223
+ ##################################################
224
+ # Create a parse setting #
225
+ # POST /user/webhooks/parse/settings #
226
+
227
+ data = JSON.parse('{
228
+ "hostname": "myhostname.com",
229
+ "send_raw": false,
230
+ "spam_check": true,
231
+ "url": "http://email.myhosthame.com"
232
+ }')
233
+ response = sg.client.user.webhooks.parse.settings.post(request_body: data)
234
+ puts response.status_code
235
+ puts response.body
236
+ puts response.headers
237
+
238
+ ##################################################
239
+ # Retrieve all parse settings #
240
+ # GET /user/webhooks/parse/settings #
241
+
242
+ response = sg.client.user.webhooks.parse.settings.get
243
+ puts response.status_code
244
+ puts response.body
245
+ puts response.headers
246
+
247
+ ##################################################
248
+ # Update a parse setting #
249
+ # PATCH /user/webhooks/parse/settings/{hostname} #
250
+
251
+ data = JSON.parse('{
252
+ "send_raw": true,
253
+ "spam_check": false,
254
+ "url": "http://newdomain.com/parse"
255
+ }')
256
+ hostname = 'test_url_param'
257
+ response = sg.client.user.webhooks.parse.settings._(hostname).patch(request_body: data)
258
+ puts response.status_code
259
+ puts response.body
260
+ puts response.headers
261
+
262
+ ##################################################
263
+ # Retrieve a specific parse setting #
264
+ # GET /user/webhooks/parse/settings/{hostname} #
265
+
266
+ hostname = 'test_url_param'
267
+ response = sg.client.user.webhooks.parse.settings._(hostname).get
268
+ puts response.status_code
269
+ puts response.body
270
+ puts response.headers
271
+
272
+ ##################################################
273
+ # Delete a parse setting #
274
+ # DELETE /user/webhooks/parse/settings/{hostname} #
275
+
276
+ hostname = 'test_url_param'
277
+ response = sg.client.user.webhooks.parse.settings._(hostname).delete
278
+ puts response.status_code
279
+ puts response.body
280
+ puts response.headers
281
+
282
+ ##################################################
283
+ # Retrieves Inbound Parse Webhook statistics. #
284
+ # GET /user/webhooks/parse/stats #
285
+
286
+ params = JSON.parse('{"aggregated_by": "day", "limit": "test_string", "start_date": "2016-01-01", "end_date": "2016-04-01", "offset": "test_string"}')
287
+ response = sg.client.user.webhooks.parse.stats.get(query_params: params)
288
+ puts response.status_code
289
+ puts response.body
290
+ puts response.headers
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'ruby_http_client'
6
+ gem 'sinatra', '~> 1.4'
@@ -0,0 +1,6 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec path: '..'
4
+
5
+ gem 'ruby_http_client'
6
+ gem 'sinatra', '>= 2.0.0.rc2'
@@ -0,0 +1,55 @@
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
+
31
+ request = Rack::Request.new(env)
32
+
33
+ event_webhook = SendGrid::EventWebhook.new
34
+ ec_public_key = event_webhook.convert_public_key_to_ecdsa(@public_key)
35
+ verified = event_webhook.verify_signature(
36
+ ec_public_key,
37
+ request.body.read,
38
+ request.env[SendGrid::EventWebhookHeader::SIGNATURE],
39
+ request.env[SendGrid::EventWebhookHeader::TIMESTAMP]
40
+ )
41
+
42
+ request.body.rewind
43
+
44
+ if verified
45
+ @app.call(env)
46
+ else
47
+ [
48
+ 403,
49
+ { 'Content-Type' => 'text/plain' },
50
+ ['SendGrid Request Verification Failed.']
51
+ ]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,40 @@
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, :http_options
8
+
9
+ # * *Args* :
10
+ # - +auth+ -> authorization header value
11
+ # - +host+ -> the base URL for the API
12
+ # - +request_headers+ -> any headers that you want to be globally applied
13
+ # - +version+ -> the version of the API you wish to access,
14
+ # currently only "v3" is supported
15
+ # - +impersonate_subuser+ -> the subuser to impersonate, will be passed
16
+ # in the "On-Behalf-Of" header
17
+ # - +http_options+ -> http options that you want to be globally applied to each request
18
+ #
19
+ def initialize(auth:, host:, request_headers: nil, version: nil, impersonate_subuser: nil, http_options: {})
20
+ @auth = auth
21
+ @host = host
22
+ @version = version || 'v3'
23
+ @impersonate_subuser = impersonate_subuser
24
+ @user_agent = "sendgrid/#{SendGrid::VERSION};ruby"
25
+ @request_headers = JSON.parse('
26
+ {
27
+ "Authorization": "' + @auth + '",
28
+ "Accept": "application/json",
29
+ "User-Agent": "' + @user_agent + '"
30
+ }
31
+ ')
32
+ @request_headers['On-Behalf-Of'] = @impersonate_subuser if @impersonate_subuser
33
+
34
+ @request_headers = @request_headers.merge(request_headers) if request_headers
35
+ @http_options = http_options
36
+ @client = SendGrid::Client.new(host: "#{@host}/#{@version}",
37
+ request_headers: @request_headers,
38
+ http_options: @http_options)
39
+ end
40
+ end
@@ -0,0 +1,50 @@
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 StandardError
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
+ raise NotSupportedError, "Event Webhook verification is not supported by JRuby" if RUBY_PLATFORM == "java"
35
+ end
36
+
37
+ class Error < ::RuntimeError
38
+ end
39
+
40
+ class NotSupportedError < Error
41
+ end
42
+ end
43
+
44
+ # This class lists headers that get posted to the webhook. Read the docs for
45
+ # more details: https://sendgrid.com/docs/for-developers/tracking-events/event
46
+ class EventWebhookHeader
47
+ SIGNATURE = "HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_SIGNATURE".freeze
48
+ TIMESTAMP = "HTTP_X_TWILIO_EMAIL_EVENT_WEBHOOK_TIMESTAMP".freeze
49
+ end
50
+ end
@@ -0,0 +1,98 @@
1
+ **This helper is a stand alone module to help get you started consuming and processing Inbound Parse data.**
2
+
3
+ ## Table of Contents
4
+
5
+ - [Installation](#installation)
6
+ - [Quick Start for Local Testing with Sample Data](#quick-start-for-local-testing-with-sample-data)
7
+ - [Quick Start for Local Testing with Real Data](#quick-start-for-local-testing-with-real-data)
8
+ - [Code Walkthrough](#code-walkthrough)
9
+ - [app.rb](#apprb)
10
+ - [config.yml](#configyml)
11
+ - [send.rb & /sample_data](#sendrb--sampledata)
12
+ - [Contributing](#contributing)
13
+
14
+ <a name="quick_start_local_sample"></a>
15
+
16
+
17
+ # Installation
18
+
19
+ In addition to the installation instructions in
20
+ [the main readme](../../../../README.md#installation),
21
+ you must also add sinatra to your Gemfile:
22
+
23
+ ```
24
+ gem 'sinatra', '>= 1.4.7', '< 3'
25
+ ```
26
+
27
+
28
+ # Quick Start for Local Testing with Sample Data
29
+
30
+ ```bash
31
+ git clone https://github.com/sendgrid/sendgrid-ruby.git
32
+ cd sendgrid-ruby
33
+ bundle install
34
+ ```
35
+
36
+ Run the Inbound Parse listener in your terminal:
37
+
38
+ ```ruby
39
+ rackup
40
+ ```
41
+
42
+ In another terminal, run the test data sender:
43
+
44
+ ```bash
45
+ cd [path to sendgrid-ruby]
46
+ bundle install
47
+ ruby ./lib/sendgrid/helpers/inbound/send.rb ./lib/sendgrid/helpers/inbound/sample_data/default_data.txt
48
+ ```
49
+
50
+ More sample data can be found [here](sample_data).
51
+
52
+ View the results in the first terminal.
53
+
54
+ <a name="quick_start_local_real"></a>
55
+ # Quick Start for Local Testing with Real Data
56
+
57
+ [Setup your MX records.](https://sendgrid.com/docs/Classroom/Basics/Inbound_Parse_Webhook/setting_up_the_inbound_parse_webhook.html#-Setup) Depending on your domain name host, you may need to wait up to 48 hours for the settings to propagate.
58
+
59
+ Run the Inbound Parse listener in your terminal:
60
+
61
+ ```bash
62
+ git clone https://github.com/sendgrid/sendgrid-ruby.git
63
+ cd sendgrid-ruby
64
+ bundle install
65
+ rackup
66
+ ```
67
+
68
+ In another terminal, use [ngrok](https://ngrok.com/) to allow external access to your machine:
69
+ ```bash
70
+ ngrok http 9292
71
+ ```
72
+
73
+ Update your Twilio SendGrid Incoming Parse settings: [Settings Page](https://app.sendgrid.com/settings/parse) | [Docs](https://sendgrid.com/docs/Classroom/Basics/Inbound_Parse_Webhook/setting_up_the_inbound_parse_webhook.html#-Pointing-to-a-Hostname-and-URL)
74
+
75
+ - For the HOSTNAME field, use the domain that you changed the MX records (e.g. inbound.yourdomain.com)
76
+ - For the URL field, use the URL generated by ngrok + /inbound, e.g http://XXXXXXX.ngrok.io/inbound
77
+
78
+ Next, send an email to [anything]@inbound.yourdomain.com, then look at the terminal where you started the Inbound Parse listener.
79
+
80
+ <a name="code_walkthrough"></a>
81
+ # Code Walkthrough
82
+
83
+ ## app.rb
84
+
85
+ This module runs a [Sinatra](http://www.sinatrarb.com/) server, that by default (you can change those settings [here](config.yml)), listens for POSTs on http://localhost:9292. When the server receives the POST, it parses and prints the key/value data.
86
+
87
+ ## config.yml
88
+
89
+ This module loads application environment variables (located in [config.yml](config.yml)).
90
+
91
+ ## send.rb & /sample_data
92
+
93
+ This module is used to send sample test data. It is useful for testing and development, particularly while you wait for your MX records to propagate.
94
+
95
+ <a name="contributing"></a>
96
+ # Contributing
97
+
98
+ If you would like to contribute to this project, please see our [contributing guide](../../../../CONTRIBUTING.md). Thanks!
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'sinatra'
3
+ rescue LoadError
4
+ puts <<-NOTE
5
+ As of sengrid verison 6, sinatra is no longer specified as a dependency of
6
+ the sendgrid gem. All the functionality of the inbound server is still the same
7
+ and fully supported, but you just need to include the sinatra dependency in your gemfile
8
+ yourself, like so:
9
+
10
+ gem 'sinatra', '>= 1.4.7', '< 3'
11
+ NOTE
12
+ raise
13
+ end
14
+ require 'logger'
15
+ require 'json'
16
+ require 'yaml'
17
+
18
+ class Main < Sinatra::Base
19
+ configure :production, :development do
20
+ enable :logging
21
+ set :config, YAML.load_file("#{File.dirname(__FILE__)}/config.yml")
22
+ end
23
+
24
+ get '/' do
25
+ redirect to('index.html')
26
+ end
27
+
28
+ post settings.config['endpoint'] do
29
+ filtered = params.select { |k, _v| settings.config['keys'].include?(k) }
30
+ logger.info JSON.pretty_generate(filtered)
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # Incoming Parse endpoint for receiver
2
+ endpoint: '/inbound'
3
+
4
+ # List all Incoming Parse fields you would like parsed
5
+ # Reference: https://sendgrid.com/docs/Classroom/Basics/Inbound_Parse_Webhook/setting_up_the_inbound_parse_webhook.html
6
+ keys:
7
+ - from
8
+ - attachments
9
+ - headers
10
+ - text
11
+ - envelope
12
+ - to
13
+ - html
14
+ - sender_ip
15
+ - attachment-info
16
+ - subject
17
+ - dkim
18
+ - SPF
19
+ - charsets
20
+ - content-ids
21
+ - spam_report
22
+ - spam_score
23
+ - email
24
+
25
+ # URL that the sender will POST to
26
+ host: 'http://127.0.0.1:9292/inbound'
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ <title>Twilio SendGrid Incoming Parse</title>
4
+ </head>
5
+ <body>
6
+ <h1>You have successfuly launched the server!</h1>
7
+
8
+ Check out <a href="https://github.com/sendgrid/sendgrid-ruby/tree/HEAD/sendgrid/helpers/inbound">the documentation</a> on how to use this software to utilize the SendGrid Inbound Parse webhook.
9
+ </body>
10
+ </html>
@@ -0,0 +1,58 @@
1
+ --xYzZY
2
+ Content-Disposition: form-data; name="headers"
3
+
4
+ MIME-Version: 1.0
5
+ Received: by 0.0.0.0 with HTTP; Wed, 10 Aug 2016 18:10:13 -0700 (PDT)
6
+ From: Example User <test@example.com>
7
+ Date: Wed, 10 Aug 2016 18:10:13 -0700
8
+ Subject: Inbound Parse Test Data
9
+ To: inbound@inbound.example.com
10
+ Content-Type: multipart/alternative; boundary=001a113df448cad2d00539c16e89
11
+
12
+ --xYzZY
13
+ Content-Disposition: form-data; name="dkim"
14
+
15
+ {@sendgrid.com : pass}
16
+ --xYzZY
17
+ Content-Disposition: form-data; name="to"
18
+
19
+ inbound@inbound.example.com
20
+ --xYzZY
21
+ Content-Disposition: form-data; name="html"
22
+
23
+ <html><body><strong>Hello Twilio SendGrid!</body></html>
24
+
25
+ --xYzZY
26
+ Content-Disposition: form-data; name="from"
27
+
28
+ Example User <test@example.com>
29
+ --xYzZY
30
+ Content-Disposition: form-data; name="text"
31
+
32
+ Hello Twilio SendGrid!
33
+
34
+ --xYzZY
35
+ Content-Disposition: form-data; name="sender_ip"
36
+
37
+ 0.0.0.0
38
+ --xYzZY
39
+ Content-Disposition: form-data; name="envelope"
40
+
41
+ {"to":["inbound@inbound.example.com"],"from":"test@example.com"}
42
+ --xYzZY
43
+ Content-Disposition: form-data; name="attachments"
44
+
45
+ 0
46
+ --xYzZY
47
+ Content-Disposition: form-data; name="subject"
48
+
49
+ Testing non-raw
50
+ --xYzZY
51
+ Content-Disposition: form-data; name="charsets"
52
+
53
+ {"to":"UTF-8","html":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"UTF-8"}
54
+ --xYzZY
55
+ Content-Disposition: form-data; name="SPF"
56
+
57
+ pass
58
+ --xYzZY--