Search code examples
pythondjangoencodingutf-8attributeerror

'bytes' object has no attribute 'encode' in EmailMessage


I am trying to make an app in Django which accepts information from user and send a HTML template as pdf through an e-mail to the user. But I am getting this error 'bytes' object has no attribute 'encode'

Here is my view for the email

def email(request, serial_no):
    user = get_object_or_404(Student, pk=serial_no)
    # roll_no = {'roll': str(user['roll_no'])}
    html = render_to_string('card.html',
                            {'user': user})
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'filename={}'.format(user.roll_no + '.pdf')
    pdf = weasyprint.HTML(string=html, base_url='').write_pdf(
        stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
    to_emails = [str(user.roll_no) + '@gmail.com']
    subject = "Certificate from Nami Montana"
    email = EmailMessage(subject, body=pdf, from_email='SSC', to=to_emails)
    email.attach("{}".format(user.roll_no) + '.pdf', pdf, "application/pdf")
    email.content_subtype = "pdf"  # Main content is now text/html
    email.encoding = 'utf-8'
    email.send()
    return HttpResponseRedirect(reverse('id_card:submit'))

Here is the error

Traceback (most recent call last):
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Dell\Documents\GitHub\SSC-Website\id_card\views.py", line 49, in email
    email.send()
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\message.py", line 284, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\backends\console.py", line 34, in send_messages
    self.write_message(message)
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\backends\console.py", line 17, in write_message
    msg = message.message()
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\message.py", line 246, in message
    msg = SafeMIMEText(self.body, self.content_subtype, encoding)
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\message.py", line 159, in __init__
    MIMEText.__init__(self, _text, _subtype=_subtype, _charset=_charset)
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\email\mime\text.py", line 42, in __init__
    self.set_payload(_text, _charset)
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\message.py", line 167, in set_payload
    has_long_lines = any(
  File "C:\Users\Dell\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\mail\message.py", line 168, in <genexpr>
    len(line.encode()) > RFC5322_EMAIL_LINE_LENGTH_LIMIT
AttributeError: 'bytes' object has no attribute 'encode'

Thanks in advance


Solution

  • The problem is that you're sending a PDF file object as the message body:

    pdf = weasyprint.HTML(string=html, base_url='').write_pdf(
            stylesheets=[weasyprint.CSS(string='body { font-family: serif}')])
    email = EmailMessage(subject, body=pdf, from_email='SSC', to=to_emails)
    

    EmailMessage attempts to encode the body with the utf-8 codec, but the body is a PDF file object, which is bytes, and bytes doesn't provide an encode method only a decode method. The correct way to add a PDF to an email is to attach it as you've done later in your code. Now, if you want the email body to be the text of the PDF file, get the text in a str and pass it as the body kwarg.