[IMP] phone_validation: try to be defensive when parsing phone numbers

After some testing notably with WhatsApp module, it appears usage of phone
numbers could be a bit more defensive to try to accomodate with data users
entered. Notably when failing to recognize a number, we can distinguish
error and try to reformat it based on two commonly spotted errors

  * missing "+" in front of a E164-like number (e.g. '32455001122');
  * usage of "00" in countries where it is not really standard to use it
    instead of a "+" (e.g. '0032455001122');

Those find of numbers generate a 'TOO_LONG' error from phonenumbers library.
In that case we try to reformat it just to see if we can do better with it.

Task-3608129 (Whatsapp: Moultifix !)

X-original-commit: odoo/odoo@85c1306156
Part-of: odoo/odoo#146398
This commit is contained in:
Thibault Delavallée
2023-12-15 17:13:25 +00:00
parent 065659ba90
commit bdfb802293
2 changed files with 48 additions and 1 deletions
@@ -185,6 +185,20 @@ msgid ""
" mass mailing sms anymore, from any list"
msgstr ""
#. module: phone_validation
#. odoo-python
#: code:addons/phone_validation/tools/phone_validation.py:0
#, python-format
msgid "Impossible number %s: not a valid country prefix."
msgstr ""
#. module: phone_validation
#. odoo-python
#: code:addons/phone_validation/tools/phone_validation.py:0
#, python-format
msgid "Impossible number %s: not enough digits."
msgstr ""
#. module: phone_validation
#. odoo-python
#: code:addons/phone_validation/tools/phone_validation.py:0
@@ -192,6 +206,15 @@ msgstr ""
msgid "Impossible number %s: probably invalid number of digits."
msgstr ""
#. module: phone_validation
#. odoo-python
#: code:addons/phone_validation/tools/phone_validation.py:0
#: code:addons/phone_validation/tools/phone_validation.py:0
#: code:addons/phone_validation/tools/phone_validation.py:0
#, python-format
msgid "Impossible number %s: too many digits."
msgstr ""
#. module: phone_validation
#: model:ir.model.fields,help:phone_validation.field_mail_thread_phone__mobile_blacklisted
msgid ""
@@ -22,7 +22,31 @@ try:
) from e
if not phonenumbers.is_possible_number(phone_nbr):
raise UserError(_('Impossible number %s: probably invalid number of digits.', number))
reason = phonenumbers.is_possible_number_with_reason(phone_nbr)
if reason == phonenumbers.ValidationResult.INVALID_COUNTRY_CODE:
raise UserError(_('Impossible number %s: not a valid country prefix.', number))
if reason == phonenumbers.ValidationResult.TOO_SHORT:
raise UserError(_('Impossible number %s: not enough digits.', number))
# in case of "TOO_LONG", we may try to reformat the number in case it was
# entered without '+' prefix or using leading '++' not always recognized;
# in any case final error should keep the original number to ease tracking
if reason == phonenumbers.ValidationResult.TOO_LONG:
# people may enter 0033... instead of +33...
if number.startswith('00'):
try:
phone_nbr = phone_parse(f'+{number.lstrip("00")}', country_code)
except UserError:
raise UserError(_('Impossible number %s: too many digits.', number))
# people may enter 33... instead of +33...
elif not number.startswith('+'):
try:
phone_nbr = phone_parse(f'+{number}', country_code)
except UserError:
raise UserError(_('Impossible number %s: too many digits.', number))
else:
raise UserError(_('Impossible number %s: too many digits.', number))
else:
raise UserError(_('Impossible number %s: probably invalid number of digits.', number))
if not phonenumbers.is_valid_number(phone_nbr):
raise UserError(_('Invalid number %s: probably incorrect prefix.', number))