diff options
| author | Julien (juc) Castiaux <juc@odoo.com> | 2019-03-01 11:04:23 +0000 |
|---|---|---|
| committer | Julien (juc) Castiaux <juc@odoo.com> | 2019-03-06 09:04:29 +0000 |
| commit | e0bd7b99327c917927ead86a4fa04acce6cddefe (patch) | |
| tree | 2f236b8cde475c870b4bfb8979d12f01991469ef | |
| parent | 645d9dc037d856d002ad19d360ea621acba3ec19 (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.py | 53 |
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 #------------------------------------------------------ |
