preg_match проверка адресов электронной почты не на английском языке (международные доменные имена)

Мы все знаем, что проверка адреса электронной почты — это щекотливая тема, существует так много мнений о том, как лучше всего справиться с этим без кодирования для всего RFC. Но с 2009 года все стало еще сложнее, и я еще не видел, чтобы кто-то занимался проблемой IDN.

Вот что я использовал:

preg_match(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,6}\z/i)

Что будет работать для большинства адресов электронной почты, но что, если мне нужно сопоставить адрес электронной почты не на латинице? например: bob@china.中國 или bob@russia.рф

Полный список смотрите здесь. (Обратите внимание на все нелатинские доменные расширения внизу списка.)

Информацию на эту тему можно найти здесь и я думаю, что они говорят, что эти новые символы будут просто читаться как «.xn--fiqz9s» и «.xn--p1ai» на машинном уровне, но я не уверен на 100%.

Если это так, значит ли это, что единственное изменение, которое мне нужно рассмотреть, заключается в следующем? (Для доменных расширений, таких как .travelersinsurance и .sandvikcoromant)

preg_match(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,20}\z/i)

ВНИМАНИЕ. Это не связано с обсуждением на этой странице Использование регулярное выражение для проверки адреса электронной почты


person Vince    schedule 25.02.2016    source источник
comment
Это не дубликат, он спрашивает о том, чего даже не существовало, когда был задан процитированный вопрос.   -  person trognanders    schedule 26.02.2016
comment
@Stilleur Аспект проверки международных доменных имен (IDN) нигде на этой странице не обсуждается.   -  person Vince    schedule 26.02.2016
comment
@ Винс Да, извини за это. Поскольку я только что отметил ваш вопрос. Я спросил себя, как я могу отменить это (и я проголосовал за это, потому что это очень интересно).   -  person Cédric M.    schedule 26.02.2016
comment
вы можете просто доверять пользователю, чтобы он знал свой собственный адрес электронной почты   -  person    schedule 26.02.2016
comment
@ Винс Почему ты этого хочешь? Какие из них вы бы проголосовали против?   -  person trognanders    schedule 26.02.2016
comment
Дагона, он просто не рассматривает все причины, по которым мне может понадобиться эта функция.   -  person Vince    schedule 26.02.2016


Ответы (3)


Учтите: каждый раз, когда вы создаете собственное новое регулярное выражение без проверки адресов в соответствии с полной спецификацией RFC, вы только ухудшаете ситуацию с использованием «экзотических» адресов электронной почты в Интернете. Вы изобретаете какой-то новый специальный подмножество или надстройку официальной спецификации RFC; это означает, что у вас будут либо ложные срабатывания, либо ложные отрицания, либо и то, и другое, вы будете запрещать людям использовать их фактические адреса, потому что ваше регулярное выражение не учитывает их правильно, или вы будете принимать адреса, которые на самом деле недействительны.

Добавьте к этому, что даже если адрес синтаксически действителен, это все равно не означает, что а) адрес действительно (все еще) существует, б) принадлежит этому пользователю или в) действительно может получать электронную почту. В схеме грантов проверка синтаксиса является чрезвычайно незначительной проблемой.

Если вы вообще собираетесь проверять синтаксис, либо выполните очень грубую общую проверку, которая наверняка не отклонит действительные адреса (например, /.+@.+/), или проверьте в соответствии с ко всем правилам RFC; не делайте какую-то промежуточную неполную строгую, но не совсем проверку, которую вы только что придумали.

person deceze♦    schedule 26.02.2016
comment
будет ли уникум@из.рф считаться действительным адресом электронной почты в соответствии со спецификацией RFC? - person oldboy; 29.07.2019
comment
Он должен соответствовать какому-то RFC, иначе он не будет пригодным для использования адресом электронной почты. (И вам также нужно сначала следовать спецификации IDNA…) - person deceze♦; 29.07.2019
comment
Кроме того, как вы предлагаете проверять глобальные имена и фамилии? как вы думаете, этот парень прав, говоря, что имена вообще не должны проверяться? - person oldboy; 30.07.2019
comment
есть идеи, как изменить регулярное выражение электронной почты (/.+@.+/), чтобы оно содержало не более 50 символов, но минимум 1 слева от @ и минимум 4 справа? что-то вроде ^.{1,}?@.{4,}?$, но каким-то образом ограничивая общее количество символов - person oldboy; 30.07.2019
comment
Прежде всего: почему? Как вы пришли к конкретному числу 50? Вы слушали что-нибудь, что я сказал?! ???? Во-вторых, задайте новый вопрос для этого. В-третьих, если это элемент input, используйте его атрибут maxlength. Если это проверка на стороне сервера, используйте отдельную проверку длины; все это не нужно объединять в одно регулярное выражение (хотя это, вероятно, возможно). - person deceze♦; 30.07.2019
comment
потому что я не хочу принимать адреса электронной почты длиннее 50 символов. 50 символов достаточно долго. я имею в виду, что я не создаю социальную сеть или что-то в этом роде, лол. я получил решение с чистым регулярным выражением, используя отрицательный прогноз: ^(?!.{51,}).{1,}?@.{4,}?$ - person oldboy; 31.07.2019

Я останусь с проверенным и верным предложением отправить им электронное письмо с подтверждением. Нет необходимости в причудливых регулярных выражениях, которые нужно будет обновлять снова и снова. Просто предположите, что они знают свой адрес электронной почты, и позвольте им ввести его.

Я всегда так делал, когда возникала такая ситуация. Во всяком случае, я бы заставил их ввести свой адрес электронной почты дважды. Это освободит вас, чтобы тратить больше времени на важные части вашего сайта/проекта.

person Iwnnay    schedule 25.02.2016
comment
я люблю сайты, которые просят меня напечатать это дважды (копировать-вставить) ;-) - person ; 26.02.2016
comment
`onpaste=return false;` (пальцевые пистолеты: pew pew) - person Iwnnay; 26.02.2016

Вот что я в итоге придумал.

preg_match(/^[\pL\pM*+\pN._%+-]+@[\pL\pM*+\pN.-]+\.[\pL\pM*+]{2,20}\z/u)

При этом используются регулярные выражения Unicode, такие как \pL, \pM*+ и \pN, чтобы помочь мне работать с символами и числами любого языка.

\pL Любая буква любого языка, в верхнем или нижнем регистре.

\pM*+ Соответствует нулю или более кодовым точкам, которые объединяют метки. Символ, предназначенный для сочетания с другим символом (например, акценты, умлауты, закрывающие прямоугольники и т. д.).

\pN Любое число.

Приведенное выше выражение отлично работает для обычных адресов электронной почты, таких как [email protected], и какофонических адресов электронной почты, таких как a.s中3_yÄhমহাজোটেরoo文%网+d-fελληνικά@πyÄhooαράδειγμα.δοκιμή.

Это не значит, что я не доверяю людям, которые могут вводить свои собственные адреса электронной почты, но люди делают ошибки, и я могу использовать этот код в других ситуациях. Например: мне нужно дважды проверить целостность существующего списка из 10 000 адресов электронной почты. Кроме того, меня всегда учили НЕ доверять пользовательскому вводу и ВСЕГДА фильтровать.

ОБНОВЛЕНИЕ

Я только что обнаружил, что это прекрасно работает при тестировании на таких сайтах, как phpliveregex.com, и локально при анализе обычной строки для utf-8, он не работает должным образом с полями электронной почты, потому что браузеры преобразуют поля этого типа контента в обычную латиницу. Таким образом, адреса электронной почты типа bob@china.中國 или bob@russia.рф перед получением сервером конвертируются в [email protected] или [email protected]. Единственное, чего мне действительно не хватало в моем исходном фильтре, так это включения дефисов из расширения домена.

Вот окончательная версия:

preg_match('/^[a-z0-9%+-._]+@[a-z0-9-.]+\.[a-z0-9-]{2,20}\z/i');
person Vince    schedule 26.02.2016
comment
Это регулярное выражение не позволяет использовать все возможные допустимые адреса электронной почты. См. stackoverflow.com/questions/4816424/ - person deceze♦; 28.07.2016