I'm using this library with my Django(1.9.3) app. It works in all cases except the one with attachments where is raises 400 bad request.
Here's my code which creates the attachment:
import csv
from io import StringIO
import sendgrid
from sendgrid.helpers.mail import *
from django.conf import settings
def _send_email(to, subject, body_html, from_email, body_text='', cc=[], bcc=[], **kwargs):
sg = sendgrid.SendGridAPIClient(apikey=settings.SENDGRID_API_KEY)
from_email = Email(from_email)
personalization = Personalization()
# Add recepients
if isinstance(to, (list, tuple)):
for i in to:
personalization.add_to(Email(i))
message = Mail(from_email, subject, Email(to[0]), Content('text/html', body_html))
else:
personalization.add_to(Email(to))
message = Mail(from_email, subject, Email(to), Content('text/html', body_html))
# Add CCs if available
if cc:
if isinstance(cc, (list, tuple)):
for i in cc:
personalization.add_cc(Email(i))
else:
personalization.add_cc(Email(cc))
# Add BCCs if available
if bcc:
if isinstance(bcc, (list, tuple)):
for i in bcc:
personalization.add_bcc(Email(i))
else:
personalization.add_bcc(Email(bcc))
message.add_personalization(personalization)
# Add attachments
if kwargs.get('attachments'):
if isinstance(kwargs['attachments'], (list, tuple)):
for attachment in kwargs['attachments']:
message.add_attachment(attachment)
else:
message.add_attachment(kwargs['attachments'])
message.set_reply_to(from_email)
print(message.get())
sg.client.mail.send.post(request_body=message.get())
csvfile = StringIO()
csvwriter = csv.writer(csvfile)
csvwriter.writerow(['hello', 'world'])
attachment = Attachment()
attachment.set_content(csvfile.getvalue())
attachment.set_type('text/csv')
attachment.set_filename('request.csv')
attachment.set_disposition('attachment')
attachment.set_content_id('request')
_send_email(
'some_address@some_host.com',
'New Request',
'foo bar',
'another_address@another_host.com',
attachments=attachment
)
This is probably not a bug in the library but I'm doing something wrong here. Please help me with this.
Hello @debugger22,
attachment.set_content() expects a base64 value.
Please see: https://docs.python.org/3/library/base64.html#base64.b64encode
Thanks!
Thanks for the reply @thinkingserious!
In [9]: csvfile.getvalue()
Out[9]: 'hello,world\r\n'
In [10]: bytearray(csvfile.getvalue(), 'utf-8')
Out[10]: bytearray(b'hello,world\r\n')
In [11]: base64.b64encode(bytearray(csvfile.getvalue(), 'utf-8'))
Out[11]: b'aGVsbG8sd29ybGQNCg=='
After doing this, I am getting
TypeError: b'aGVsbG8sd29ybGQNCg==' is not JSON serializable
base64.b64encode(csvfile.getvalue().encode()).decode() works great. Thanks!
Thanks for sharing the solution @debugger22!
@debugger22,
I just noticed another issue in the code. It looks like you are adding a new personalization object when you add a cc or bcc.
The Mail constructor creates a personalization object for you. Here is an example of how to add to it.
Most helpful comment
base64.b64encode(csvfile.getvalue().encode()).decode()works great. Thanks!