summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/pixelated/adapter/model/mail.py31
-rw-r--r--service/test/unit/adapter/test_mail.py19
-rw-r--r--web-ui/app/js/tags/ui/tag_list.js1
-rw-r--r--web-ui/test/spec/tags/ui/tag_list.spec.js7
4 files changed, 48 insertions, 10 deletions
diff --git a/service/pixelated/adapter/model/mail.py b/service/pixelated/adapter/model/mail.py
index 618b980a..8e7b745c 100644
--- a/service/pixelated/adapter/model/mail.py
+++ b/service/pixelated/adapter/model/mail.py
@@ -239,22 +239,33 @@ class PixelatedMail(Mail):
content_type = self._parse_charset_header(part['headers'].get('Content-Type'))
try:
- decoding_map = {
- 'quoted-printable': lambda content, content_type: unicode(content.decode('quopri'), content_type),
- 'base64': lambda content, content_type: content.decode('base64').decode('utf-8'),
- '7bit': lambda content, content_type: content.encode(content_type),
- '8bit': lambda content, content_type: content.encode(content_type)
- }
- if encoding:
- return decoding_map[encoding](part['content'], content_type)
- else:
- return part['content']
+ decoding_func = self._decoding_function_for_encoding(encoding)
+ return self._decode_content_with_fallback(part['content'], decoding_func, content_type)
except Exception:
logger.error('Failed to decode mail part with:')
logger.error('Content-Transfer-Encoding: %s' % encoding)
logger.error('Content-Type: %s' % part['headers'].get('Content-Type'))
raise
+ def _decoding_function_for_encoding(self, encoding):
+ decoding_map = {
+ 'quoted-printable': lambda content, content_type: content.decode('quopri').decode(content_type),
+ 'base64': lambda content, content_type: content.decode('base64').decode('utf-8'),
+ '7bit': lambda content, content_type: content.encode(content_type),
+ '8bit': lambda content, content_type: content.encode(content_type)
+ }
+ if encoding in decoding_map:
+ return decoding_map[encoding]
+ else:
+ return decoding_map['8bit']
+
+ def _decode_content_with_fallback(self, content, decode_func, content_type):
+ try:
+ return decode_func(content, content_type)
+ # return content.encode(content_type)
+ except ValueError:
+ return content.encode('ascii', 'ignore')
+
@property
def alternatives(self):
return self.parts.get('alternatives')
diff --git a/service/test/unit/adapter/test_mail.py b/service/test/unit/adapter/test_mail.py
index d77816cd..1a9280ff 100644
--- a/service/test/unit/adapter/test_mail.py
+++ b/service/test/unit/adapter/test_mail.py
@@ -232,6 +232,25 @@ class TestPixelatedMail(unittest.TestCase):
self.assertEquals(u'H\xe4llo', mail.text_plain_body)
self.assertEquals(u'<p>H\xe4llo</p>', mail.html_body)
+ def test_broken_content_type_defaults_to_usascii(self):
+ plain_headers = {'Content-Type': 'I lie to you', 'Content-Transfer-Encoding': 'quoted-printable'}
+ html_headers = {'Content-Type': 'text/html;\ncharset=utf-8', 'Content-Transfer-Encoding': 'quoted-printable'}
+ parts = {'alternatives': [{'content': 'H=E4llo', 'headers': plain_headers}, {'content': '<p>H=C3=A4llo</p>', 'headers': html_headers}]}
+
+ mail = PixelatedMail.from_soledad(None, None, self._create_bdoc(raw='some raw body'), parts=parts, soledad_querier=None)
+
+ self.assertEquals(u'H=E4llo', mail.text_plain_body)
+
+ def test_broken_encoding_defaults_to_8bit(self):
+ plain_headers = {'Content-Type': 'text/plain;\ncharset=iso-8859-1', 'Content-Transfer-Encoding': 'I lie to you!'}
+ html_headers = {'Content-Type': 'text/html;\ncharset=utf-8', 'Content-Transfer-Encoding': 'quoted-printable'}
+ parts = {'alternatives': [{'content': 'H=E4llo', 'headers': plain_headers}, {'content': '<p>H=C3=A4llo</p>', 'headers': html_headers}]}
+
+ mail = PixelatedMail.from_soledad(None, None, self._create_bdoc(raw='some raw body'), parts=parts, soledad_querier=None)
+
+ self.assertEquals(u'H=E4llo', mail.text_plain_body)
+ self.assertEquals(u'<p>H\xe4llo</p>', mail.html_body)
+
def test_clean_line_breaks_on_address_headers(self):
many_recipients = 'One <one@mail.com>,\nTwo <two@mail.com>, Normal <normal@mail.com>,\nalone@mail.com'
headers = {'Cc': many_recipients,
diff --git a/web-ui/app/js/tags/ui/tag_list.js b/web-ui/app/js/tags/ui/tag_list.js
index a2172c6d..d6f6f76c 100644
--- a/web-ui/app/js/tags/ui/tag_list.js
+++ b/web-ui/app/js/tags/ui/tag_list.js
@@ -98,6 +98,7 @@ define(
this.after('initialize', function() {
this.on(document, events.tags.received, this.displayTags);
this.on(document, events.ui.tag.select, this.updateCurrentTag);
+ this.on(document, events.ui.tag.select, events.ui.mails.uncheckAll);
this.renderTagListTemplate();
});
}
diff --git a/web-ui/test/spec/tags/ui/tag_list.spec.js b/web-ui/test/spec/tags/ui/tag_list.spec.js
index f92f72af..e84c68aa 100644
--- a/web-ui/test/spec/tags/ui/tag_list.spec.js
+++ b/web-ui/test/spec/tags/ui/tag_list.spec.js
@@ -62,6 +62,13 @@ describeComponent('tags/ui/tag_list', function () {
expect(this.component.attr.currentTag).toEqual('amazing');
});
+ it('should uncheck all emails when a new tag is selected', function () {
+ var uncheckAllEvent = spyOnEvent(document, Pixelated.events.ui.mails.uncheckAll);
+ $(document).trigger(Pixelated.events.ui.tag.select, { tag: 'amazing'});
+
+ expect(uncheckAllEvent).toHaveBeenTriggeredOn(document);
+ });
+
it('resets the tag lists when loading tags', function () {
var tagList = [tag('tag1', 1, false), tag('tag2', 2, true), tag('tag3', 3, true)];
$(document).trigger(Pixelated.events.tags.received, {tags: tagList});