Skip to content
Browse files

[FIX] base: Allow default email_from by database

It is possible to get to a situation where Odoo would try to send an email without a `From:` header address.

In such case, you're unlucky if you don't have access to the underlying deployment, or if you use multiple databases in a single Odoo instance and each of them uses a different mail configuration.

To make this configuration easier to use and cover those use cases, here I add support for a new ICP: `mail.default.from`. It will be used when present, so it shouldn't affect existing deployments. When present, it will allow a admin to configure the default sending address just with Odoo itself.

closes #36837

Signed-off-by: Thibault Delavallee (tde) <>
  • Loading branch information...
Yajo committed Oct 7, 2019
1 parent 1b50c05 commit d6f4b2cdc8eefa5d6b480bd29c3077de1b7b83b3
Showing with 49 additions and 3 deletions.
  1. +23 −2 odoo/addons/base/ir/
  2. +26 −1 odoo/addons/base/tests/
@@ -289,9 +289,10 @@ def build_email(self, email_from, email_to, subject, body, email_cc=None, email_
:rtype: email.message.Message (usually MIMEMultipart)
:return: the new RFC2822 email message
email_from = email_from or tools.config.get('email_from')
email_from = email_from or self._get_default_from_address()
assert email_from, "You must either provide a sender address explicitly or configure "\
"a global sender address in the server configuration or with the "\
"using the combintion of `mail.catchall.domain` and `mail.default.from` "\
"ICPs, in the server configuration file or with the "\
"--email-from startup parameter."

# Note: we must force all strings to to 8-bit utf-8 when crafting message,
@@ -388,6 +389,26 @@ def _get_default_bounce_address(self):
if postmaster and domain:
return '%s@%s' % (postmaster, domain)

def _get_default_from_address(self):
"""Compute the default from address.
Used for the "header from" address when no other has been received.
:return str/None:
Combines config parameters ``mail.default.from`` and
``mail.catchall.domain`` to generate a default sender address.
If some of those parameters is not defined, it will default to the
``--email-from`` CLI/config parameter.
get_param = self.env['ir.config_parameter'].sudo().get_param
domain = get_param('mail.catchall.domain')
email_from = get_param("mail.default.from")
if email_from and domain:
return "%s@%s" % (email_from, domain)
return tools.config.get("email_from")

def send_email(self, message, mail_server_id=None, smtp_server=None, smtp_port=None,
smtp_user=None, smtp_password=None, smtp_encryption=None, smtp_debug=False,
@@ -3,7 +3,10 @@

import unittest

from import html_sanitize, append_content_to_html, plaintext2html, email_split, misc
from unittest.mock import patch

from import html_sanitize, append_content_to_html, config, plaintext2html, email_split, misc
from odoo.tests.common import SavepointCase
from . import test_mail_examples

@@ -328,3 +331,25 @@ def test_email_split(self):
for text, expected in cases:
self.assertEqual(email_split(text), expected, 'email_split is broken')

class EmailConfigCase(SavepointCase):
@patch.dict("", {"email_from": ""})
def test_default_email_from(self, *args):
"""Email from setting is respected."""
# ICP setting is more important
ICP = self.env["ir.config_parameter"].sudo()
ICP.set_param("mail.catchall.domain", "")
ICP.set_param("mail.default.from", "icp")
message = self.env["ir.mail_server"].build_email(
False, "", "Subject",
"The body of an email",
self.assertEqual(message["From"], "")
# Without ICP, the config file/CLI setting is used
ICP.set_param("mail.default.from", False)
message = self.env["ir.mail_server"].build_email(
False, "", "Subject",
"The body of an email",
self.assertEqual(message["From"], "")

0 comments on commit d6f4b2c

Please sign in to comment.
You can’t perform that action at this time.