diff --git a/openerp/addons/base/tests/test_mail.py b/openerp/addons/base/tests/test_mail.py
index ec9877f895d..8186674b964 100644
--- a/openerp/addons/base/tests/test_mail.py
+++ b/openerp/addons/base/tests/test_mail.py
@@ -330,6 +330,13 @@ class TestCleaner(unittest.TestCase):
for ext in test_mail_examples.BUG_3_OUT:
self.assertNotIn(ext, new_html, 'html_email_cleaner did not removed invalid content')
+ def test_80_remove_classes(self):
+ new_html = html_email_clean(test_mail_examples.REMOVE_CLASS, remove=True)
+ for ext in test_mail_examples.REMOVE_CLASS_IN:
+ self.assertIn(ext, new_html, 'html_email_cleaner wrongly removed classes')
+ for ext in test_mail_examples.REMOVE_CLASS_OUT:
+ self.assertNotIn(ext, new_html, 'html_email_cleaner did not removed correctly unwanted classes')
+
def test_90_misc(self):
# False boolean for text must return empty string
new_html = html_email_clean(False)
diff --git a/openerp/addons/base/tests/test_mail_examples.py b/openerp/addons/base/tests/test_mail_examples.py
index 97a34c45e55..3342876bf73 100644
--- a/openerp/addons/base/tests/test_mail_examples.py
+++ b/openerp/addons/base/tests/test_mail_examples.py
@@ -91,12 +91,12 @@ OERP_WEBSITE_HTML_1 = """
OERP_WEBSITE_HTML_1_IN = [
'Manage your company most important asset: People',
- 'img class="img-rounded img-responsive" src="/website/static/src/img/china_thumb.jpg"',
+ 'src="/website/static/src/img/china_thumb.jpg"',
]
OERP_WEBSITE_HTML_1_OUT = [
'Break down information silos.',
'Keep track of the vacation days accrued by each employee',
- 'img class="img-rounded img-responsive" src="/website/static/src/img/deers_thumb.jpg',
+ 'src="/website/static/src/img/deers_thumb.jpg',
]
OERP_WEBSITE_HTML_2 = """
@@ -205,7 +205,7 @@ OERP_WEBSITE_HTML_2_IN = [
]
OERP_WEBSITE_HTML_2_OUT = [
'Make every employee feel more connected',
- 'img class="img-responsive shadow" src="/website/static/src/img/text_image.png',
+ 'src="/website/static/src/img/text_image.png',
]
TEXT_1 = """I contact you about our meeting tomorrow. Here is the schedule I propose:
@@ -1173,3 +1173,34 @@ BUG_3_IN = [
BUG_3_OUT = [
'New kanban view of documents'
]
+
+REMOVE_CLASS = """
+
+
Hello
+
I have just installed Odoo 9 and I've got the following error:
+
+
+
+
+
+
+
+
+
An error occured in a modal and I will send you back the html to try opening one on your end
+
+
+
+
+
+"""
+
+REMOVE_CLASS_IN = [
+ 'An error occured in a modal and I will send you back the html to try opening one on your end'
+]
+REMOVE_CLASS_OUT = [
+ ''
+]
\ No newline at end of file
diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py
index 5f82df93af9..2e44cfc7395 100644
--- a/openerp/tools/mail.py
+++ b/openerp/tools/mail.py
@@ -26,6 +26,7 @@ _logger = logging.getLogger(__name__)
tags_to_kill = ["script", "head", "meta", "title", "link", "style", "frame", "iframe", "base", "object", "embed"]
tags_to_remove = ['html', 'body']
+whitelist_classes = set(['WordSection1', 'MsoNormal', 'SkyDrivePlaceholder', 'oe_mail_expand', 'stopSpelling'])
# allow new semantic HTML5 tags
allowed_tags = clean.defs.tags | frozenset('article section header footer hgroup nav aside figure main'.split() + [etree.Comment])
@@ -292,6 +293,11 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
if expand_options is None:
expand_options = {}
+ whitelist_classes_local = whitelist_classes.copy()
+ if expand_options.get('oe_expand_container_class'):
+ whitelist_classes_local.add(expand_options.get('oe_expand_container_class'))
+ if expand_options.get('oe_expand_a_class'):
+ whitelist_classes_local.add(expand_options.get('oe_expand_a_class'))
if not html or not isinstance(html, basestring):
return html
@@ -336,6 +342,7 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
quoted = False
quote_begin = False
overlength = False
+ replace_class = False
overlength_section_id = None
overlength_section_count = 0
cur_char_nbr = 0
@@ -347,6 +354,17 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
# do not take into account multiple spaces that are displayed as max 1 space in html
node_text = ' '.join((node.text and node.text.strip(' \t\r\n') or '').split())
+ # remove unwanted classes from node
+ if node.get('class'):
+ sanitize_classes = []
+ for _class in node.get('class').split(' '):
+ if _class in whitelist_classes_local:
+ sanitize_classes.append(_class)
+ else:
+ sanitize_classes.append('cleaned_'+_class)
+ replace_class = True
+ node.set('class', ' '.join(sanitize_classes))
+
# root: try to tag the client used to write the html
if 'WordSection1' in node.get('class', '') or 'MsoNormal' in node.get('class', ''):
root.set('msoffice', '1')
@@ -448,7 +466,7 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
node_class = node.get('class', '') + ' oe_mail_cleaned'
node.set('class', node_class)
- if not overlength and not quote_begin and not quoted:
+ if not overlength and not quote_begin and not quoted and not replace_class:
return html
# html: \n that were tail of elements have been encapsulated into -> back to \n