From b3b6f1209dcf0205f7b6b07567bb195d1c443b5a Mon Sep 17 00:00:00 2001 From: krissik Date: Fri, 27 Sep 2019 04:27:10 +0200 Subject: [PATCH] Fix image attachment (#188) * Fix image attachment * Fix code analysis * Update change log --- CHANGES.rst | 3 +++ src/collective/easyform/actions.py | 4 ++-- src/collective/easyform/tests/PloneLogo.png | Bin 0 -> 4339 bytes src/collective/easyform/tests/attachment.rst | 8 ++++---- src/collective/easyform/tests/testDocTests.py | 9 ++++++++- 5 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 src/collective/easyform/tests/PloneLogo.png diff --git a/CHANGES.rst b/CHANGES.rst index 200d2b45..b44fa4a0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -32,6 +32,9 @@ issues if those validators, or default values, were misconfigured in the first p - Put in tests to show recaptcha validation prevents submissions [djay] +- Fix UnicodeDecodeError while attaching an image to a mail #187 + [krissik] + 2.1.0 (2019-04-25) ------------------ diff --git a/src/collective/easyform/actions.py b/src/collective/easyform/actions.py index 29bbc2ca..4ee77316 100644 --- a/src/collective/easyform/actions.py +++ b/src/collective/easyform/actions.py @@ -464,14 +464,14 @@ def get_mail_text(self, fields, request, context): ctype = attachment[1] # encoding = attachment[2] content = attachment[3] - if not six.PY2 and isinstance(content, six.binary_type): - content = content.decode("utf-8") if ctype is None: ctype = "application/octet-stream" maintype, subtype = ctype.split("/", 1) if maintype == "text": + if not six.PY2 and isinstance(content, six.binary_type): + content = content.decode("utf-8") msg = MIMEText(content, _subtype=subtype) elif maintype == "image": msg = MIMEImage(content, _subtype=subtype) diff --git a/src/collective/easyform/tests/PloneLogo.png b/src/collective/easyform/tests/PloneLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..768e6ebc3588ebfd55c2e13da5f93f5df652cfe9 GIT binary patch literal 4339 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 literal 0 HcmV?d00001 diff --git a/src/collective/easyform/tests/attachment.rst b/src/collective/easyform/tests/attachment.rst index 833866f2..533a483e 100644 --- a/src/collective/easyform/tests/attachment.rst +++ b/src/collective/easyform/tests/attachment.rst @@ -75,7 +75,7 @@ Submit the form with an image attachment:: >>> browser.getControl('Your E-Mail Address').value = 'test@example.com' >>> browser.getControl('Subject').value = 'test' >>> browser.getControl('Comments').value = 'PFG rocks!' - >>> browser.getControl(name='form.widgets.attachment').add_file(BytesIO(b'image content'), 'image/gif', 'test.gif') + >>> browser.getControl(name='form.widgets.attachment').add_file(open(get_image_path(), 'rb'), 'image/png', 'test.png') >>> browser.getControl('Submit').click() >>> 'Thanks for your input.' in browser.contents @@ -84,8 +84,8 @@ Submit the form with an image attachment:: Make sure the attachment was included in the email message:: - >>> portal.MailHost.msg.get_payload()[1].get_payload(decode=True) - b'image content' + >>> b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xb4\x00\x00\x00/\x08\x06\x00\x00\x00Jl\xe0\xb2\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x10\xa8IDATx\x9c\xed\x9d{xT\xd5\xb5\xc0\x7f\xeb\x9c\t\t \xf8\xa0BQ\xd0\x86IxH}]\xad\xb6^\xad\x8f\xa2\xb4\x96\xaaU\xc1\x07>\x9a\x07\xc6\x8b\x8fj\xd5\xab\xb6\xda\xc6\xf7\xf5Q\xfba\xc5\x162\x93\x88\xd7\xf6r\xa3\xe2\x93\xab\xf7\x93[D[\xabT' in portal.MailHost.msg.get_payload()[1].get_payload(decode=True) + True Submit the form with an audio attachment:: @@ -163,7 +163,7 @@ Check saved data:: >>> browser.getLink('Saver').click() >>> "5 input(s) saved" in browser.contents True - >>> ".widgets.attachment/@@download/test.gif" in browser.contents + >>> ".widgets.attachment/@@download/test.png" in browser.contents True >>> ".widgets.attachment/@@download/test.mp3" in browser.contents True diff --git a/src/collective/easyform/tests/testDocTests.py b/src/collective/easyform/tests/testDocTests.py index 12f76719..91125f59 100644 --- a/src/collective/easyform/tests/testDocTests.py +++ b/src/collective/easyform/tests/testDocTests.py @@ -9,6 +9,7 @@ import six import transaction import unittest +import os optionflags = ( @@ -48,6 +49,11 @@ def get_browser(layer, auth=True): return browser +def get_image_path(): + dir_name = os.path.dirname(os.path.realpath(__file__)) + return '{0}/PloneLogo.png'.format(dir_name) + + def test_suite(): suite = unittest.TestSuite() suite.addTests( @@ -56,7 +62,8 @@ def test_suite(): doctest.DocFileSuite( f, optionflags=optionflags, - globs={"get_browser": get_browser}, + globs={"get_browser": get_browser, + "get_image_path": get_image_path}, checker=Py23DocChecker(), ), layer=FUNCTIONAL_TESTING,