nylas 6.5.0 → 6.7.0
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 +115 -12
- data/lib/nylas/resources/folders.rb +5 -0
- data/lib/nylas/resources/messages.rb +1 -1
- data/lib/nylas/resources/webhooks.rb +1 -0
- data/lib/nylas/version.rb +1 -1
- metadata +3 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc90a16ef74fc2f47d6f35ada72d9cd80e3e842e08d9d5b1916a819ae36c0808
|
4
|
+
data.tar.gz: b2c8494899f1b2ff4620dfbcce0aeb52e037adfe97f1609bcaaf455bfb843745
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9cda94765c3957d6457071ac616dd12a3a807378773b566da0be82b39c5a89db370049f21744b91ed8f3a5abf211b6c75363f8df10f52d102007becfcd2a635
|
7
|
+
data.tar.gz: e50d00d31fdb2ae23058d146b38cc75a5a75f239ba19220b5c28280defe4624b4ab4d858ec3abd496555ab6b0f35033ac2c606ed2bc346572f0593df0cebb5cc
|
@@ -41,7 +41,8 @@ module Nylas
|
|
41
41
|
content_type = response.headers["content-type"].downcase
|
42
42
|
end
|
43
43
|
|
44
|
-
parsed_response = parse_json_evaluate_error(result.code.to_i, response.body, path, content_type
|
44
|
+
parsed_response = parse_json_evaluate_error(result.code.to_i, response.body, path, content_type,
|
45
|
+
response.headers)
|
45
46
|
# Include headers in the response
|
46
47
|
parsed_response[:headers] = response.headers unless parsed_response.nil?
|
47
48
|
parsed_response
|
@@ -103,6 +104,7 @@ module Nylas
|
|
103
104
|
is_multipart = !payload.nil? && (payload["multipart"] || payload[:multipart])
|
104
105
|
|
105
106
|
if !payload.nil? && !is_multipart
|
107
|
+
normalize_json_encodings!(payload)
|
106
108
|
payload = payload&.to_json
|
107
109
|
resulting_headers["Content-type"] = "application/json"
|
108
110
|
elsif is_multipart
|
@@ -149,7 +151,7 @@ module Nylas
|
|
149
151
|
# Handle multipart uploads
|
150
152
|
if payload.is_a?(Hash) && file_upload?(payload)
|
151
153
|
options[:multipart] = true
|
152
|
-
options[:body] = payload
|
154
|
+
options[:body] = prepare_multipart_payload(payload)
|
153
155
|
elsif payload
|
154
156
|
options[:body] = payload
|
155
157
|
end
|
@@ -176,9 +178,113 @@ module Nylas
|
|
176
178
|
def file_upload?(payload)
|
177
179
|
return false unless payload.is_a?(Hash)
|
178
180
|
|
179
|
-
|
181
|
+
# Check for traditional file uploads (File objects or objects that respond to :read)
|
182
|
+
has_file_objects = payload.values.any? do |value|
|
180
183
|
value.respond_to?(:read) || (value.is_a?(File) && !value.closed?)
|
181
184
|
end
|
185
|
+
|
186
|
+
return true if has_file_objects
|
187
|
+
|
188
|
+
# Check if payload was prepared by FileUtils.build_form_request for multipart uploads
|
189
|
+
# This handles binary content attachments that are strings with added singleton methods
|
190
|
+
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
|
+
|
193
|
+
# If we have both a "message" field and "file{N}" fields, this indicates
|
194
|
+
# the payload was prepared by FileUtils.build_form_request for multipart upload
|
195
|
+
has_message_field && has_attachment_fields
|
196
|
+
end
|
197
|
+
|
198
|
+
# Prepare multipart payload for HTTParty compatibility
|
199
|
+
# HTTParty requires all multipart fields to have compatible encodings
|
200
|
+
def prepare_multipart_payload(payload)
|
201
|
+
require "stringio"
|
202
|
+
|
203
|
+
modified_payload = payload.dup
|
204
|
+
|
205
|
+
# First, normalize all string encodings to prevent HTTParty encoding conflicts
|
206
|
+
normalize_multipart_encodings!(modified_payload)
|
207
|
+
|
208
|
+
# Handle binary content attachments (file0, file1, etc.) by converting them to enhanced StringIO
|
209
|
+
# HTTParty expects file uploads to be objects with full file-like interface
|
210
|
+
modified_payload.each do |key, value|
|
211
|
+
next unless key.is_a?(String) && key.match?(/^file\d+$/) && value.is_a?(String)
|
212
|
+
|
213
|
+
# Get the original value to check for singleton methods
|
214
|
+
original_value = payload[key]
|
215
|
+
|
216
|
+
# Create an enhanced StringIO object for HTTParty compatibility
|
217
|
+
string_io = create_file_like_stringio(value)
|
218
|
+
|
219
|
+
# Preserve filename and content_type if they exist as singleton methods
|
220
|
+
if original_value.respond_to?(:original_filename)
|
221
|
+
string_io.define_singleton_method(:original_filename) { original_value.original_filename }
|
222
|
+
end
|
223
|
+
|
224
|
+
if original_value.respond_to?(:content_type)
|
225
|
+
string_io.define_singleton_method(:content_type) { original_value.content_type }
|
226
|
+
end
|
227
|
+
|
228
|
+
modified_payload[key] = string_io
|
229
|
+
end
|
230
|
+
|
231
|
+
modified_payload
|
232
|
+
end
|
233
|
+
|
234
|
+
# Normalize string encodings in multipart payload to prevent HTTParty encoding conflicts
|
235
|
+
# This ensures all string fields use consistent ASCII-8BIT encoding for multipart compatibility
|
236
|
+
def normalize_multipart_encodings!(payload)
|
237
|
+
payload.each do |key, value|
|
238
|
+
next unless value.is_a?(String)
|
239
|
+
|
240
|
+
# Force all string values to ASCII-8BIT encoding for multipart compatibility
|
241
|
+
# HTTParty/multipart-post expects binary encoding for consistent concatenation
|
242
|
+
payload[key] = value.dup.force_encoding(Encoding::ASCII_8BIT)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Normalize JSON encodings for attachment content to ensure binary data is base64 encoded.
|
247
|
+
# This handles cases where users pass raw binary content directly instead of file objects.
|
248
|
+
def normalize_json_encodings!(payload)
|
249
|
+
return unless payload.is_a?(Hash)
|
250
|
+
|
251
|
+
# Handle attachment content encoding for JSON serialization
|
252
|
+
attachments = payload[:attachments] || payload["attachments"]
|
253
|
+
return unless attachments
|
254
|
+
|
255
|
+
attachments.each do |attachment|
|
256
|
+
content = attachment[:content] || attachment["content"]
|
257
|
+
next unless content.is_a?(String)
|
258
|
+
|
259
|
+
# If content appears to be binary (non-UTF-8), base64 encode it
|
260
|
+
next unless content.encoding == Encoding::ASCII_8BIT || !content.valid_encoding?
|
261
|
+
|
262
|
+
encoded_content = Base64.strict_encode64(content)
|
263
|
+
if attachment.key?(:content)
|
264
|
+
attachment[:content] = encoded_content
|
265
|
+
else
|
266
|
+
attachment["content"] = encoded_content
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Create a StringIO object that behaves more like a File for HTTParty compatibility
|
272
|
+
def create_file_like_stringio(content)
|
273
|
+
# Content is already normalized to ASCII-8BIT by normalize_multipart_encodings!
|
274
|
+
# Create StringIO with the normalized binary content
|
275
|
+
string_io = StringIO.new(content)
|
276
|
+
|
277
|
+
# Add methods that HTTParty/multipart-post might expect
|
278
|
+
string_io.define_singleton_method(:path) { nil }
|
279
|
+
string_io.define_singleton_method(:local_path) { nil }
|
280
|
+
string_io.define_singleton_method(:respond_to_missing?) do |method_name, include_private = false|
|
281
|
+
File.instance_methods.include?(method_name) || super(method_name, include_private)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Set binary mode for file-like behavior
|
285
|
+
string_io.binmode if string_io.respond_to?(:binmode)
|
286
|
+
|
287
|
+
string_io
|
182
288
|
end
|
183
289
|
|
184
290
|
def setup_http(path, timeout, headers, query, api_key)
|
@@ -206,37 +312,34 @@ module Nylas
|
|
206
312
|
end
|
207
313
|
|
208
314
|
# Parses the response from the Nylas API and evaluates for errors.
|
209
|
-
def parse_json_evaluate_error(http_code, response, path, content_type = nil)
|
315
|
+
def parse_json_evaluate_error(http_code, response, path, content_type = nil, headers = nil)
|
210
316
|
begin
|
211
317
|
response = parse_response(response) if content_type == "application/json"
|
212
318
|
rescue Nylas::JsonParseError
|
213
|
-
handle_failed_response(http_code, response, path)
|
319
|
+
handle_failed_response(http_code, response, path, headers)
|
214
320
|
raise
|
215
321
|
end
|
216
322
|
|
217
|
-
handle_failed_response(http_code, response, path)
|
323
|
+
handle_failed_response(http_code, response, path, headers)
|
218
324
|
response
|
219
325
|
end
|
220
326
|
|
221
327
|
# Handles failed responses from the Nylas API.
|
222
|
-
def handle_failed_response(http_code, response, path)
|
328
|
+
def handle_failed_response(http_code, response, path, headers = nil)
|
223
329
|
return if HTTP_SUCCESS_CODES.include?(http_code)
|
224
330
|
|
225
331
|
case response
|
226
332
|
when Hash
|
227
|
-
raise error_hash_to_exception(response, http_code, path)
|
333
|
+
raise error_hash_to_exception(response, http_code, path, headers)
|
228
334
|
else
|
229
335
|
raise NylasApiError.parse_error_response(response, http_code)
|
230
336
|
end
|
231
337
|
end
|
232
338
|
|
233
339
|
# Converts error hashes to exceptions.
|
234
|
-
def error_hash_to_exception(response, status_code, path)
|
340
|
+
def error_hash_to_exception(response, status_code, path, headers = nil)
|
235
341
|
return if !response || !response.key?(:error)
|
236
342
|
|
237
|
-
# Safely get headers without risking KeyError
|
238
|
-
headers = response.key?(:headers) ? response[:headers] : nil
|
239
|
-
|
240
343
|
if %W[#{api_uri}/v3/connect/token #{api_uri}/v3/connect/revoke].include?(path)
|
241
344
|
NylasOAuthError.new(response[:error], response[:error_description], response[:error_uri],
|
242
345
|
response[:error_code], status_code)
|
@@ -15,6 +15,11 @@ module Nylas
|
|
15
15
|
#
|
16
16
|
# @param identifier [String] Grant ID or email account to query.
|
17
17
|
# @param query_params [Hash, nil] Query params to pass to the request.
|
18
|
+
# Supported parameters include:
|
19
|
+
# - single_level: (Boolean) For Microsoft accounts only. If true, retrieves folders from
|
20
|
+
# a single-level hierarchy only. If false (default), retrieves folders across a
|
21
|
+
# multi-level hierarchy.
|
22
|
+
# - include_hidden_folders [Boolean] (Microsoft only) When true, includes hidden folders.
|
18
23
|
# @return [Array(Array(Hash), String, String)] The list of folders, API Request ID, and next cursor.
|
19
24
|
def list(identifier:, query_params: nil)
|
20
25
|
get_list(
|
data/lib/nylas/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nylas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nylas, Inc.
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: base64
|
@@ -295,7 +294,6 @@ files:
|
|
295
294
|
- lib/nylas/resources/webhooks.rb
|
296
295
|
- lib/nylas/utils/file_utils.rb
|
297
296
|
- lib/nylas/version.rb
|
298
|
-
homepage:
|
299
297
|
licenses:
|
300
298
|
- MIT
|
301
299
|
metadata:
|
@@ -305,7 +303,6 @@ metadata:
|
|
305
303
|
homepage_uri: https://www.nylas.com
|
306
304
|
source_code_uri: https://github.com/nylas/nylas-ruby
|
307
305
|
github_repo: https://github.com/nylas/nylas-ruby
|
308
|
-
post_install_message:
|
309
306
|
rdoc_options: []
|
310
307
|
require_paths:
|
311
308
|
- lib
|
@@ -320,8 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
320
317
|
- !ruby/object:Gem::Version
|
321
318
|
version: '0'
|
322
319
|
requirements: []
|
323
|
-
rubygems_version: 3.
|
324
|
-
signing_key:
|
320
|
+
rubygems_version: 3.7.2
|
325
321
|
specification_version: 4
|
326
322
|
summary: Gem for interacting with the Nylas API
|
327
323
|
test_files: []
|