Skip to content


Subversion checkout URL

You can clone with
Download ZIP


UnicodeDecodeError, pyramid_mailer 0.9, repoze.sendmail 3.2 #18

robottaway opened this Issue · 12 comments

8 participants


Hi I am trying to attach a pdf and when I do some sort of encoding issue pops up. I can send a csv file no problem it's only when I add the pdf (or another binary file like a gpg key) that this encoding issue comes up.

I saw issue 17 which seems similar to mine but that is fixed in the versions I am using right?

This is the code I am using, I've tried setting the disposition explicitly to 'attachment' as well as using the full file location for the file name.

   csv_attachment = Attachment("%s.csv" %, "text/csv", open(csv_loc, "rb"), 'attachment')
   pdf_attachment = Attachment("%s.pdf" %, "application/pdf", open(pdf_loc, "rb"), 'attachment')

    body = render('mail/report.mak', {'user':user, 'report':report}, request)
    message = Message(subject='Famoso Reporting - %s' %,
                sender='Famoso Admin <>',

Here is the traceback of the error:

Traceback (most recent call last):
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/waitress-0.8.1-py2.6.egg/waitress/", line 329, in service
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/waitress-0.8.1-py2.6.egg/waitress/", line 173, in service
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/waitress-0.8.1-py2.6.egg/waitress/", line 380, in execute
app_iter =, start_response)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/pyramid/", line 187, in call
response = self.handle_request(request)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/pyramid/", line 20, in excview_tween
response = handler(request)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/pyramid_tm-0.4-py2.6.egg/pyramid_tm/", line 102, in tm_tween
return response
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 96, in __exit_
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 89, in commit
return self.get().commit()
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 342, in commit
reraise(t, v, tb)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 333, in commit
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 473, in _commitResources
reraise(t, v, tb)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/transaction/", line 455, in _commitResources
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/repoze/sendmail/", line 70, in tpc_finish
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/repoze/sendmail/", line 53, in send
message = encode_message(message)
File "/Users/rottaway/PyEnvs/famoso_reports/lib/python2.6/site-packages/repoze/sendmail/", line 101, in encode_message
return message.as_string().encode('ascii')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb5 in position 1476: ordinal not in range(128)


What version are you using?


For pyramid_mailer 0.9, and repoze.sendmail is 3.2.

I just switched to pyramid_mailer 0.6 and the problem went away, the pdf attachments work.


repoze.sendmail expects you to pass attachments which handle
encoding properly. For instance, if you use email.mime.application.MIMEApplication
instead of a raw Attachment, your code works under repoze.sendmail 3.2::

pdf_attachment = MIMEApplication(open(pdf_loc, "rb").read(), 'pdf')


Thank you, I will give this a try I was going off of the documentation which sends a png or was it a jpg, but doesn't show anything of the type outline in your example. Also funny that it works just fine in 0.6 maybe this is a documentation issue?

@robottaway robottaway closed this
@tseaver tseaver reopened this

robottawaw is correct that the pyramid_mailer docs advise using
the pyeramid_mailer.message.Attachment class in this way. That
class needs to take into account how it interacts with the email package,
which wants attachments to be encoded (e.g., via base64).


Have same error after upgrading Pyramid to 1.3.2 (so now I have pyramid_mailer 0.9 and repoze.sendmail 3.2). Error appears only with attached binary file.

def test_multipart_encoding(self):
    from repoze.sendmail import encoding
    from pyramid_mailer.message import Message
    from pyramid_mailer.message import Attachment

    msg = Message(subject="testing",
    msg.attach(Attachment("test.gif", "image/gif", 
                          open("test.gif", "rb").read()))
    result = encoding.encode_message(msg.to_message())

repoze.sendmail expects you to pass attachments which handle encoding properly.

According to tseaver, pyramid_mailer should encode the attachemnt and add Content-Transfer-Encoding header.

I summarize my changes.

  • encode the attachments with base64 or quoted-printable
  • encode a text file forcibly because it might be included non-ascii characters
  • add the Content-Transfer-Encoding header
  • read an attached file with binary mode

I know one more issue about an attached filename encoding (e.g. rfc2231 However, I'm thinking that we firstly fix binary attachments with ascii filename, then fix a filename encoding issue as an another issue (it also might be fixed cleanup_message function in repoze.sendmail).


A note on workarounds for others experiencing this issue

If your code is like so:

mailer = get_mailer(request)
att = Attachment(filename, "application/pdf", data)
message = Message(subject="Subj", sender="email@address", ...)

you can get it to work by altering it like so:

mailer = get_mailer(request)
att = MIMEApplication(, 'pdf')
att.add_header('Content-Disposition', 'attachment', filename=filename)
message = Message(subject="Subj", sender="email@address", ...)

# Add this to ensure we get a multipart message - it will be removed later
message.attach(Attachment('foo.txt', 'text/plain', 'foo'))

msg = message.to_message()
msg.set_payload([p for p in msg.get_payload() if p.get_filename()!='foo.txt'] + [attachment])
mailer.direct_delivery.send(message.sender, message.send_to, msg)

Thank you for giving workarounds.

Do you consider about Content-Transfer-Encoding header? I think it should be add explicitly when the attachment is a binary file.

I don't know what is the best practice in pyramid_mailer. But, the pyramid_mailer document says as follows.

from pyramid_mailer.message import Attachment
from pyramid_mailer.message import Message

message = Message()

photo_data = open("photo.jpg", "rb").read()
attachment = Attachment("photo.jpg", "image/jpg", photo_data)


I think we should revise the documentation if adding some header information is appropriate way. Or, we should add some header information implicitly if developers prefer the way of current document.


I think it's reasonable to assume base64 for binary data, unless the user explicitly specifies some other encoding such as quopri.


From my humble experience, the documentation should be changed till pyramid_mailer can send binary attachments.

It might be nice to have somewhere to set the base64 header for the attachment and do the encoding by ourselves.

@t2y patch is the best I've seen for this problem. And after 3 months without any other suggestion. My +1 for a merge.

@mmerickel mmerickel closed this in d0ed443
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.