You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.8 KiB

  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. # This module copyright (C) 2015 Savoir-faire Linux
  6. # (<http://www.savoirfairelinux.com>).
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import logging
  23. import unicodedata
  24. from openerp.osv import orm
  25. from openerp.tools.translate import _
  26. _logger = logging.getLogger(__name__)
  27. class Partner(orm.Model):
  28. _name = _inherit = 'res.partner'
  29. def _check_email_domain(self, domain):
  30. """ Checks if a domain is valid for an email """
  31. # Allow localhost and test, those are valid domains
  32. if domain in (u'localhost', u'test'):
  33. return True
  34. domain_parts = domain.split(u".")
  35. # Disallow @foo @foo. @foo..com
  36. if len(domain_parts) <= 1:
  37. _logger.debug("Email has single domain part")
  38. return False
  39. # Disallow @foo. @foo..com, @.b
  40. for part in domain_parts:
  41. if not part:
  42. _logger.debug("Empty domain part")
  43. return False
  44. # TLD must have 2 chars at least
  45. if len(domain_parts[-1]) < 2:
  46. _logger.debug("TLD too short")
  47. return False
  48. # Check that we have letters, numbers, '.' or '-'
  49. for letter in domain:
  50. if letter in ".-":
  51. continue
  52. cat = unicodedata.category(letter)
  53. if cat[0] not in u'LN': # Letter or Number
  54. _logger.debug("Character not accepted in domain: %r",
  55. letter)
  56. return False
  57. return True
  58. def _check_email_mailbox(self, mailbox):
  59. """ Checks if a mailbox is valid for an email """
  60. for letter in mailbox:
  61. if letter in ".-_+": # Few accepted symbols
  62. continue
  63. cat = unicodedata.category(letter)
  64. if cat[0] not in u'LN': # Letter or Number
  65. _logger.debug("Character not accepted in mailbox: %r",
  66. letter)
  67. return False
  68. return True
  69. def _check_valid_email(self, email):
  70. """ Checks if an email address is valid """
  71. mail, sep, domain = email.rpartition(u'@')
  72. # We need a full "mail@domain"
  73. if not mail or not sep or not domain:
  74. _logger.debug("Mail is not mail@domain")
  75. return False
  76. if not self._check_email_domain(domain):
  77. return False
  78. if not self._check_email_mailbox(mail):
  79. return False
  80. return True
  81. def _check_customer_email(self, cr, uid, ids, context=None):
  82. for partner in self.browse(cr, uid, ids, context=None):
  83. if not partner.email:
  84. # The view already forces the email to be filled, do not
  85. # double check or repeat conditions
  86. continue
  87. if not self._check_valid_email(partner.email):
  88. return False
  89. return True
  90. _constraints = [
  91. (_check_customer_email,
  92. _('You must provide a valid email address'), ['email']),
  93. ]