diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py
index 19b565c9f6f2dadc25faee6edd10d0f5b94c5877..bf8dd84981acdc0c7a25ca1b3ea17ccb1e8c0040 100644
--- a/addons/crm/models/crm_lead.py
+++ b/addons/crm/models/crm_lead.py
@@ -1838,12 +1838,17 @@ class Lead(models.Model):
             # we consider that posting a message with a specified recipient (not a follower, a specific one)
             # on a document without customer means that it was created through the chatter using
             # suggested recipients. This heuristic allows to avoid ugly hacks in JS.
-            new_partner = message.partner_ids.filtered(lambda partner: partner.email == self.email_from)
+            new_partner = message.partner_ids.filtered(
+                lambda partner: partner.email == self.email_from or (self.email_normalized and partner.email_normalized == self.email_normalized)
+            )
             if new_partner:
+                if new_partner[0].email_normalized:
+                    email_domain = ('email_normalized', '=', new_partner[0].email_normalized)
+                else:
+                    email_domain = ('email_from', '=', new_partner[0].email)
                 self.search([
-                    ('partner_id', '=', False),
-                    ('email_from', '=', new_partner.email),
-                    ('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
+                    ('partner_id', '=', False), email_domain, ('stage_id.fold', '=', False)
+                ]).write({'partner_id': new_partner[0].id})
         return super(Lead, self)._message_post_after_hook(message, msg_vals)
 
     def _message_partner_info_from_emails(self, emails, link_mail=False):
diff --git a/addons/event/models/event_registration.py b/addons/event/models/event_registration.py
index 3ecb8ea39d514d88998d3a8f4b06eb4a5fed83ee..31c81a92e2e5d08fcafe0aa67a7723af3028ba23 100644
--- a/addons/event/models/event_registration.py
+++ b/addons/event/models/event_registration.py
@@ -4,7 +4,7 @@
 from dateutil.relativedelta import relativedelta
 
 from odoo import _, api, fields, models, SUPERUSER_ID
-from odoo.tools import format_datetime
+from odoo.tools import format_datetime, email_normalize
 from odoo.exceptions import AccessError, ValidationError
 
 
@@ -305,13 +305,18 @@ class EventRegistration(models.Model):
             # we consider that posting a message with a specified recipient (not a follower, a specific one)
             # on a document without customer means that it was created through the chatter using
             # suggested recipients. This heuristic allows to avoid ugly hacks in JS.
-            new_partner = message.partner_ids.filtered(lambda partner: partner.email == self.email)
+            email_normalized = email_normalize(self.email)
+            new_partner = message.partner_ids.filtered(
+                lambda partner: partner.email == self.email or (email_normalized and partner.email_normalized == email_normalized)
+            )
             if new_partner:
+                if new_partner[0].email_normalized:
+                    email_domain = ('email', 'in', [new_partner[0].email, new_partner[0].email_normalized])
+                else:
+                    email_domain = ('email', '=', new_partner[0].email)
                 self.search([
-                    ('partner_id', '=', False),
-                    ('email', '=', new_partner.email),
-                    ('state', 'not in', ['cancel']),
-                ]).write({'partner_id': new_partner.id})
+                    ('partner_id', '=', False), email_domain, ('state', 'not in', ['cancel']),
+                ]).write({'partner_id': new_partner[0].id})
         return super(EventRegistration, self)._message_post_after_hook(message, msg_vals)
 
     # ------------------------------------------------------------
diff --git a/addons/hr_recruitment/models/hr_recruitment.py b/addons/hr_recruitment/models/hr_recruitment.py
index 4a79654514649dc0fe038869028f8d03f89a3ba6..73544832831c14ddf5330b56a9c2f16c1d20e619 100644
--- a/addons/hr_recruitment/models/hr_recruitment.py
+++ b/addons/hr_recruitment/models/hr_recruitment.py
@@ -470,18 +470,24 @@ class Applicant(models.Model):
             # we consider that posting a message with a specified recipient (not a follower, a specific one)
             # on a document without customer means that it was created through the chatter using
             # suggested recipients. This heuristic allows to avoid ugly hacks in JS.
-            new_partner = message.partner_ids.filtered(lambda partner: partner.email == self.email_from)
+            email_normalized = tools.email_normalize(self.email_from)
+            new_partner = message.partner_ids.filtered(
+                lambda partner: partner.email == self.email_from or (email_normalized and partner.email_normalized == email_normalized)
+            )
             if new_partner:
-                if new_partner.create_date.date() == fields.Date.today():
-                    new_partner.write({
+                if new_partner[0].create_date.date() == fields.Date.today():
+                    new_partner[0].write({
                         'type': 'private',
                         'phone': self.partner_phone,
                         'mobile': self.partner_mobile,
                     })
+                if new_partner[0].email_normalized:
+                    email_domain = ('email_from', 'in', [new_partner[0].email, new_partner[0].email_normalized])
+                else:
+                    email_domain = ('email_from', '=', new_partner[0].email)
                 self.search([
-                    ('partner_id', '=', False),
-                    ('email_from', '=', new_partner.email),
-                    ('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
+                    ('partner_id', '=', False), email_domain, ('stage_id.fold', '=', False)
+                ]).write({'partner_id': new_partner[0].id})
         return super(Applicant, self)._message_post_after_hook(message, msg_vals)
 
     def create_employee_from_applicant(self):
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index 5cc17438806a377bd5e15e6edff30433f0410c96..50a4fb3409aa02b2a18f511313ae2d8ecc50f1de 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -2122,12 +2122,18 @@ class Task(models.Model):
             # we consider that posting a message with a specified recipient (not a follower, a specific one)
             # on a document without customer means that it was created through the chatter using
             # suggested recipients. This heuristic allows to avoid ugly hacks in JS.
-            new_partner = message.partner_ids.filtered(lambda partner: partner.email == self.email_from)
+            email_normalized = tools.email_normalize(self.email_from)
+            new_partner = message.partner_ids.filtered(
+                lambda partner: partner.email == self.email_from or (email_normalized and partner.email_normalized == email_normalized)
+            )
             if new_partner:
+                if new_partner[0].email_normalized:
+                    email_domain = ('email_from', 'in', [new_partner[0].email, new_partner[0].email_normalized])
+                else:
+                    email_domain = ('email_from', '=', new_partner[0].email)
                 self.search([
-                    ('partner_id', '=', False),
-                    ('email_from', '=', new_partner.email),
-                    ('stage_id.fold', '=', False)]).write({'partner_id': new_partner.id})
+                    ('partner_id', '=', False), email_domain, ('stage_id.fold', '=', False)
+                ]).write({'partner_id': new_partner[0].id})
         return super(Task, self)._message_post_after_hook(message, msg_vals)
 
     def action_assign_to_me(self):
diff --git a/addons/website_event_track/models/event_track.py b/addons/website_event_track/models/event_track.py
index 22b5ffec3b41a98b1e112c956697ebc0dc20b0c4..2ae02b42312376779d7ee01b54d142193a55712a 100644
--- a/addons/website_event_track/models/event_track.py
+++ b/addons/website_event_track/models/event_track.py
@@ -5,7 +5,7 @@ from datetime import timedelta
 from pytz import utc
 from random import randint
 
-from odoo import api, fields, models
+from odoo import api, fields, models, tools
 from odoo.addons.http_routing.models.ir_http import slug
 from odoo.osv import expression
 from odoo.tools.mail import is_html_empty
@@ -482,15 +482,19 @@ class Track(models.Model):
             #  Contact(s) created from chatter set on track : we verify if at least one is the expected contact
             #  linked to the track. (created from contact_email if any, then partner_email if any)
             main_email = self.contact_email or self.partner_email
-            if main_email:
-                new_partner = message.partner_ids.filtered(lambda partner: partner.email == main_email)
-                if new_partner:
-                    main_email_string = 'contact_email' if self.contact_email else 'partner_email'
-                    self.search([
-                        ('partner_id', '=', False),
-                        (main_email_string, '=', new_partner.email),
-                        ('stage_id.is_cancel', '=', False),
-                    ]).write({'partner_id': new_partner.id})
+            main_email_normalized = tools.email_normalize(main_email)
+            new_partner = message.partner_ids.filtered(
+                lambda partner: partner.email == main_email or (main_email_normalized and partner.email_normalized == main_email_normalized)
+            )
+            if new_partner:
+                mail_email_fname = 'contact_email' if self.contact_email else 'partner_email'
+                if new_partner[0].email_normalized:
+                    email_domain = (mail_email_fname, 'in', [new_partner[0].email, new_partner[0].email_normalized])
+                else:
+                    email_domain = (mail_email_fname, '=', new_partner[0].email)
+                self.search([
+                    ('partner_id', '=', False), email_domain, ('stage_id.is_cancel', '=', False),
+                ]).write({'partner_id': new_partner[0].id})
         return super(Track, self)._message_post_after_hook(message, msg_vals)
 
     def _track_template(self, changes):