Browse Source

fixup! fixup! fixup! fixup! fixup! fixup! [ADD] mail_embed_image module

pull/404/head
George Daramouskas 5 years ago
parent
commit
692b5339df
No known key found for this signature in database GPG Key ID: 5B4EF742F8CD859C
  1. 118
      mail_embed_image/models/ir_mail_server.py
  2. 5
      mail_embed_image/tests/test_mail_embed_image.py

118
mail_embed_image/models/ir_mail_server.py

@ -2,12 +2,15 @@
# Copyright 2019 Therp BV <https://therp.nl> # Copyright 2019 Therp BV <https://therp.nl>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import uuid import uuid
import requests
from werkzeug.routing import Rule, Map
from odoo import models 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 odoo.addons.base.ir.ir_mail_server import encode_header_param
from lxml.html.soupparser import fromstring from lxml.html.soupparser import fromstring
from lxml.etree import tostring from lxml.etree import tostring
from base64 import b64encode
from base64 import b64encode, b64decode
from email.mime.image import MIMEImage from email.mime.image import MIMEImage
from email import Encoders from email import Encoders
@ -33,10 +36,10 @@ class IrMailServer(models.Model):
body_alternative=None, body_alternative=None,
subtype_alternative='plain'): subtype_alternative='plain'):
result = super(IrMailServer, self).build_email( result = super(IrMailServer, self).build_email(
email_from,
email_to,
subject,
body,
email_from=email_from,
email_to=email_to,
subject=subject,
body=body,
email_cc=email_cc, email_cc=email_cc,
email_bcc=email_bcc, email_bcc=email_bcc,
reply_to=reply_to, reply_to=reply_to,
@ -49,40 +52,75 @@ class IrMailServer(models.Model):
body_alternative=body_alternative, body_alternative=body_alternative,
subtype_alternative=subtype_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.
def _build_email_replace_img_src(msg, attachments):
""" 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
:param msg: A email.message.Message
"""
if msg.is_multipart():
for part in msg.get_payload():
_build_email_replace_img_src(part, attachments)
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: else:
if msg.get_content_subtype() == 'html':
body = msg.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')
src = base_url + img.get('src')
response = requests.get(src)
cid = uuid.uuid4().hex
filename_rfc2047 = encode_header_param(cid)
part = MIMEImage(response.content)
part.set_param('name', filename_rfc2047)
part.add_header(
'Content-Disposition',
'inline',
cid=cid,
filename=filename_rfc2047,
)
part.set_payload(response.content)
Encoders.encode_base64(part)
result.attach(part)
img.set('src', 'cid:%s' % (cid))
msg.set_payload(b64encode(tostring(root)))
_build_email_replace_img_src(result, attachments)
return result
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

5
mail_embed_image/tests/test_mail_embed_image.py

@ -34,7 +34,7 @@ class TestMailEmbedImage(TransactionCase):
body1 = '<div>this is an email</div>' body1 = '<div>this is an email</div>'
email1 = model_mail_mail.create({ email1 = model_mail_mail.create({
'body_html': body1, 'body_html': body1,
'body': body1,
'email_from': 'test@example.com',
'email_to': 'test@example.com', 'email_to': 'test@example.com',
}) })
email1.send() email1.send()
@ -52,9 +52,12 @@ class TestMailEmbedImage(TransactionCase):
) )
email2 = model_mail_mail.create({ email2 = model_mail_mail.create({
'body_html': body2, 'body_html': body2,
'email_from': 'test@example.com',
'email_to': 'test@example.com', 'email_to': 'test@example.com',
}) })
email2.send() 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) body2final = fromstring(email2.body_html)
self.assertEquals(len(body2final.xpath('//img')), 3) self.assertEquals(len(body2final.xpath('//img')), 3)
srcs = [x.get('src') for x in body2final.xpath('//img')] srcs = [x.get('src') for x in body2final.xpath('//img')]

Loading…
Cancel
Save