Browse Source

Merge 692b5339df into f303cae18d

pull/404/merge
George Daramouskas 5 years ago
committed by GitHub
parent
commit
2177aeb5ae
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 80
      mail_embed_image/README.rst
  2. 4
      mail_embed_image/__init__.py
  3. 16
      mail_embed_image/__manifest__.py
  4. 4
      mail_embed_image/models/__init__.py
  5. 126
      mail_embed_image/models/ir_mail_server.py
  6. BIN
      mail_embed_image/static/description/icon.png
  7. 4
      mail_embed_image/tests/__init__.py
  8. 68
      mail_embed_image/tests/test_mail_embed_image.py

80
mail_embed_image/README.rst

@ -0,0 +1,80 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
================
mail_embed_image
================
This module was written to extend the functionality of ... to support ...
and allow you to ...
Installation
============
To install this module, you need to:
Follow the usual procedure for your version of Odoo.
Configuration
=============
To configure this module, you need to:
There are no configuration parameters for now
Usage
=====
When this module is installed all the emails that will be sent will be examined
and if they contain images with their src attribute pointing to a url, then
that will change to Content Id cid.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/205/10.0
Known issues / Roadmap
======================
* None so far.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/social/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback.
Credits
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* George Daramouskas <gdaramouskas@therp.nl>
Do not contact contributors directly about help with questions or problems concerning this addon, but use the `community mailing list <mailto:community@mail.odoo.com>`_ or the `appropriate specialized mailinglist <https://odoo-community.org/groups>`_ for help, and the bug tracker linked in `Bug Tracker`_ above for technical issues.
Maintainer
----------
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit https://odoo-community.org.

4
mail_embed_image/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

16
mail_embed_image/__manifest__.py

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Mail Embed Image",
"version": "10.0.1.0.0",
"author": "Therp BV,Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Social",
"summary": "Replace img.src's which start with http with inline cids",
"depends": [
'mail',
],
"installable": True,
"application": False,
}

4
mail_embed_image/models/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import ir_mail_server

126
mail_embed_image/models/ir_mail_server.py

@ -0,0 +1,126 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import uuid
from werkzeug.routing import Rule, Map
from odoo import models
from odoo.tools.image import image_resize_image
from odoo.addons.web.controllers.main import Binary
from odoo.modules import get_resource_path
from odoo.addons.base.ir.ir_mail_server import encode_header_param
from lxml.html.soupparser import fromstring
from lxml.etree import tostring
from base64 import b64encode, b64decode
from email.mime.image import MIMEImage
from email import Encoders
class IrMailServer(models.Model):
_inherit = 'ir.mail_server'
def build_email(
self,
email_from,
email_to,
subject,
body,
email_cc=None,
email_bcc=None,
reply_to=None,
attachments=None,
message_id=None,
references=None,
object_id=None,
subtype='plain',
headers=None,
body_alternative=None,
subtype_alternative='plain'):
result = super(IrMailServer, self).build_email(
email_from=email_from,
email_to=email_to,
subject=subject,
body=body,
email_cc=email_cc,
email_bcc=email_bcc,
reply_to=reply_to,
attachments=attachments,
message_id=message_id,
references=references,
object_id=object_id,
subtype=subtype,
headers=headers,
body_alternative=body_alternative,
subtype_alternative=subtype_alternative,
)
return self._build_email_replace_img_src(result, result)
def _build_email_replace_img_src(self, email, email_part):
""" Given a message, find it's img tags and if they
are URLs, replace them with cids.
:param email: The root email.message.Message, used for reference
:param email_part: The current part of email being examined
"""
if email_part.is_multipart():
for part in email_part.get_payload():
self._build_email_replace_img_src(email, part)
else:
if email_part.get_content_subtype() == 'html':
body = email_part.get_payload(decode=True)
root = fromstring(body)
for img in root.xpath(
"//img[starts-with(@src, '/web/image')]"):
base_url = self.env['ir.config_parameter'].get_param(
'web.base.url')
response = self._get_image(base_url, img.get('src'))
cid = uuid.uuid4().hex
filename_rfc2047 = encode_header_param(cid)
part = MIMEImage(response)
part.set_param('name', filename_rfc2047)
part.add_header(
'Content-Disposition',
'inline',
cid=cid,
filename=filename_rfc2047,
)
part.set_payload(response)
Encoders.encode_base64(part)
# attach the image into the email as attachment
email.attach(part)
img.set('src', 'cid:%s' % (cid))
email_part.set_payload(b64encode(tostring(root)))
return email
def _get_image(self, base_url, src):
""" This function emulates the operations of
odoo.addons.web.controllers.main.Binary.content_image() because
we cannot call this from here
Given an absolute url, return the raw image data.
"""
routes = Binary.content_image.routing['routes']
map_rules = Map([Rule(x) for x in routes])
urls = map_rules.bind(base_url)
endpoint, kwargs = urls.match(src)
status, headers, content = self.env['ir.http'].binary_content(
env=self.env, **kwargs)
height = int(kwargs.get('height', 0))
width = int(kwargs.get('width', 0))
if content and (height or width):
if height > 500:
height = 500
if width > 500:
width = 500
content = image_resize_image(
content,
(width or None, height or None),
filetype='PNG',
)
if content:
content = b64decode(content)
else:
path_placeholder = '/web/static/src/img/placeholder.png'
with open(get_resource_path(path_placeholder)) as f:
content = f.read()
else:
content = b64decode(content)
return content

BIN
mail_embed_image/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

4
mail_embed_image/tests/__init__.py

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import test_mail_embed_image

68
mail_embed_image/tests/test_mail_embed_image.py

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
from mock import patch
from requests import get
from base64 import b64encode
from lxml.html.soupparser import fromstring
from odoo.addons.base.ir.ir_mail_server import encode_header_param
class TestMailEmbedImage(TransactionCase):
post_install = True
at_install = False
@patch(
'odoo.fields.html_sanitize',
side_effect=lambda *args, **kwargs: args[0],
)
def test_mail_embed_image(self, html_sanitize):
""" The following are tested here:
1) Create an email with no image, send it.
2) Create an email with three images, one base64 content, one http
full url and one of the format `/web/image/.*`
We assert that nothing has changed on 1) and only the `/web/image/.*`
has changed in 2)
"""
model_mail_mail = self.env['mail.mail']
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
image_url = base_url + '/mail_embed_image/static/description/icon.png'
image = get(image_url).content
body1 = '<div>this is an email</div>'
email1 = model_mail_mail.create({
'body_html': body1,
'email_from': 'test@example.com',
'email_to': 'test@example.com',
})
email1.send()
self.assertEquals(email1.body_html, body1)
body2 = """
<div>
this is an email
<img src="base64: %s"></img>
<img src="%s"></img>
<img src="%s"></img>
</div>""" % (
b64encode(image),
image_url,
'/web/image/res.partner/1/image',
)
email2 = model_mail_mail.create({
'body_html': body2,
'email_from': 'test@example.com',
'email_to': 'test@example.com',
})
email2.send()
# TODO the below will not work, assert build_email called and return
# value (remove the tests above as well, they are foolish)
body2final = fromstring(email2.body_html)
self.assertEquals(len(body2final.xpath('//img')), 3)
srcs = [x.get('src') for x in body2final.xpath('//img')]
self.assertIn('base64:', srcs[0])
self.assertIn('http:', srcs[1])
self.assertIn('cid:', srcs[2])
cid = srcs[2][3:]
self.assertEquals(email2.attachment_ids.name, encode_header_param(cid))
Loading…
Cancel
Save