[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.
This commit is contained in:
Manuel Vázquez Acosta 2014-10-30 08:42:39 -04:00 committed by Olivier Dony
parent 7a0451d649
commit a4597fe34f
1 changed files with 32 additions and 3 deletions

View File

@ -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.