Может ли это повредить проверку адресов электронной почты с помощью регулярных выражений?
Я слышал, что проверять адреса электронной почты с помощью регулярных выражений - это плохо, и это действительно может причинить вред. Это почему? Я думал, что это никогда не может быть плохо для проверки данных. Может быть ненужным, но никогда не плохим, если вы правильно выполняете проверку. Не могли бы вы объяснить мне, почему это правильно или неправильно? Если это может причинить вред, приведите пример.
7 ответов
В общем, да - использование регулярных выражений для проверки адресов электронной почты вредно. Это из-за неправильных (неправильных) предположений автора регулярного выражения.
Как указал @klutt, адрес электронной почты состоит из двух частей: local-part
и domain
, Стоит отметить некоторые вещи об этих частях, которые не сразу очевидны:
local-part
может содержать экранированные символы и даже дополнительные@
персонажи.local-part
может быть чувствительным к регистру, однако почтовый сервер в этом конкретном домене должен определять регистр.domain
часть может содержать ноль или более меток, разделенных точкой (.
), хотя на практике нет записей MX, соответствующих корню (нулевые метки) или самим рДВУ (одна метка).
Итак, есть несколько проверок, которые вы можете сделать, не отклоняя действительные адреса электронной почты, которые соответствуют вышеуказанному:
- Адрес содержит хотя бы один
@
local-part
(все слева от самого правого@
) непустоdomain
часть (все справа от самого правого@
) содержит хотя бы один период (опять же, это не совсем верно, но прагматично)
Вот и все. Как уже отмечали другие, рекомендуется проверять доставку по этому адресу. Это установит две важные вещи:
- Существует ли электронная почта в настоящее время; а также
- То, что пользователь имеет доступ к адресу электронной почты (является законным пользователем или владельцем)
Если вы встраиваете процессы активации электронной почты в свой бизнес-процесс, вам не нужно беспокоиться о сложных регулярных выражениях, которые имеют проблемы.
Некоторое дальнейшее чтение для справки:
Создание регулярных выражений для проверки писем может быть хорошим и увлекательным упражнением, но в целом вы должны действительно избегать этого в рабочем коде.
В большинстве случаев, когда вы захотите использовать это, просто знать, что адрес электронной почты является действительным, не значит ничего. Что вы действительно хотите знать, так это правильный адрес электронной почты. Правильный способ проверить это - отправить письмо со ссылкой для подтверждения.
Если вы подтвердили адрес электронной почты с помощью ссылки подтверждения, часто нет смысла проверять, является ли это правильный адрес электронной почты, поскольку вы знаете, что он работает. Однако его можно использовать для проверки того, что пользователь вводит адрес электронной почты в правильном поле. Мой совет в этом случае должен быть чрезвычайно прощающим. Я бы сказал, что достаточно просто проверить, что это @ в поле. Это простая проверка, и ВСЕ адреса электронной почты включают @. Если вы хотите сделать его более сложным, я бы рекомендовал просто предупредить пользователя, что с адресом может быть что-то не так, но не запрещать его.
Но хуже всего то, что регулярное выражение для точной проверки адреса электронной почты на самом деле очень сложный вопрос. Если вы попытаетесь создать регулярное выражение самостоятельно, вы почти наверняка сделаете ошибки. Здесь стоит упомянуть, что стандарт rfc5322 допускает комментарии в скобках. Что еще хуже, вложенные комментарии допускаются. Стандартное регулярное выражение не может соответствовать вложенным шаблонам. Вам понадобится расширенное регулярное выражение для этого. Хотя расширенные регулярные выражения не являются чем-то необычным, они говорят о сложности. И даже если вы поймете это правильно, вы обновите регулярное выражение, когда появится новый стандарт?
И еще одна вещь, даже если вы сделаете это на 100% правильно, этого все же может быть недостаточно. Адрес электронной почты имеет локальную часть слева от @ и часть домена справа. Все в локальной части предназначено для обработки сервером. Конечно, RFC 5322 довольно подробно описывает, как выглядит действительная локальная часть, но что, если конкретный почтовый сервер принимает адреса, которые недопустимы в соответствии с rfc5322? Вы действительно уверены, что не хотите разрешить определенный адрес электронной почты, который работает только потому, что он не соответствует стандарту? Хотите ли вы потерять клиентов за ваш бизнес только потому, что они выбрали малоизвестного почтового провайдера?
Если вы действительно хотите проверить правильность адреса в рабочем коде, используйте класс MailAddress или что-то подобное. Но сначала подумайте, действительно ли это то, что вы хотите. Спросите себя, имеет ли адрес какое-либо значение, если это не правильный адрес. Если ответ отрицательный, то нет. Вместо этого используйте ссылки для подтверждения.
Это, как говорится, может быть хорошей вещью для проверки ввода. Важно знать, почему вы это делаете. Подтверждение электронной почты с помощью регулярного выражения или (предпочтительно) что-то вроде Mailaddress
класс может дать некоторую защиту от вредоносного ввода, такого как SQL-инъекции и тому подобное. Но если это единственный способ защитить вас от злонамеренного ввода, значит, вы делаете что-то совсем другое.
В дополнение к другим ответам я хотел бы отметить, что движки Regex подвержены ReDOS - атакам типа "отказ в обслуживании". Атака основана на том факте, что многие нетривиальные регулярные выражения имеют входные данные, для которых может потребоваться необычайное количество циклов ЦП, чтобы произвести несовпадение.
Создание такого входа может вызвать проблемы с доступностью сайта даже при небольшом ботнете.
Для получения дополнительной информации "Атаки с использованием регулярных выражений в обслуживании (ReDOS)": https://dzone.com/articles/regular-expressions-denial
Проверка почтовых адресов по своей сути не так уж и плоха.
Даже неплохо проверять адреса электронной почты с помощью регулярных выражений... хотя, возможно, есть и более эффективные способы их проверки.
Реальные проблемы в том, что проверка адресов электронной почты (на основе синтаксиса):
- не сообщает, соответствует ли адрес действующему рабочему почтовому ящику, и
- не говорит вам, если это адрес для правильного пользователя (или агента).
Так как пользователи случайно (или намеренно) используют неправильные адреса электронной почты для различных целей, вам нужно сделать что-то еще, если вам нужно знать, правильный ли адрес; например, отправьте какое-нибудь электронное письмо с активацией на адрес.
Итак, при условии, что вы собираетесь реализовать второй этап проверки, первый этап относительно не важен. Возможно, даже ненужный.
Я слышал, что проверять адреса электронной почты с помощью регулярных выражений - это плохо, и это действительно может причинить вред. Это почему?
Это правильно. Решение regex привлекательно, потому что адрес электронной почты является структурированной строкой, а regex используется для поиска структуры в строках.
Это также неправильное решение, потому что когда вы спрашиваете у пользователя адрес электронной почты, обычно вы можете связаться с ним.
Проверка неверна, потому что:
адрес может быть действительным, но не адрес, к которому у пользователя есть доступ. Я мог бы заполнить адрес
billgates@microsoft.com
в любой форме, и он, вероятно, будет принят в качестве действительного адреса электронной почты (отказ от ответственности: я не Билл Гейтс:)).синтаксис для адресов электронной почты очень сложно получить правильно (см. примеры здесь) - определив свой собственный регулярное выражение для проверки электронной почты, вы в конечном итоге отклоните действительные адреса и примете недействительные.
Я думал, что это никогда не может быть плохо для проверки данных.
Это не плохо для проверки данных. Однако в этом случае вы предоставите в своем приложении функцию, которая является дефектной по своей структуре:
Ваше приложение выглядит для ваших разработчиков так, как будто оно проверяет входные данные, но проверка не является необходимой, возможно, неполной, и в конце проверки вы не знаете, есть ли у вас адрес, который позволит вам связаться с пользователем.
Может быть ненужным, но никогда не плохим, если вы правильно выполняете проверку.
Это не ненужно, это необходимо. Просто регулярное выражение не подходит для этого.
В конце концов, лучший способ проверить, является ли адрес действительным для пользователя, - это уникальный обмен токенами для этого адреса:
- отправить электронное письмо на адрес, содержащий уникальный случайный токен (хранить токен с данными пользователя)
- попросите пользователя в электронном письме "щелкнуть ссылку / кнопку", чтобы отправить вам токен обратно.
- проверьте токен.
Если ваше регулярное выражение плохо сформировано, вы можете отказать в действительных адресах электронной почты. Это относится к любому правилу "проверки электронной почты".
Я знаю адрес электронной почты, который регулярно опровергается формами, в которых нет никаких странностей; это просто долго. Это действительно раздражает человека, которому он принадлежит, потому что часть до @
это их официальное название - очевидный выбор для адреса электронной почты.
Это является частью потенциального вреда неправильной проверки электронной почты: раздражает пользователей, отказывая в доступе действительным адресам электронной почты.
Регекс не вреден.
Используйте хорошее регулярное выражение электронной почты, чтобы отфильтровать нетерпеливого фальшивого пользователя.
Если вы продаете этому человеку, вы можете связаться с ним
для дальнейшей проверки, хотя продавцы не слишком заботятся об электронной почте
и просто проверка кредитной карты достаточно хороша для них.
В противном случае единственное место, где необходима проверка, это когда
кто-то хочет получить доступ и взаимодействовать с вашим форумом, и по какой-то причине
Вы хотите получать вознаграждение, продавая свою электронную почту массовым рекламодателям,
даже если вы говорите, что не будете этого делать.
Общее регулярное выражение электронной почты в спецификации html5 таково:
^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
http://www.w3.org/TR/html5/forms.html
^
[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+
@
[a-zA-Z0-9]
(?:
[a-zA-Z0-9-]{0,61}
[a-zA-Z0-9]
)?
(?:
\.
[a-zA-Z0-9]
(?:
[a-zA-Z0-9-]{0,61}
[a-zA-Z0-9]
)?
)*
$
Регулярное выражение, вероятно, лучший способ проверить адрес электронной почты; пока вы используете правильный. После того, как вы проверили адрес с помощью регулярного выражения, необходимо проверить лишь несколько дополнительных требований (адрес не слишком длинный и является допустимым UTF-8).
Это связано с тем, что грамматика ABNF, определяющая форму адресов электронной почты, является "регулярной", что означает, что ее можно описать точно как регулярное выражение; без возврата, рекурсии или каких-либо нестандартных функций.
Это только вопрос понимания спецификации; но как только вы это сделаете, оказывается, что регулярное выражение для адреса электронной почты на самом деле очень простое: как проверить адрес электронной почты с помощью регулярного выражения?