From 7a0451d64960b2582208054757d818a1e92f3162 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 28 Jan 2015 11:26:06 +0100 Subject: [PATCH 1/3] [FIX] safe_eval: no shadowing of PostgreSQL's exceptions Letting PostgreSQL low-level exceptions bubble up ensures that the mechanism for automatically retrying transactions will work. In case of transient errors such as deadlocks or serialization errors, the transaction will be transparently retried. Previously they were transformed into ValueError and caused a permanent failure immediately. The fallback to ValueError is meant for invalid expressions or expressions that use variables not provided in the evaluation context. Other exception types should be preserved (this is further improved in Odoo 8) --- openerp/tools/safe_eval.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py index 6c5bb88da4e..99ce2f78ef3 100644 --- a/openerp/tools/safe_eval.py +++ b/openerp/tools/safe_eval.py @@ -32,6 +32,7 @@ condition/math builtins. # - safe_eval in tryton http://hg.tryton.org/hgwebdir.cgi/trytond/rev/bbb5f73319ad from opcode import HAVE_ARGUMENT, opmap, opname +from psycopg2 import OperationalError from types import CodeType import logging @@ -285,6 +286,10 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal ) try: return eval(test_expr(expr, _SAFE_OPCODES, mode=mode), globals_dict, locals_dict) + except OperationalError: + # Do not hide PostgreSQL low-level exceptions, to let the auto-replay + # of serialized transactions work its magic + raise except Exception: _logger.exception('Cannot eval %r', expr) raise From a4597fe34fcfa8dae28b156410080346bb33af33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20V=C3=A1zquez=20Acosta?= Date: Thu, 30 Oct 2014 08:42:39 -0400 Subject: [PATCH 2/3] [FIX] ir_mail_server: use local envelope sender rather than spoofing it Acting as a mailing-list-like distribution system, the system used to set the enveloper sender (aka bounce address) to the From header of the message, effectively pretending to be the original sender. In some cases the domain of the From header explicitly forbids sending emails from external systems (e.g. with a hardfail SPF record), so this could cause the email to be rejected by some spam filters, depending on their policies. The system will now use a local bounce address in the form: mail-catchall-alias@mail-catchall-domain or, if no catchall is configured: postmaster-odoo@mail-catchall-domain (as soon there is a mail.catchall.domain configured) It will only fallback to using the From header when no catchall domain is configured. Fixes issue #3347. Closes #3393. --- openerp/addons/base/ir/ir_mail_server.py | 35 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/openerp/addons/base/ir/ir_mail_server.py b/openerp/addons/base/ir/ir_mail_server.py index 881eafb8549..6a7784fead1 100644 --- a/openerp/addons/base/ir/ir_mail_server.py +++ b/openerp/addons/base/ir/ir_mail_server.py @@ -361,6 +361,27 @@ class ir_mail_server(osv.osv): msg.attach(part) return msg + def _get_default_bounce_address(self, cr, uid, context=None): + '''Compute the default bounce address. + + The default bounce address is used to set the envelop address if no + envelop address is provided in the message. It is formed by properly + joining the parameters "mail.catchall.alias" and + "mail.catchall.domain". + + If "mail.catchall.alias" is not set it defaults to "postmaster-odoo". + + If "mail.catchall.domain" is not set, return None. + + ''' + get_param = self.pool['ir.config_parameter'].get_param + postmaster = get_param(cr, uid, 'mail.catchall.alias', + default='postmaster-odoo', + context=context,) + domain = get_param(cr, uid, 'mail.catchall.domain', context=context) + if postmaster and domain: + return '%s@%s' % (postmaster, domain) + def send_email(self, cr, uid, message, mail_server_id=None, smtp_server=None, smtp_port=None, smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False, context=None): @@ -376,8 +397,9 @@ class ir_mail_server(osv.osv): and fails if not found. :param message: the email.message.Message to send. The envelope sender will be extracted from the - ``Return-Path`` or ``From`` headers. The envelope recipients will be - extracted from the combined list of ``To``, ``CC`` and ``BCC`` headers. + ``Return-Path`` (if present), or will be set to the default bounce address. + The envelope recipients will be extracted from the combined list of ``To``, + ``CC`` and ``BCC`` headers. :param mail_server_id: optional id of ir.mail_server to use for sending. overrides other smtp_* arguments. :param smtp_server: optional hostname of SMTP server to use :param smtp_encryption: optional TLS mode, one of 'none', 'starttls' or 'ssl' (see ir.mail_server fields for explanation) @@ -388,7 +410,14 @@ class ir_mail_server(osv.osv): :return: the Message-ID of the message that was just sent, if successfully sent, otherwise raises MailDeliveryException and logs root cause. """ - smtp_from = message['Return-Path'] or message['From'] + # Use the default bounce address **only if** no Return-Path was + # provided by caller. Caller may be using Variable Envelope Return + # Path (VERP) to detect no-longer valid email addresses. + smtp_from = message['Return-Path'] + if not smtp_from: + smtp_from = self._get_default_bounce_address(cr, uid, context=context) + if not smtp_from: + smtp_from = message['From'] assert smtp_from, "The Return-Path or From header is required for any outbound email" # The email's "Envelope From" (Return-Path), and all recipient addresses must only contain ASCII characters. From 4c2706d6858c4b7ec6db4b647dc2e3559f650cd8 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Thu, 29 Jan 2015 12:47:29 +0100 Subject: [PATCH 3/3] [FIX] web: saveas_ajax, correct filename when data passed directly In cases where data is directly given to the saveas_ajax controller, the filename was not correctly set, as no read method was performed. (The read call is useless as the data is already avaiable in such a case) In such cases, the filename must be given in advance opw-626707 --- addons/web/controllers/main.py | 2 +- addons/web/static/src/js/view_form.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 6206d1fa4d4..b3acbbe5119 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1309,7 +1309,7 @@ class Binary(openerpweb.Controller): if filename_field: fields.append(filename_field) if data: - res = { field: data } + res = {field: data, filename_field: jdata.get('filename', None)} elif id: res = Model.read([int(id)], fields, context)[0] else: diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 5581ca7b0ae..d4cf85a59f2 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -5087,14 +5087,17 @@ instance.web.form.FieldBinary = instance.web.form.AbstractField.extend(instance. } else { instance.web.blockUI(); var c = instance.webclient.crashmanager; + var filename_fieldname = this.node.attrs.filename; + var filename_field = this.view.fields && this.view.fields[filename_fieldname]; this.session.get_file({ url: '/web/binary/saveas_ajax', data: {data: JSON.stringify({ model: this.view.dataset.model, id: (this.view.datarecord.id || ''), field: this.name, - filename_field: (this.node.attrs.filename || ''), + filename_field: (filename_fieldname || ''), data: instance.web.form.is_bin_size(value) ? null : value, + filename: filename_field ? filename_field.get('value') : null, context: this.view.dataset.get_context() })}, complete: instance.web.unblockUI,