2

I am trying to send a python dict as a JSON file for an email attachment using the sendgrid package.

Here is the code :

from sendgrid import SendGridAPIClient
from sendgrid import Mail
from sendgrid import Email
from sendgrid import Attachment

final_data = {"user":{"email": "test@gmail.com", "username": "test1"}}
result = json.dumps(final_data)
print(f"Result type {type(result)}")
encoded = base64.b64encode(result.encode("utf-8"))
print(f"encoded : {encoded}")
attachment = Attachment(file_content=encoded, file_name="user.json", file_type="application/json")
message.add_attachment(attachment)
sg.send(message)

And the line sg.send(message) is throwing the error : Object of type bytes is not JSON serializable

I have seen so many SO questions about how to encode to base64, but i actually did and here is the whole trace of this code snippet :

Result type <class 'str'>
encoded : b'eyJ1c2VyIjogeyJsYXN0TmFtZSI6ICJCb2JvIiwgImZpcnN0TmFtZSI6ICJCb2JvIiwgImVtYWlsIjogImJvcmlzLmZhcmVsbEBnbWFpbC5jb20iLCAidGVsIjogIiIsICJiaXJ0aGRhdGUiOiAwLCAicGhvdG9VcmwiOiAiaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL2luZmVlbGliL2RvY3VtZW50cy91c2Vycy9qVHBBdGRBS1lCV2V2YWUwajJLVHBSalByeUMzL3Byb2ZpbGUvMGE0ZTQzYjEtMWQzZS00ODk0LWJjYWItNGFkYTFhZDY3ODFkLmpwZz9YLUdvb2ctQWxnb3JpdGhtPUdPT0c0LVJTQS1TSEEyNTYmWC1Hb29nLUNyZWRlbnRpYWw9ZmlyZWJhc2UtYWRtaW5zZGstbmU0emElNDBpbmZ0ZWFtLWkuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20lMkYyMDIzMDcwOSUyRmF1dG8lMkZzdG9yYWdlJTJGZ29vZzRfcmVxdWVzdCZYLUdvb2ctRGF0ZT0yMDIzMDcwOVQxMDQ2MDlaJlgtR29vZy1FeHBpcmVzPTYwNDgwMCZYLUdvb2ctU2lnbmVkSGVhZGVycz1ob3N0JlgtR29vZy1TaWduYXR1cmU9Mjk2MjY4MjY1MTA3NGMyN2VkMmY5MmY1YzBkYWM4N2JhYTIzODY0N2Q4NzFhYTk3ZTIyZmE3ZjE5MjcyNWEwN2ZiN2U4NzAxZGU4ZmJlYmIyOGZiMWVmZjdlMWY5MGQ3NzZmNTU3OTRiMTVlOTEwMzkyMTM0MmNlNzE4YzQ5ZWZjOTdlNjk1Njk3YTg0Nzk5OTQyODY4NDliMjcyYmZmMzdjM2I0MzE5ZWM1NmZlNDk2N2YzZDczM2Q5ZTMzZWMxZjJjOWFiZTUyYjA2OWJhZmU0MTA5OTMxMWFhYmQ4MTU2MzgyNDVmZWYzYjdhNzY5M2I2OGE3Njc3NzFhMjZkYWIzY2E1NGRkZDdkYTJlYTJlYTcyZjZlOGE5YmYzYjJiNTZjOWNiOTdmZTZhOTZiZjczYjI5ZTNiN2E5YTlmODI1ZDA3MTkxNWIwYTQ1ZWYwZjE1MmJmOTEyYzQxNmVlYThmOWEzZGIyNDg3ZTc4YzIxYTM3MGZiZmYxMzg4NDZhMTI3ZDk5NDk4NTQzZGIyYzA1ZjFmNGNmMjc4YTQ3MTg2MTM0ODczZTAxNzY5ZmU4YzliNjIxMmRmMTdiZjI1NDQ2Y2RkM2M2NjgyZjNmZWIyMThiMTZkNTNmZWU0YTU3ODhjOTAxMWRlNTA5NjExZjY5MjI1Yzk5NmUwNWRhNmUifX0='
ERROR:root:export_all_data: Object of type bytes is not JSON serializable

EDIT :

I have changed my code to use :

from sendgrid import FileContent
from sendgrid import FileName
from sendgrid import FileType
attachment = Attachment(file_content=FileContent(encoded), file_name=FileName("user.json"),
                                file_type=FileType("application/json"))

According to the documentation but it's still failing, unfortunately.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
Tom3652
  • 2,540
  • 3
  • 19
  • 45
  • Can you please mention what modules you have imported? So that we can know what is the return type of the add_attachment method! – Rahul Kumar Jha Jul 09 '23 at 10:56
  • Yes sure i have updated the question ! the `add_attachment` method returns nothing and the error occurs on the `send` method – Tom3652 Jul 09 '23 at 11:44

1 Answers1

1
ERROR:root:export_all_data: Object of type bytes is not JSON serializable

Looking at sendgrid-python / use cases / attachment, I see there is that the SendGrid API requires the base64-encoded attachment to be in a string format, not in bytes.
After calling base64.b64encode(result.encode("utf-8")), it will return a bytes object, which is not JSON serializable. Therefore, you need to decode the bytes to string before passing it to the FileContent().

And I do not see "decode()" anywhere in your question.

You can see that change in this updated code:
(but also illustrated in "Python Sendgrid send email with PDF attachment file")

from sendgrid import SendGridAPIClient
from sendgrid import Mail
from sendgrid.helpers.mail import Email, To, Content, Attachment, FileContent, FileName, FileType

import json
import base64

final_data = {"user":{"email": "test@gmail.com", "username": "test1"}}
result = json.dumps(final_data)
print(f"Result type {type(result)}")

# base64 encode the json string and decode the bytes to string
encoded = base64.b64encode(result.encode("utf-8")).decode()

print(f"encoded : {encoded}")

# Initialize a Mail object
email = Mail(
    from_email=Email('your-email@example.com'),
    to_emails=To('test@gmail.com'),
    subject='Subject',
    plain_text_content='Content',
)

# Attach the file
attachment = Attachment()
attachment.file_content = FileContent(encoded)
attachment.file_name = FileName("user.json")
attachment.file_type = FileType("application/json")
email.add_attachment(attachment)

# Use your SendGrid API key
sg = SendGridAPIClient('your_sendgrid_api_key')

# Send the email
response = sg.send(email)

Do replace 'your-email@example.com' and 'your_sendgrid_api_key' with your actual email and SendGrid API key.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thanks it's working fine with the `decode` ! I saw the documentation that was asking for bytes in `Attachment` for the `file_content` param, because at first i was not using `FileContent` – Tom3652 Jul 11 '23 at 18:17