From 8d3fcf42c9e1f1aedaf5dae0f3776c0efbe7644f Mon Sep 17 00:00:00 2001 From: David Beguin Date: Thu, 25 Oct 2018 12:52:04 +0000 Subject: [PATCH] [IMP] mail : add mixin to normalize email address This Mixin can be used to store a normalized version of the primary email address of the parent model. The email_normalized field can than be used on that model to search quickly on emails (by simple comparison and not using time consuming regex anymore) This commit will be usefull to simplify the email address comparison in the blacklist mixin but also for any models storing non normalized email address. Task ID : 1896677 --- addons/mail/models/__init__.py | 1 + addons/mail/models/mail_address_mixin.py | 52 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 addons/mail/models/mail_address_mixin.py diff --git a/addons/mail/models/__init__.py b/addons/mail/models/__init__.py index 5319c310790..c53d8689082 100644 --- a/addons/mail/models/__init__.py +++ b/addons/mail/models/__init__.py @@ -10,6 +10,7 @@ from . import mail_message from . import mail_activity from . import mail_mail from . import mail_thread +from . import mail_address_mixin from . import mail_blacklist from . import mail_channel from . import mail_template diff --git a/addons/mail/models/mail_address_mixin.py b/addons/mail/models/mail_address_mixin.py new file mode 100644 index 00000000000..740191dcd4c --- /dev/null +++ b/addons/mail/models/mail_address_mixin.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models, tools, _ +from odoo.exceptions import UserError + + +class MailAddressMixin(models.AbstractModel): + """ Purpose of this mixing is to store a normalized email based on the primary email field. + A normalized email is considered as : + - having a left part + @ + a right part (the domain can be without '.something') + - being lower case + - having no name before the address. Typically, having no 'Name <>' + Ex: + - Formatted Email : 'Name ' + - Normalized Email : 'name@domain.com' + The primary email field can be specified on the parent model, if it differs from the default one ('email') + The email_normalized field can than be used on that model to search quickly on emails (by simple comparison + and not using time consuming regex anymore). + """ + _name = 'mail.address.mixin' + _description = 'Email address mixin' + _primary_email = ['email'] + + email_normalized = fields.Char(string='Normalized email address', compute="_compute_email_normalized", invisible=True, + compute_sudo=True, store=True, help="""This field is used to search on email address, + as the primary email field can contain more than strictly an email address.""") + + @api.depends(lambda self: self._primary_email) + def _compute_email_normalized(self): + self._assert_primary_email() + [email_field] = self._primary_email + for record in self: + record.email_normalized = self._normalize_email(record[email_field]) + + def _normalize_email(self, email): + """ Sanitize and standardize email address entries: all emails should be + only real email extracted from strings (A -> a@a) and should be + lower case. """ + emails = tools.email_split(email) + if not emails or len(emails) != 1: + return False + return emails[0].lower() + + def _assert_primary_email(self): + if not hasattr(self, "_primary_email") or \ + not isinstance(self._primary_email, (list, tuple)) or \ + not len(self._primary_email) == 1: + raise UserError(_('Invalid primary email field on model %s') % self._name) + field_name = self._primary_email[0] + if field_name not in self._fields or self._fields[field_name].type != 'char': + raise UserError(_('Invalid primary email field on model %s') % self._name)