Skip to content

Instantly share code, notes, and snippets.

@nitinbhojwani
Created May 4, 2016 18:33
Show Gist options
  • Save nitinbhojwani/a5f9bab74185b04ad6e73e37a970ad37 to your computer and use it in GitHub Desktop.
Save nitinbhojwani/a5f9bab74185b04ad6e73e37a970ad37 to your computer and use it in GitHub Desktop.
Django - Send a Mail with Attachment File like CSV
# Import EmailMessage class - https://docs.djangoproject.com/en/1.9/topics/email/#django.core.mail.EmailMessage
from django.core.mail import EmailMessage
email = EmailMessage('... Subject ...', '... Body ...', 'from-email',
['to-email-1', 'to-email-2'], ['bcc-email-1', 'bcc-email-2'])
# now let's create a csv file dynamically
import csv, StringIO
attachment_csv_file = StringIO.StringIO()
writer = csv.writer(attachment_csv_file)
labels = ['name', 'city', 'email']
writer.writerow(labels)
rows = [['Nitin', 'Bengaluru', 'nitinbhojwani1993@gmail.com'], ['X', 'Y', 'Z']]
for row in rows:
writer.writerow(row)
email.attach('attachment_file_name.csv', attachment_csv_file.getvalue(), 'text/csv')
email.send(fail_silently=False)
@nateshmbhat
Copy link

Thanks. This was helpful

@undernewmanagement
Copy link

for python 3 you will want to have from io import StringIO

@Ankit-Kr-Singh
Copy link

I am using the same code but python 3.6 gives the following error. FYI I am using io.StringIO().

File "/Users/user/miniconda3/envs/project36/lib/python3.6/code.py", line 91, in runcode
exec(code, self.locals)
File "", line 1, in
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/django/core/mail/message.py", line 342, in send
return self.get_connection(fail_silently).send_messages([self])
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/sgbackend/mail.py", line 63, in send_messages
mail = self._build_sg_mail(email)
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/sgbackend/mail.py", line 142, in _build_sg_mail
base64_attachment = base64.b64encode(attachment[1])
File "/Users/user/miniconda3/envs/projec36/lib/python3.6/base64.py", line 58, in b64encode
encoded = binascii.b2a_base64(s, newline=False)
TypeError: a bytes-like object is required, not 'str'

@neara
Copy link

neara commented Jun 4, 2019

I am using the same code but python 3.6 gives the following error. FYI I am using io.StringIO().

File "/Users/user/miniconda3/envs/project36/lib/python3.6/code.py", line 91, in runcode
exec(code, self.locals)
File "", line 1, in
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/django/core/mail/message.py", line 342, in send
return self.get_connection(fail_silently).send_messages([self])
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/sgbackend/mail.py", line 63, in send_messages
mail = self._build_sg_mail(email)
File "/Users/user/miniconda3/envs/project36/lib/python3.6/site-packages/sgbackend/mail.py", line 142, in _build_sg_mail
base64_attachment = base64.b64encode(attachment[1])
File "/Users/user/miniconda3/envs/projec36/lib/python3.6/base64.py", line 58, in b64encode
encoded = binascii.b2a_base64(s, newline=False)
TypeError: a bytes-like object is required, not 'str'

I've been having same issue too. Python 3.6 and 3.7. Still looking for a solution.

@Ankit-Kr-Singh
Copy link

Ankit-Kr-Singh commented Jun 4, 2019

@neara The issue is with Sendgrid.

Please find the solution on this link. https://github.com/elbuo8/sendgrid-django/pull/70/files

Or you can make changes by yourself. Goto /Users/user-name/miniconda/env/env/lib/python3.6/site-packages/sgbackend/mail.py and make the changes below.

Replace line 146 with the below:

           if type(attachment[1]) == str:

                attachment_object = attachment[1].encode()

           else:

                attachment_object = attachment[1]

           base64_attachment = base64.b64encode(attachment_object)

This will fix the issue with attaching text/* files to mail. Thanks

@neara
Copy link

neara commented Jun 4, 2019

@Ankit-Kr-Singh I found that fallowing works:

Changing this line:

email.attach('attachment_file_name.csv', attachment_csv_file.getvalue(), 'text/csv')

To this:

email.attach('attachment_file_name.csv', attachment_csv_file.getvalue().encode(), 'application/octet-stream')

As an additional workout, until the django sendgrid package will be fixed.

@Ankit-Kr-Singh
Copy link

Cool. I will try that. Thanks!!

@siddharth-cm
Copy link

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment