summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien (juc) Castiaux <juc@odoo.com>2019-03-01 11:04:23 +0000
committerJulien (juc) Castiaux <juc@odoo.com>2019-03-06 09:04:29 +0000
commite0bd7b99327c917927ead86a4fa04acce6cddefe (patch)
tree2f236b8cde475c870b4bfb8979d12f01991469ef
parent645d9dc037d856d002ad19d360ea621acba3ec19 (diff)
[FIX] mass_mailing: inline image not supported
Inline (base64) embedded images are not supported by most mail clients (gmail on top of them), this fix save those images as attachments and replace the src tag with the url of the generated image so the image correctly renders. opw-1929940 closes odoo/odoo#31532 Signed-off-by: Julien Castiaux <Julien00859@users.noreply.github.com>
-rw-r--r--addons/mass_mailing/models/mass_mailing.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py
index 36643c35c8f..d8aaf7ae682 100644
--- a/addons/mass_mailing/models/mass_mailing.py
+++ b/addons/mass_mailing/models/mass_mailing.py
@@ -4,10 +4,12 @@
import hashlib
import hmac
import logging
+import lxml
import random
import re
import threading
from ast import literal_eval
+from base64 import b64encode
from odoo import api, fields, models, tools, _, SUPERUSER_ID
from odoo.exceptions import UserError
@@ -26,6 +28,10 @@ MASS_MAILING_BUSINESS_MODELS = [
]
EMAIL_PATTERN = '([^ ,;<@]+@[^> ,;]+)'
+# Syntax of the data URL Scheme: https://tools.ietf.org/html/rfc2397#section-3
+# Used to find inline images
+image_re = re.compile(r"data:(image/[A-Za-z]+);base64,(.*)")
+
class MassMailingTag(models.Model):
"""Model of categories of mass mailing, i.e. marketing, newsletter, ... """
@@ -661,6 +667,53 @@ class MassMailing(models.Model):
if len(record_lists) > 0:
record.sudo().message_post(body=_(message % ', '.join(str(list.name) for list in record_lists.mapped('list_id'))))
+ @api.model
+ def create(self, values):
+ if values.get('body_html'):
+ values['body_html'] = self._convert_inline_images_to_urls(values['body_html'])
+ return super(MassMailing, self).create(values)
+
+ def write(self, values):
+ if values.get('body_html'):
+ values['body_html'] = self._convert_inline_images_to_urls(values['body_html'])
+ return super(MassMailing, self).write(values)
+
+ def _convert_inline_images_to_urls(self, body_html):
+ """
+ Find inline base64 encoded images, make an attachement out of
+ them and replace the inline image with an url to the attachement.
+ """
+
+ def _image_to_url(b64image: bytes):
+ """Store an image in an attachement and returns an url"""
+ attachment = self.env['ir.attachment'].create({
+ 'name': "cropped_image",
+ 'datas': b64image,
+ 'datas_fname': "cropped_image_mailing_{}".format(self.id),
+ 'type': 'binary',})
+
+ attachment.generate_access_token()
+
+ return '/web/image/%s?access_token=%s' % (
+ attachment.id, attachment.access_token)
+
+
+ modified = False
+ root = lxml.html.fromstring(body_html)
+ for node in root.iter('img'):
+ match = image_re.match(node.attrib.get('src', ''))
+ if match:
+ mime = match.group(1) # unsed
+ image = match.group(2).encode() # base64 image as bytes
+
+ node.attrib['src'] = _image_to_url(image)
+ modified = True
+
+ if modified:
+ return lxml.html.tostring(root)
+
+ return body_html
+
#------------------------------------------------------
# Views & Actions
#------------------------------------------------------