diff --git a/addons/crm/tests/test_crm_lead_notification.py b/addons/crm/tests/test_crm_lead_notification.py
index ca7df34cc4ff71c016bdc19b7f9c9414f906ae37..ec6c4e6039cc5730e20763cbf073d3a2d5472b03 100644
--- a/addons/crm/tests/test_crm_lead_notification.py
+++ b/addons/crm/tests/test_crm_lead_notification.py
@@ -39,7 +39,7 @@ class NewLeadNotification(TestCrmCommon):
             [(False, '"New Customer" <new.customer.format@test.example.com>', 'Customer Email'),
              (False, 'new.customer.multi.1@test.example.com, new.customer.2@test.example.com', 'Customer Email'),
              (False, 'new.customer.simple@test.example.com', 'Customer Email'),
-             (self.contact_1.id, '"Philip J Fry" <"Philip, J. Fry" <philip.j.fry@test.example.com>>', 'Customer'),
+             (self.contact_1.id, '"Philip J Fry" <philip.j.fry@test.example.com>', 'Customer'),
             ]
         ):
             with self.subTest(lead=lead, email_from=lead.email_from):
diff --git a/addons/mail/tests/test_res_partner.py b/addons/mail/tests/test_res_partner.py
index 56fb86f4db59f2a6a2a374f3759e399af9858e9a..588a969ca2b90d012162e846d2607a222b2da740 100644
--- a/addons/mail/tests/test_res_partner.py
+++ b/addons/mail/tests/test_res_partner.py
@@ -51,8 +51,8 @@ class TestPartner(MailCommon):
         self.assertEqual(
             partners.mapped('email_formatted'),
             ['"Classic Format" <classic.format@test.example.com>',
-             '"FindMe Format" <"FindMe Format" <find.me.format@test.example.com>>',
-             '"FindMe Multi" <find.me.multi.1@test.example.com, "FindMe Multi" <find.me.multi.2@test.example.com>>']
+             '"FindMe Format" <find.me.format@test.example.com>',
+             '"FindMe Multi" <find.me.multi.1@test.example.com,find.me.multi.2@test.example.com>']
         )
         self.assertEqual(
             partners.mapped('email_normalized'),
diff --git a/addons/test_mail/tests/test_mail_composer.py b/addons/test_mail/tests/test_mail_composer.py
index 107f6abad4bf27bb7d7cf711b0250a344f330a8e..99b6664fa6b70b03b8c38008bfaf503889c0468e 100644
--- a/addons/test_mail/tests/test_mail_composer.py
+++ b/addons/test_mail/tests/test_mail_composer.py
@@ -637,15 +637,15 @@ class TestComposerResultsComment(TestMailComposer):
         # ensure values used afterwards for testing
         self.assertEqual(
             self.partner_employee.email_formatted,
-            '"Ernest Employee" <email.from.1@test.example.com, email.from.2@test.example.com>',
+            '"Ernest Employee" <email.from.1@test.example.com,email.from.2@test.example.com>',
             'Formatting: wrong formatting due to multi-email')
         self.assertEqual(
             self.partner_1.email_formatted,
-            '"Valid Lelitre" <"Valid Formatted" <valid.lelitre@agrolait.com>>',
-            'Formatting: wrong double encapsulation')
+            '"Valid Lelitre" <valid.lelitre@agrolait.com>',
+            'Formatting: avoid wrong double encapsulation')
         self.assertEqual(
             self.partner_2.email_formatted,
-            '"Valid Poilvache" <valid.other.1@agrolait.com, valid.other.cc@agrolait.com>',
+            '"Valid Poilvache" <valid.other.1@agrolait.com,valid.other.cc@agrolait.com>',
             'Formatting: wrong formatting due to multi-email')
 
         # instantiate composer, post message
@@ -680,8 +680,8 @@ class TestComposerResultsComment(TestMailComposer):
         )
         self.assertEqual(
             sorted(new_partners.mapped('email_formatted')),
-            sorted(['"FindMe Format" <"FindMe Format" <find.me.format@test.example.com>>',
-                    '"FindMe Multi" <find.me.multi.1@test.example.com, "FindMe Multi" <find.me.multi.2@test.example.com>>',
+            sorted(['"FindMe Format" <find.me.format@test.example.com>',
+                    '"FindMe Multi" <find.me.multi.1@test.example.com,find.me.multi.2@test.example.com>',
                     '"find.me.multi.1@test.example.com" <find.me.multi.1@test.example.com>',
                     '"find.me.multi.2@test.example.com" <find.me.multi.2@test.example.com>',
                     '"test.cc.1@example.com" <test.cc.1@example.com>',
@@ -722,12 +722,12 @@ class TestComposerResultsComment(TestMailComposer):
             email_values={
                 'body_content': f'TemplateBody {self.test_record.name}',
                 # currently holding multi-email 'from'
-                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com, email.from.2@test.example.com')),
+                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com,email.from.2@test.example.com')),
                 'subject': f'TemplateSubject {self.test_record.name}',
             },
             fields_values={
                 # currently holding multi-email 'email_from'
-                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com, email.from.2@test.example.com')),
+                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com,email.from.2@test.example.com')),
             },
             mail_message=self.test_record.message_ids[0],
         )
@@ -736,12 +736,12 @@ class TestComposerResultsComment(TestMailComposer):
             author=self.partner_employee,
             email_values={
                 'body_content': f'TemplateBody {self.test_record.name}',
-                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com, email.from.2@test.example.com')),
+                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com,email.from.2@test.example.com')),
                 'subject': f'TemplateSubject {self.test_record.name}',
             },
             fields_values={
                 # currently holding multi-email 'email_from'
-                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com, email.from.2@test.example.com')),
+                'email_from': formataddr((self.user_employee.name, 'email.from.1@test.example.com,email.from.2@test.example.com')),
             },
             mail_message=self.test_record.message_ids[0],
         )
@@ -1080,15 +1080,15 @@ class TestComposerResultsMass(TestMailComposer):
         # ensure values used afterwards for testing
         self.assertEqual(
             self.partner_employee.email_formatted,
-            '"Ernest Employee" <email.from.1@test.example.com, email.from.2@test.example.com>',
+            '"Ernest Employee" <email.from.1@test.example.com,email.from.2@test.example.com>',
             'Formatting: wrong formatting due to multi-email')
         self.assertEqual(
             self.partner_1.email_formatted,
-            '"Valid Lelitre" <"Valid Formatted" <valid.lelitre@agrolait.com>>',
-            'Formatting: wrong double encapsulation')
+            '"Valid Lelitre" <valid.lelitre@agrolait.com>',
+            'Formatting: avoid wrong double encapsulation')
         self.assertEqual(
             self.partner_2.email_formatted,
-            '"Valid Poilvache" <valid.other.1@agrolait.com, valid.other.cc@agrolait.com>',
+            '"Valid Poilvache" <valid.other.1@agrolait.com,valid.other.cc@agrolait.com>',
             'Formatting: wrong formatting due to multi-email')
 
         # instantiate composer, send mailing
@@ -1123,8 +1123,8 @@ class TestComposerResultsMass(TestMailComposer):
         )
         self.assertEqual(
             sorted(new_partners.mapped('email_formatted')),
-            sorted(['"FindMe Format" <"FindMe Format" <find.me.format@test.example.com>>',
-                    '"FindMe Multi" <find.me.multi.1@test.example.com, "FindMe Multi" <find.me.multi.2@test.example.com>>',
+            sorted(['"FindMe Format" <find.me.format@test.example.com>',
+                    '"FindMe Multi" <find.me.multi.1@test.example.com,find.me.multi.2@test.example.com>',
                     '"find.me.multi.1@test.example.com" <find.me.multi.1@test.example.com>',
                     '"find.me.multi.2@test.example.com" <find.me.multi.2@test.example.com>',
                     '"test.cc.1@example.com" <test.cc.1@example.com>',
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index f468951a0a39be9556be38dffc4b5220b175d1aa..2d26e11df9af1ddc8d75d82ef4db03bf23034294 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -379,11 +379,36 @@ class Partner(models.Model):
 
     @api.depends('name', 'email')
     def _compute_email_formatted(self):
+        """ Compute formatted email for partner, using formataddr. Be defensive
+        in computation, notably
+
+          * double format: if email already holds a formatted email like
+            'Name' <email@domain.com> we should not use it as it to compute
+            email formatted like "Name <'Name' <email@domain.com>>";
+          * multi emails: sometimes this field is used to hold several addresses
+            like email1@domain.com, email2@domain.com. We currently let this value
+            untouched, but remove any formatting from multi emails;
+          * invalid email: if something is wrong, keep it in email_formatted as
+            this eases management and understanding of failures at mail.mail,
+            mail.notification and mailing.trace level;
+          * void email: email_formatted is False, as we cannot do anything with
+            it;
+        """
+        self.email_formatted = False
         for partner in self:
-            if partner.email:
-                partner.email_formatted = tools.formataddr((partner.name or u"False", partner.email or u"False"))
-            else:
-                partner.email_formatted = ''
+            emails_normalized = tools.email_normalize_all(partner.email)
+            if emails_normalized:
+                # note: multi-email input leads to invalid email like "Name" <email1, email2>
+                # but this is current behavior in Odoo 14+ and some servers allow it
+                partner.email_formatted = tools.formataddr((
+                    partner.name or u"False",
+                    ','.join(emails_normalized)
+                ))
+            elif partner.email:
+                partner.email_formatted = tools.formataddr((
+                    partner.name or u"False",
+                    partner.email
+                ))
 
     @api.depends('is_company')
     def _compute_company_type(self):
diff --git a/odoo/addons/base/tests/test_res_partner.py b/odoo/addons/base/tests/test_res_partner.py
index 2ec3458de8034a87fb15f940f18ed5ca94b89165..3160db404fae627b506e5975ee2884f78a5b7a17 100644
--- a/odoo/addons/base/tests/test_res_partner.py
+++ b/odoo/addons/base/tests/test_res_partner.py
@@ -61,25 +61,25 @@ class TestPartner(TransactionCase):
             # encapsulated email
             (
                 "Vlad the Impaler <vlad.the.impaler@example.com>",
-                '"Balázs" <Vlad the Impaler <vlad.the.impaler@example.com>>'
+                '"Balázs" <vlad.the.impaler@example.com>'
             ), (
                 '"Balázs" <balazs@adam.hu>',
-                '"Balázs" <"Balázs" <balazs@adam.hu>>'
+                '"Balázs" <balazs@adam.hu>'
             ),
             # multi email
             (
                 "vlad.the.impaler@example.com, vlad.the.dragon@example.com",
-                '"Balázs" <vlad.the.impaler@example.com, vlad.the.dragon@example.com>'
+                '"Balázs" <vlad.the.impaler@example.com,vlad.the.dragon@example.com>'
             ), (
                 "vlad.the.impaler.com, vlad.the.dragon@example.com",
-                '"Balázs" <vlad.the.impaler.com, vlad.the.dragon@example.com>'
+                '"Balázs" <vlad.the.dragon@example.com>'
             ), (
                 'vlad.the.impaler.com, "Vlad the Dragon" <vlad.the.dragon@example.com>',
-                '"Balázs" <vlad.the.impaler.com, "Vlad the Dragon" <vlad.the.dragon@example.com>>'
+                '"Balázs" <vlad.the.dragon@example.com>'
             ),
             # falsy emails
-            (False, ''),
-            ('', ''),
+            (False, False),
+            ('', False),
             (' ', '"Balázs" <@ >'),
             ('notanemail', '"Balázs" <@notanemail>'),
         ]:
diff --git a/odoo/tools/mail.py b/odoo/tools/mail.py
index 3562b1b726c327268e9914cee0dafd41957e236d..9e84681107816dde60199603e46bcdb6769b698b 100644
--- a/odoo/tools/mail.py
+++ b/odoo/tools/mail.py
@@ -552,6 +552,20 @@ def email_normalize(text):
         return False
     return emails[0].lower()
 
+def email_normalize_all(text):
+    """ Tool method allowing to extract email addresses from a text input and returning
+    normalized version of all found emails. If no email is found, a void list
+    is returned.
+
+    e.g. if email is 'tony@e.com, "Tony2" <tony2@e.com' returned result is ['tony@e.com, tony2@e.com']
+
+    :return list: list of normalized emails found in text
+    """
+    if not text:
+        return []
+    emails = email_split(text)
+    return list(filter(None, [email_normalize(email) for email in emails]))
+
 def email_escape_char(email_address):
     """ Escape problematic characters in the given email address string"""
     return email_address.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_')