nylas 6.7.0 → 6.7.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/lib/nylas/handler/http_client.rb +94 -19
- data/lib/nylas/resources/webhooks.rb +4 -5
- data/lib/nylas/utils/file_utils.rb +6 -3
- data/lib/nylas/version.rb +1 -1
- metadata +18 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa916629fd9482f57599bd8cb7887f69575cc12cffd4f2d3d0fa37c5cd163b70
|
|
4
|
+
data.tar.gz: 906042891eb1519df1ff287ae27104b5f871edcbb938e25cc23e65a1d71452a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f7203ab924ec04f7efda91875003a8ffa10a182800ae7f0ffa8fb1cb7ad01a5cb4403bf99d79d84e58514acd25b45e8446a5522f771b7bd110e1c17595d94c1
|
|
7
|
+
data.tar.gz: fb23ac5760b2ed22f253dba8316baf5542ca29f654b1ca5b92345d34918e138065051b207435a62c82d41cefdbb7d3f6ecec0df0eee8294c3471518cc54f3151
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "httparty"
|
|
4
4
|
require "net/http"
|
|
5
|
+
require "net/http/post/multipart"
|
|
5
6
|
|
|
6
7
|
require_relative "../errors"
|
|
7
8
|
require_relative "../version"
|
|
@@ -135,7 +136,9 @@ module Nylas
|
|
|
135
136
|
|
|
136
137
|
private
|
|
137
138
|
|
|
138
|
-
# Sends a request to the Nylas REST API using HTTParty.
|
|
139
|
+
# Sends a request to the Nylas REST API using HTTParty or Net::HTTP for multipart.
|
|
140
|
+
# Multipart requests use Net::HTTP::Post::Multipart (multipart-post gem) because
|
|
141
|
+
# HTTParty's multipart handling produces malformed requests that the Nylas API rejects.
|
|
139
142
|
#
|
|
140
143
|
# @param method [Symbol] HTTP method for the API call. Either :get, :post, :delete, or :patch.
|
|
141
144
|
# @param url [String] URL for the API call.
|
|
@@ -143,25 +146,16 @@ module Nylas
|
|
|
143
146
|
# @param payload [String, Hash] Body to send with the request.
|
|
144
147
|
# @param timeout [Hash] Timeout value to send with the request.
|
|
145
148
|
def httparty_execute(method:, url:, headers:, payload:, timeout:)
|
|
146
|
-
|
|
147
|
-
headers: headers,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if payload.is_a?(Hash) && file_upload?(payload)
|
|
153
|
-
options[:multipart] = true
|
|
154
|
-
options[:body] = prepare_multipart_payload(payload)
|
|
155
|
-
elsif payload
|
|
156
|
-
options[:body] = payload
|
|
149
|
+
if method == :post && payload.is_a?(Hash) && file_upload?(payload)
|
|
150
|
+
response = execute_multipart_request(url: url, headers: headers, payload: payload, timeout: timeout)
|
|
151
|
+
else
|
|
152
|
+
options = { headers: headers, timeout: timeout }
|
|
153
|
+
options[:body] = payload if payload
|
|
154
|
+
response = HTTParty.send(method, url, options)
|
|
157
155
|
end
|
|
158
156
|
|
|
159
|
-
response = HTTParty.send(method, url, options)
|
|
160
|
-
|
|
161
|
-
# Create a compatible response object that mimics RestClient::Response
|
|
162
157
|
result = create_response_wrapper(response)
|
|
163
158
|
|
|
164
|
-
# Call the block with the response in the same format as rest-client
|
|
165
159
|
if block_given?
|
|
166
160
|
yield response, nil, result
|
|
167
161
|
else
|
|
@@ -169,6 +163,77 @@ module Nylas
|
|
|
169
163
|
end
|
|
170
164
|
end
|
|
171
165
|
|
|
166
|
+
# Executes multipart POST using Net::HTTP::Post::Multipart (fixes issue #538).
|
|
167
|
+
# HTTParty's multipart produces malformed requests; multipart-post/UploadIO works correctly.
|
|
168
|
+
def execute_multipart_request(url:, headers:, payload:, timeout:)
|
|
169
|
+
uri = URI.parse(url)
|
|
170
|
+
params = build_multipart_params(payload)
|
|
171
|
+
|
|
172
|
+
req = Net::HTTP::Post::Multipart.new(uri.path, params)
|
|
173
|
+
headers.each { |key, value| req[key] = value }
|
|
174
|
+
|
|
175
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
176
|
+
http.use_ssl = (uri.scheme == "https")
|
|
177
|
+
http.read_timeout = timeout
|
|
178
|
+
http.open_timeout = timeout
|
|
179
|
+
|
|
180
|
+
response = http.request(req)
|
|
181
|
+
|
|
182
|
+
create_httparty_like_response(response)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Build params hash for Net::HTTP::Post::Multipart with UploadIO for file fields.
|
|
186
|
+
def build_multipart_params(payload)
|
|
187
|
+
params = {}
|
|
188
|
+
payload.each do |key, value|
|
|
189
|
+
params[key] = if key.is_a?(String) && key != "message" && file_like_value?(value)
|
|
190
|
+
value_to_upload_io(value)
|
|
191
|
+
else
|
|
192
|
+
value.to_s
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
params
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def file_like_value?(value)
|
|
199
|
+
return true if value.respond_to?(:read) && (value.is_a?(File) ? !value.closed? : true)
|
|
200
|
+
if value.is_a?(String) && (value.respond_to?(:original_filename) || value.respond_to?(:content_type))
|
|
201
|
+
return true
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
false
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Convert File, String, or StringIO to UploadIO for multipart-post.
|
|
208
|
+
def value_to_upload_io(value)
|
|
209
|
+
content_type = value.respond_to?(:content_type) ? value.content_type : "application/octet-stream"
|
|
210
|
+
filename = value.respond_to?(:original_filename) ? value.original_filename : "file.bin"
|
|
211
|
+
|
|
212
|
+
io = if value.respond_to?(:read) && value.respond_to?(:rewind)
|
|
213
|
+
value.rewind if value.respond_to?(:rewind)
|
|
214
|
+
value
|
|
215
|
+
else
|
|
216
|
+
require "stringio"
|
|
217
|
+
content = value.to_s
|
|
218
|
+
content = content.dup.force_encoding(Encoding::ASCII_8BIT) if content.is_a?(String)
|
|
219
|
+
StringIO.new(content)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
UploadIO.new(io, content_type, filename)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Create response object compatible with HTTParty::Response interface.
|
|
226
|
+
def create_httparty_like_response(net_http_response)
|
|
227
|
+
headers = net_http_response.to_hash
|
|
228
|
+
headers = headers.transform_values { |v| v.is_a?(Array) && v.one? ? v.first : v }
|
|
229
|
+
|
|
230
|
+
OpenStruct.new(
|
|
231
|
+
body: net_http_response.body,
|
|
232
|
+
code: net_http_response.code.to_i,
|
|
233
|
+
headers: headers
|
|
234
|
+
)
|
|
235
|
+
end
|
|
236
|
+
|
|
172
237
|
# Create a response wrapper that mimics RestClient::Response.code behavior
|
|
173
238
|
def create_response_wrapper(response)
|
|
174
239
|
OpenStruct.new(code: response.code)
|
|
@@ -188,10 +253,20 @@ module Nylas
|
|
|
188
253
|
# Check if payload was prepared by FileUtils.build_form_request for multipart uploads
|
|
189
254
|
# This handles binary content attachments that are strings with added singleton methods
|
|
190
255
|
has_message_field = payload.key?("message") && payload["message"].is_a?(String)
|
|
191
|
-
has_attachment_fields = payload.keys.any? { |key| key.is_a?(String) && key.match?(/^file\d+$/) }
|
|
192
256
|
|
|
193
|
-
#
|
|
194
|
-
#
|
|
257
|
+
# Check for attachment fields - these can have custom content_id values (not just "file{N}")
|
|
258
|
+
# FileUtils.build_form_request creates entries with string values that have singleton methods
|
|
259
|
+
# like original_filename and content_type defined on them
|
|
260
|
+
has_attachment_fields = payload.any? do |key, value|
|
|
261
|
+
next false unless key.is_a?(String) && key != "message"
|
|
262
|
+
|
|
263
|
+
# Check if the value is a string with attachment-like singleton methods
|
|
264
|
+
# (original_filename or content_type), which indicates it's a file content
|
|
265
|
+
value.is_a?(String) && (value.respond_to?(:original_filename) || value.respond_to?(:content_type))
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# If we have both a "message" field and attachment fields with file metadata,
|
|
269
|
+
# this indicates the payload was prepared by FileUtils.build_form_request
|
|
195
270
|
has_message_field && has_attachment_fields
|
|
196
271
|
end
|
|
197
272
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "cgi"
|
|
4
3
|
require_relative "resource"
|
|
5
4
|
require_relative "../handler/api_operations"
|
|
6
5
|
|
|
@@ -115,14 +114,14 @@ module Nylas
|
|
|
115
114
|
# @return [String] The challenge parameter
|
|
116
115
|
def self.extract_challenge_parameter(url)
|
|
117
116
|
url_object = URI.parse(url)
|
|
118
|
-
|
|
117
|
+
params = URI.decode_www_form(url_object.query || "")
|
|
118
|
+
challenge_pair = params.find { |k, _| k == "challenge" }
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
if challenge_parameter.nil? || challenge_parameter.empty? || challenge_parameter.first.nil?
|
|
120
|
+
if challenge_pair.nil? || challenge_pair.last.to_s.empty?
|
|
122
121
|
raise "Invalid URL or no challenge parameter found."
|
|
123
122
|
end
|
|
124
123
|
|
|
125
|
-
|
|
124
|
+
challenge_pair.last
|
|
126
125
|
end
|
|
127
126
|
end
|
|
128
127
|
end
|
|
@@ -28,12 +28,13 @@ module Nylas
|
|
|
28
28
|
|
|
29
29
|
attachments.each_with_index do |attachment, index|
|
|
30
30
|
file = attachment[:content] || attachment["content"]
|
|
31
|
+
file_path = attachment[:file_path] || attachment["file_path"]
|
|
31
32
|
if file.respond_to?(:closed?) && file.closed?
|
|
32
|
-
unless
|
|
33
|
+
unless file_path
|
|
33
34
|
raise ArgumentError, "The file at index #{index} is closed and no file_path was provided."
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
file = File.open(
|
|
37
|
+
file = File.open(file_path, "rb")
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
# Setting original filename and content type if available. See rest-client#lib/restclient/payload.rb
|
|
@@ -87,7 +88,9 @@ module Nylas
|
|
|
87
88
|
|
|
88
89
|
# Use form data only if the attachment size is greater than 3mb
|
|
89
90
|
attachments = payload[:attachments]
|
|
90
|
-
|
|
91
|
+
# Support both string and symbol keys for attachment size to handle
|
|
92
|
+
# user-provided hashes that may use either key type
|
|
93
|
+
attachment_size = attachments&.sum { |attachment| attachment[:size] || attachment["size"] || 0 } || 0
|
|
91
94
|
|
|
92
95
|
# Handle the attachment encoding depending on the size
|
|
93
96
|
if attachment_size >= FORM_DATA_ATTACHMENT_SIZE
|
data/lib/nylas/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nylas
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.7.
|
|
4
|
+
version: 6.7.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nylas, Inc.
|
|
@@ -57,6 +57,20 @@ dependencies:
|
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
59
|
version: 3.5.1
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: multipart-post
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - "~>"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '2.0'
|
|
67
|
+
type: :runtime
|
|
68
|
+
prerelease: false
|
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - "~>"
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '2.0'
|
|
60
74
|
- !ruby/object:Gem::Dependency
|
|
61
75
|
name: ostruct
|
|
62
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -139,14 +153,14 @@ dependencies:
|
|
|
139
153
|
requirements:
|
|
140
154
|
- - "~>"
|
|
141
155
|
- !ruby/object:Gem::Version
|
|
142
|
-
version: '
|
|
156
|
+
version: '3.5'
|
|
143
157
|
type: :development
|
|
144
158
|
prerelease: false
|
|
145
159
|
version_requirements: !ruby/object:Gem::Requirement
|
|
146
160
|
requirements:
|
|
147
161
|
- - "~>"
|
|
148
162
|
- !ruby/object:Gem::Version
|
|
149
|
-
version: '
|
|
163
|
+
version: '3.5'
|
|
150
164
|
- !ruby/object:Gem::Dependency
|
|
151
165
|
name: rubocop-capybara
|
|
152
166
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -317,7 +331,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
317
331
|
- !ruby/object:Gem::Version
|
|
318
332
|
version: '0'
|
|
319
333
|
requirements: []
|
|
320
|
-
rubygems_version:
|
|
334
|
+
rubygems_version: 4.0.3
|
|
321
335
|
specification_version: 4
|
|
322
336
|
summary: Gem for interacting with the Nylas API
|
|
323
337
|
test_files: []
|