nylas / nylas/nylas-python

drafts.create() fails with "only JSON and multipart supported" error since v6.13.1

Đang mở
#455 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

bug
Ngôn ngữ chính
Python
Star
109
Fork
85
Merge trung bình
1 ngày 21 giờ
Pull request đã merge (30 ngày)
1

Mô tả

Describe the bug

Draft creation fails with NylasApiError: only JSON and multipart supported when using the Nylas Python SDK v6.13.1+. The Nylas API returns
a 400 error rejecting the draft creation request, even though the request appears to be properly formatted JSON.

Root Cause:

In v6.13.1 (commit d226ff113a62, PR #442), the HTTP client was changed to manually serialize JSON using json.dumps(request_body,
ensure_ascii=False) and pass it via the data= parameter instead of using the json= parameter in requests.request(). While this fixed UTF-8
encoding for multipart requests, it appears to have broken JSON-only requests for draft creation.

The issue is that when using data=json_string instead of json=dict, the requests library doesn't automatically set the correct
Content-Type header, or the manually added application/json; charset=utf-8 header is not being accepted by the Nylas API for draft
creation.

To Reproduce
from nylas import Client                                                                                                                  
 from nylas.models.drafts import CreateDraftRequest                                                                                        
                                                                                                                                           
 # Initialize client                                                                                                                       
 nylas = Client(api_key="your_api_key", api_uri="https://api.us.nylas.com")                                                                
                                                                                                                                           
 # Attempt to create a draft                                                                                                               
 draft_request = CreateDraftRequest(                                                                                                       
     to=[{"email": "recipient@example.com"}],                                                                                              
     subject="Test Subject",                                                                                                               
     body="Test body content"                                                                                                              
 )                                                                                                                                         
                                                                                                                                           
 try:                                                                                                                                      
     # This will fail with "only JSON and multipart supported"                                                                             
     response = nylas.drafts.create(                                                                                                       
         grant_id="your_grant_id",                                                                                                         
         request_body=draft_request                                                                                                        
     )                                                                                                                                     
 except Exception as e:                                                                                                                    
     print(f"Error: {e}")                                                                                                                  
     # Output: NylasApiError: only JSON and multipart supported                   
Expected behavior

The draft should be created successfully without errors. The Nylas API should accept the JSON request and return the created draft object.

Workaround:

Bypass the SDK's drafts.create() method and use requests directly with the json= parameter:

import requests                                                                                                                           
from nylas.models.response import Response                                                                                                
from nylas.models.drafts import Draft                                                                                                     
                                                                                                                                          
# Get API credentials from the SDK client                                                                                                 
api_server = nylas.drafts._http_client.api_server                                                                                         
api_key = nylas.drafts._http_client.api_key                                                                                               
                                                                                                                                          
url = f"{api_server}/v3/grants/{grant_id}/drafts"                                                                                         
headers = {                                                                                                                               
    "Authorization": f"Bearer {api_key}",                                                                                                 
    "X-Nylas-API-Wrapper": "python",                                                                                                      
}                                                                                                                                         
                                                                                                                                          
# Use requests directly with json= parameter                                                                                              
http_response = requests.post(url, headers=headers, json=draft_request_dict, timeout=30)                                                  
                                                                                                                                          
if http_response.status_code >= 400:                                                                                                      
    raise Exception(f"Draft creation failed: {http_response.json()}")                                                                     
                                                                                                                                          
draft_data = http_response.json()                                                                                                         
response = Response.from_dict(draft_data, Draft, http_response.headers)                            

This workaround succeeds because requests.post() with json=dict properly handles Content-Type headers.

SDK Version:
  • Broken: v6.13.1 and later (including v6.13.1, v6.14.0, v6.14.1, v6.14.2)
  • Last working: v6.13.0 and earlier
Additional context

The breaking change was introduced in commit d226ff113a62 (PR #442) which modified nylas/handler/http_client.py:

  • Changed from: requests.request(..., json=request_body, data=data)
  • Changed to: requests.request(..., data=json_data or data) where json_data = json.dumps(request_body, ensure_ascii=False)
  • Changed Content-Type header from application/json to application/json; charset=utf-8

While PR #442 successfully fixed UTF-8 encoding issues for multipart requests with large attachments, it appears to have broken standard
JSON requests for draft creation. The requests library handles the json= parameter differently than data= with a pre-serialized JSON
string, particularly regarding header management.

Suggested Fix:

Consider using json= parameter for JSON-only requests and data= with manual serialization only for multipart/form-data requests where
UTF-8 encoding is needed.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Đọc nylas/handler/http_client.py và đường dẫn yêu cầu được drafts.create() sử dụng, tập trung vào thay đổi từ tham số json= sang dữ liệu được tuần tự hóa thủ công. Chạy bản tái hiện việc tạo bản nháp được cung cấp và xác minh rằng các yêu cầu bản nháp JSON thành công, đồng thời hành vi multipart được PR #442 đề cập vẫn nguyên vẹn.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
api
Loại issue
Lỗi
Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
48/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.