summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorThibault Delavallée <tde@openerp.com>2014-03-04 12:29:57 +0100
committerThibault Delavallée <tde@openerp.com>2014-03-04 12:29:57 +0100
commitdb2bdee34349f5ceef06cbdde247c66fd001c18a (patch)
treebdc7f454c50030c407ead8ef066fb89939218ee5 /addons
parente78a3b18cc6c049a712d594ab70287c486447f0a (diff)
parentd417da6c1a64c6c51aa2c734e31e1360ad4f434e (diff)
MERGE] [FIX] email_template: fix relative -> absolute url conversion
Local URLs are converted into absolute URLs, notably because when using the email designer, images are added using local URLs. Previously to this fix the template was analyzed to find local URLs and make them absolute. However this causes 2 issues : - mako-based URLs are broken because a scheme is added before the mako that generated the image src - when changing the base url, the templates are not updated The URLs are now converted dynamically when generating the content of the html. This is done by passing a new parameter that enable the post processing of the generated content. Also fixed double body generation when using templates; fields parameter was not propagated correctly. bzr revid: tde@openerp.com-20140304112957-l9b10gyjqphs5fgc
Diffstat (limited to 'addons')
-rw-r--r--addons/email_template/email_template.py61
-rw-r--r--addons/email_template/wizard/mail_compose_message.py19
-rw-r--r--addons/mail/wizard/mail_compose_message.py10
-rw-r--r--addons/website_mail/models/email_template.py52
4 files changed, 73 insertions, 69 deletions
diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py
index 0b5945c1f0b..afcda2b6efd 100644
--- a/addons/email_template/email_template.py
+++ b/addons/email_template/email_template.py
@@ -24,6 +24,8 @@ import base64
import datetime
import dateutil.relativedelta as relativedelta
import logging
+import lxml
+import urlparse
import openerp
from openerp import SUPERUSER_ID
@@ -70,6 +72,7 @@ try:
except ImportError:
_logger.warning("jinja2 not available, templating features will not work!")
+
class email_template(osv.osv):
"Templates for sending email"
_name = "email.template"
@@ -82,7 +85,48 @@ class email_template(osv.osv):
res['model_id'] = self.pool['ir.model'].search(cr, uid, [('model', '=', res.pop('model'))], context=context)[0]
return res
- def render_template_batch(self, cr, uid, template, model, res_ids, context=None):
+ def _replace_local_links(self, cr, uid, html, context=None):
+ """ Post-processing of html content to replace local links to absolute
+ links, using web.base.url as base url. """
+ if not html:
+ return html
+
+ # form a tree
+ root = lxml.html.fromstring(html)
+ if not len(root) and root.text is None and root.tail is None:
+ html = '<div>%s</div>' % html
+ root = lxml.html.fromstring(html)
+
+ base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
+ (base_scheme, base_netloc, bpath, bparams, bquery, bfragment) = urlparse.urlparse(base_url)
+
+ def _process_link(url):
+ new_url = url
+ (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
+ if not scheme and not netloc:
+ new_url = urlparse.urlunparse((base_scheme, base_netloc, path, params, query, fragment))
+ return new_url
+
+ # check all nodes, replace :
+ # - img src -> check URL
+ # - a href -> check URL
+ for node in root.iter():
+ if node.tag == 'a':
+ node.set('href', _process_link(node.get('href')))
+ elif node.tag == 'img' and not node.get('src', 'data').startswith('data'):
+ node.set('src', _process_link(node.get('src')))
+
+ html = lxml.html.tostring(root, pretty_print=False, method='html')
+ # this is ugly, but lxml/etree tostring want to put everything in a 'div' that breaks the editor -> remove that
+ if html.startswith('<div>') and html.endswith('</div>'):
+ html = html[5:-6]
+ return html
+
+ def render_post_process(self, cr, uid, html, context=None):
+ html = self._replace_local_links(cr, uid, html, context=context)
+ return html
+
+ def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False):
"""Render the given template text, replace mako expressions ``${expr}``
with the result of evaluating these expressions with
an evaluation context containing:
@@ -125,6 +169,10 @@ class email_template(osv.osv):
if render_result == u"False":
render_result = u""
results[res_id] = render_result
+
+ if post_process:
+ for res_id, result in results.iteritems():
+ results[res_id] = self.render_post_process(cr, uid, result, context=context)
return results
def get_email_template_batch(self, cr, uid, template_id=False, res_ids=None, context=None):
@@ -356,17 +404,20 @@ class email_template(osv.osv):
results = dict()
for template, template_res_ids in templates_to_res_ids.iteritems():
# generate fields value for all res_ids linked to the current template
- for field in ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to']:
- generated_field_values = self.render_template_batch(cr, uid, getattr(template, field), template.model, template_res_ids, context=context)
+ for field in fields:
+ generated_field_values = self.render_template_batch(
+ cr, uid, getattr(template, field), template.model, template_res_ids,
+ post_process=(field == 'body_html'),
+ context=context)
for res_id, field_value in generated_field_values.iteritems():
results.setdefault(res_id, dict())[field] = field_value
# update values for all res_ids
for res_id in template_res_ids:
values = results[res_id]
- if template.user_signature:
+ if 'body_html' in fields and template.user_signature:
signature = self.pool.get('res.users').browse(cr, uid, uid, context).signature
values['body_html'] = tools.append_content_to_html(values['body_html'], signature)
- if values['body_html']:
+ if values.get('body_html'):
values['body'] = tools.html_sanitize(values['body_html'])
values.update(
mail_server_id=template.mail_server_id.id or False,
diff --git a/addons/email_template/wizard/mail_compose_message.py b/addons/email_template/wizard/mail_compose_message.py
index beede1122dc..71f99471afa 100644
--- a/addons/email_template/wizard/mail_compose_message.py
+++ b/addons/email_template/wizard/mail_compose_message.py
@@ -162,16 +162,18 @@ class mail_compose_message(osv.TransientModel):
partner_ids += self.pool['res.partner'].exists(cr, SUPERUSER_ID, tpl_partner_ids, context=context)
return partner_ids
- def generate_email_for_composer_batch(self, cr, uid, template_id, res_ids, context=None):
+ def generate_email_for_composer_batch(self, cr, uid, template_id, res_ids, context=None, fields=None):
""" Call email_template.generate_email(), get fields relevant for
mail.compose.message, transform email_cc and email_to into partner_ids """
# filter template values
- fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'attachments', 'mail_server_id']
+ if fields is None:
+ fields = ['subject', 'body_html', 'email_from', 'email_to', 'partner_to', 'email_cc', 'reply_to', 'attachment_ids', 'mail_server_id']
+ returned_fields = fields + ['attachments']
values = dict.fromkeys(res_ids, False)
- template_values = self.pool.get('email.template').generate_email_batch(cr, uid, template_id, res_ids, context=context)
+ template_values = self.pool.get('email.template').generate_email_batch(cr, uid, template_id, res_ids, fields=fields, context=context)
for res_id in res_ids:
- res_id_values = dict((field, template_values[res_id][field]) for field in fields if template_values[res_id].get(field))
+ res_id_values = dict((field, template_values[res_id][field]) for field in returned_fields if template_values[res_id].get(field))
res_id_values['body'] = res_id_values.pop('body_html', '')
# transform email_to, email_cc into partner_ids
@@ -189,7 +191,10 @@ class mail_compose_message(osv.TransientModel):
""" Override to handle templates. """
# generate template-based values
if wizard.template_id:
- template_values = self.generate_email_for_composer_batch(cr, uid, wizard.template_id.id, res_ids, context=context)
+ template_values = self.generate_email_for_composer_batch(
+ cr, uid, wizard.template_id.id, res_ids,
+ fields=['email_to', 'partner_to', 'email_cc', 'attachment_ids', 'mail_server_id'],
+ context=context)
else:
template_values = dict.fromkeys(res_ids, dict())
# generate composer values
@@ -206,8 +211,8 @@ class mail_compose_message(osv.TransientModel):
template_values[res_id].update(composer_values[res_id])
return template_values
- def render_template_batch(self, cr, uid, template, model, res_ids, context=None):
- return self.pool.get('email.template').render_template_batch(cr, uid, template, model, res_ids, context=context)
+ def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False):
+ return self.pool.get('email.template').render_template_batch(cr, uid, template, model, res_ids, context=context, post_process=post_process)
# Compatibility methods
def generate_email_for_composer(self, cr, uid, template_id, res_id, context=None):
diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py
index 2d09a925ca7..e5ff2b51fcd 100644
--- a/addons/mail/wizard/mail_compose_message.py
+++ b/addons/mail/wizard/mail_compose_message.py
@@ -352,10 +352,10 @@ class mail_compose_message(osv.TransientModel):
:return dict results: for each res_id, the generated template values for
subject, body, email_from and reply_to
"""
- subjects = self.render_template_batch(cr, uid, wizard.subject, wizard.model, res_ids, context)
- bodies = self.render_template_batch(cr, uid, wizard.body, wizard.model, res_ids, context)
- emails_from = self.render_template_batch(cr, uid, wizard.email_from, wizard.model, res_ids, context)
- replies_to = self.render_template_batch(cr, uid, wizard.reply_to, wizard.model, res_ids, context)
+ subjects = self.render_template_batch(cr, uid, wizard.subject, wizard.model, res_ids, context=context)
+ bodies = self.render_template_batch(cr, uid, wizard.body, wizard.model, res_ids, context=context, post_process=True)
+ emails_from = self.render_template_batch(cr, uid, wizard.email_from, wizard.model, res_ids, context=context)
+ replies_to = self.render_template_batch(cr, uid, wizard.reply_to, wizard.model, res_ids, context=context)
results = dict.fromkeys(res_ids, False)
for res_id in res_ids:
@@ -367,7 +367,7 @@ class mail_compose_message(osv.TransientModel):
}
return results
- def render_template_batch(self, cr, uid, template, model, res_ids, context=None):
+ def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False):
""" Render the given template text, replace mako-like expressions ``${expr}``
with the result of evaluating these expressions with an evaluation context
containing:
diff --git a/addons/website_mail/models/email_template.py b/addons/website_mail/models/email_template.py
index aed01c179f7..beb02739f29 100644
--- a/addons/website_mail/models/email_template.py
+++ b/addons/website_mail/models/email_template.py
@@ -19,9 +19,6 @@
#
##############################################################################
-import lxml
-import urlparse
-
from openerp.osv import osv, fields
from openerp.tools.translate import _
@@ -39,52 +36,3 @@ class EmailTemplate(osv.Model):
help='Link to the website',
),
}
-
- def _postprocess_html_replace_links(self, cr, uid, body_html, context=None):
- """ Post-processing of body_html. Indeed the content generated by the
- website builder contains references to local addresses, for example
- for images. This method changes those addresses to absolute addresses. """
- html = body_html
- if not body_html:
- return html
-
- # form a tree
- root = lxml.html.fromstring(html)
- if not len(root) and root.text is None and root.tail is None:
- html = '<div>%s</div>' % html
- root = lxml.html.fromstring(html)
-
- base_url = self.pool['ir.config_parameter'].get_param(cr, uid, 'web.base.url')
- (base_scheme, base_netloc, bpath, bparams, bquery, bfragment) = urlparse.urlparse(base_url)
-
- def _process_link(url):
- new_url = url
- (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)
- if not scheme and not netloc:
- new_url = urlparse.urlunparse((base_scheme, base_netloc, path, params, query, fragment))
- return new_url
-
- # check all nodes, replace :
- # - img src -> check URL
- # - a href -> check URL
- for node in root.iter():
- if node.tag == 'a':
- node.set('href', _process_link(node.get('href')))
- elif node.tag == 'img' and not node.get('src', 'data').startswith('data'):
- node.set('src', _process_link(node.get('src')))
-
- html = lxml.html.tostring(root, pretty_print=False, method='html')
- # this is ugly, but lxml/etree tostring want to put everything in a 'div' that breaks the editor -> remove that
- if html.startswith('<div>') and html.endswith('</div>'):
- html = html[5:-6]
- return html
-
- def create(self, cr, uid, values, context=None):
- if 'body_html' in values:
- values['body_html'] = self._postprocess_html_replace_links(cr, uid, values['body_html'], context=context)
- return super(EmailTemplate, self).create(cr, uid, values, context=context)
-
- def write(self, cr, uid, ids, values, context=None):
- if 'body_html' in values:
- values['body_html'] = self._postprocess_html_replace_links(cr, uid, values['body_html'], context=context)
- return super(EmailTemplate, self).write(cr, uid, ids, values, context=context)