Как проверить действующий адрес электронной почты?

Есть ли хороший способ проверить ввод формы с помощью регулярного выражения, чтобы убедиться, что это адрес электронной почты правильного стиля? Искал с прошлой ночи, и у всех, кто отвечал на вопросы людей по этой теме, тоже, похоже, есть проблемы с этим, если это адрес электронной почты поддомена.


person Bobby    schedule 05.11.2011    source источник


Ответы (18)


Бессысленно. Даже если вы можете убедиться, что адрес электронной почты синтаксически действителен, вам все равно необходимо убедиться, что он не был введен с ошибкой и что он действительно переходит к тому человеку, который, по вашему мнению, это делает. Единственный способ сделать это - отправить им электронное письмо и попросить их щелкнуть ссылку для подтверждения.

Поэтому обычно достаточно самой простой проверки (например, что они случайно не ввели свой почтовый адрес). Что-то вроде: у него ровно один знак @ и хотя бы один . в части после @:

[^@]+@[^@]+\.[^@]+

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

Если вам нужна полная проверка, просмотрите этот вопрос < / а>.


Обновление: вот как вы можете использовать любое такое регулярное выражение:

import re

if not re.match(r"... regex here ...", email):
  # whatever

Python ≥3.4 имеет re.fullmatch, который предпочтительнее re.match.

Обратите внимание на r перед строкой; таким образом, вам не нужно будет дважды убегать.

Если вам нужно проверить большое количество регулярных выражений, возможно, будет быстрее сначала скомпилировать регулярное выражение:

import re

EMAIL_REGEX = re.compile(r"... regex here ...")

if not EMAIL_REGEX.match(email):
  # whatever

Другой вариант - использовать пакет validate_email, который фактически связывается с сервер SMTP, чтобы убедиться, что адрес существует. Однако это еще не гарантирует, что он принадлежит правильному человеку.

person Thomas    schedule 05.11.2011
comment
Так чем в основном я бы предпочел if not re.match("[^@]+@[^@]+\.[^@]+", email):? - person Bobby; 05.11.2011
comment
Я закончил тем, что сделал if not re.match(r"^[A-Za-z0-9\.\+_-]+@[A-Za-z0-9\._-]+\.[a-zA-Z]*$", email):, поскольку это кажется наиболее правдоподобным сценарием, после которого на указанный адрес было отправлено письмо с подтверждением. - person Bobby; 05.11.2011
comment
+1 за руководство quickie re.match (rxx). Включение того, что необходимо, - признак хорошего ответа. - person JohnnyLambada; 17.11.2012
comment
@ Бобби: пожалуйста немного расслабься. Мне приходилось иметь дело с адресами электронной почты, которые могли быть отфильтрованы (например, с /, видимым в адресах университета). Еще один целый класс, который вы полностью блокируете, - это интернационализированные доменные имена. На самом деле, нет веских причин блокировать действующие адреса электронной почты. Я с неохотой прощаю людей, которые не разрешают адреса электронной почты, такие как 100%." foo b@r"(this is a cool email address!)@(just a tld)com(ok), но я думаю, что проверка на символ @ - это все, что вам нужно (домен верхнего уровня действителен как часть домена, но это маловероятно). - person Chris Morgan; 06.03.2013
comment
Я хотел чего-то более жесткого, чем этот ответ. В частности, без пробелов, не может заканчиваться точкой и соответствует до конца строки. Это должно выявить 99% опечаток. Вот он: EMAIL_REGEX = re.compile(r"[^@\s]+@[^@\s]+\.[^@\s.]+$") - person gaefan; 18.08.2015
comment
Сделаем его даже немного плотнее. Кажется безопасным прямо сейчас ограничить TLD буквенно-цифровыми символами (до сих пор не видел TLD с символами, отличными от ASCII). Используем это сейчас: re.compile(r"[^@\s]+@[^@\s]+\.[a-zA-Z0-9]+$") - person gaefan; 29.08.2015
comment
За исключением того, что "@"@localhost и \@@localhost действительны. - person Julien Palard; 03.10.2016
comment
Мне больше всего нравится этот ответ, однако, если вы хотите добавить большей устойчивости к локальной части письма (до @), сохраняя при этом общее, нет смысла, вы можете сделать что-то вроде: r'[\w!#$%&\'*+-/=?^_`{|}~.]+@[\w\.-]+' - person sponrad; 11.04.2018
comment
захват принятого ответа: взгляните на этот ответ без регулярных выражений с помощью библиотек python, включая проверку наличия в домене сервера smtp и даже опрос сервера smtp, чтобы узнать, существует ли электронное письмо: stackoverflow.com/a/28982264/2327328 - person philshem; 14.09.2018
comment
если кто-то не уверен, [^ @] означает соответствие чему угодно, кроме @. Я сам не был уверен и нашел ответ: @ w3schools не смейтесь! - person joedotnot; 11.04.2019
comment
[^ ‹\ S @] + @ [^ \ s @] + \. [A-zA-Z] +, используя ответ и комментарии, придумал это. Если вы используете SMTP, ваш адрес может быть заключен в квадратные скобки, и вашему адресу может предшествовать имя человека. При этом должен быть извлечен только адрес, без скобок. - person DonkeyKong; 04.06.2019
comment
Одно примечание для fullmatch, в моем случае для писем типа [email protected] он совпадает, но не полностью совпадает. Фактически совпадение равно [email protected], поэтому om опускается. - person milosmns; 28.07.2019
comment
Извините, но у него ровно один знак @ - неверное предположение. - person Snowirbis; 17.11.2020
comment
@Snowirbis Я не знаю RFC, но я никогда не видел практического примера адреса электронной почты с более чем одним @. Если это произойдет, скорее всего, это будет ошибка пользователя (например, пользователь дважды случайно нажал Ctrl + V), чем чей-то реальный адрес электронной почты. - person Thomas; 18.11.2020

Стандартная библиотека Python имеет функцию синтаксического анализа электронной почты: email.utils.parseaddr().

Он возвращает кортеж из двух частей, содержащий настоящее имя и фактический адрес электронной почты:

>>> from email.utils import parseaddr
>>> parseaddr('[email protected]')
('', '[email protected]')

>>> parseaddr('Full Name <[email protected]>')
('Full Name', '[email protected]')

>>> parseaddr('"Full Name with quotes and <[email protected]>" <[email protected]>')
('Full Name with quotes and <[email protected]>', '[email protected]')

И если синтаксический анализ завершился неудачно, он возвращает два кортежа пустых строк:

>>> parseaddr('[invalid!email]')
('', '')

Проблема с этим парсером заключается в том, что он принимает все, что считается допустимым адресом электронной почты для RFC-822 и его друзей, включая многие вещи, которые явно не могут быть адресованы в широком Интернете:

>>> parseaddr('invalid@example,com') # notice the comma
('', 'invalid@example')

>>> parseaddr('invalid-email')
('', 'invalid-email')

Итак, как выразился @TokenMacGuy, единственный окончательный способ проверить адрес электронной почты - это отправить электронное письмо на ожидаемый адрес и дождаться, пока пользователь отреагирует на информацию внутри сообщения.

Однако вы можете проверить хотя бы наличие знака @ на втором элементе кортежа, как предлагает @bvukelic:

>>> '@' in parseaddr("invalid-email")[1]
False

Если вы хотите пойти дальше, вы можете установить проект dnspython и разрешить почтовые серверы для домен электронной почты (часть после '@'), пытается отправить электронное письмо только при наличии реальных MX серверов:

>>> from dns.resolver import query
>>> domain = 'foo@[email protected]'.rsplit('@', 1)[-1]
>>> bool(query(domain, 'MX'))
True
>>> query('example.com', 'MX')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  [...]
dns.resolver.NoAnswer
>>> query('not-a-domain', 'MX')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  [...]
dns.resolver.NXDOMAIN

Вы можете поймать как NoAnswer, так и NXDOMAIN, поймав dns.exception.DNSException.

И да, foo@[email protected] - это синтаксически правильный адрес. Только последний @ следует рассматривать для определения того, где начинается доменная часть.

person LeoRochael    schedule 23.01.2013
comment
@PeterLada: Вы можете просто проверить, есть ли в адресе @ после использования этой функции. - person ; 26.06.2014
comment
@PeterLada, Спасибо за вклад. Исправлено название модуля. - person LeoRochael; 05.02.2015
comment
parseaddr(u"evil@addr") сломает это. - person Yajo; 23.10.2015
comment
@Yajo, как это исправить? evil@addr является таким же действительным адресом электронной почты, как и [email protected], и parseaddr() рассматривает его как таковой. В конце концов, вам всегда нужно будет попробовать отправить электронное письмо на указанный адрес для проверки. - person LeoRochael; 25.10.2015
comment
email.utils.parseaddr анализирует адрес электронной почты, но не проверяет его email.utils.parseaddr('user@@host') возвращает ('', 'user@') - person skoval00; 15.02.2017
comment
@ skoval00, это похоже на ошибку в parseaddr ... вместо этого, я думаю, он должен был быть проанализирован как ('', 'user@@host'). - person LeoRochael; 16.02.2017
comment
@ skoval00, именно это я пробовал: В [8]: parseaddr ('VIRUS ‹virus! @variable.: p›') Out [8]: ('VIRUS', 'virus! @variable.') - person Han.Oliver; 08.09.2018
comment
если я передам неверный адрес: 'doijf oijoij [email protected]', он вернет действительный кортеж из ('', 'doijf oijoij [email protected]'). Как пространство проходит проверку ....? - person DonkeyKong; 04.06.2019

Я не видел ответа здесь среди беспорядка пользовательских ответов Regex, но ...

Существует библиотека Python под названием py3-validate-email < s> validate_email, который имеет 3 уровня проверки электронной почты, включая запрос действительного SMTP-сервера. если адрес электронной почты действительный (без отправки электронного письма).

Установить

python -m pip install py3-validate-email

Основное использование:

from validate_email import validate_email
is_valid = validate_email(email_address='[email protected]', \
    check_regex=True, check_mx=True, \
    from_address='[email protected]', helo_host='my.host.name', \ 
    smtp_timeout=10, dns_timeout=10, use_blacklist=True)

Для тех, кто интересуется грязными деталями, validate_email.py (источник) предназначен соблюдать RFC 2822.

Все, что мы на самом деле делаем, - это сравниваем входную строку с одним гигантским регулярным выражением. Но создание этого регулярного выражения и обеспечение его правильности намного проще, если собрать его из токенов, определенных RFC. Каждый из этих токенов тестируется в прилагаемом файле модульного теста.


вам может понадобиться модуль pyDNS для проверки серверов SMTP.

pip install pyDNS

или из Ubuntu

apt-get install python3-dns
person philshem    schedule 11.03.2015
comment
sudo apt-get python3-dns, похоже, работает на Ubuntu вместо sudo -H pip3 install pyDNS, просто для записи. - person Brōtsyorfuzthrāx; 02.09.2018
comment
Эта вещь возвращает True практически для всего, что я ей бросаю. - person Prof. Falken; 28.09.2018
comment
@ Prof.Falken, к какому из 3 тестов вы имеете в виду (допустимый синтаксис, допустимый smtp, действующий почтовый ящик)? - person philshem; 28.09.2018
comment
@philshem, ну, два более глубоких теста, которые должны пройти на почтовые серверы, оба все время возвращают None. Не знаю почему, я постараюсь исключить, что у меня есть какие-то ограничения в сети, в которой я нахожусь. Простой тест, правильный синтаксис, я могу бросить что угодно, и он скажет, что это хороший синтаксис. Я использовал модуль pip в Python 2. - person Prof. Falken; 28.09.2018
comment
Тот же результат, что и @ Prof.Falken - person Abhishek Balani; 07.03.2019
comment
Это довольно плохой валидатор. Это не для email@examplecom. См. Большой список известных проблем. - person Acumenus; 14.03.2019
comment
Кажется, есть более новая версия для validate_email: pypi.org/project/py3-validate-email. - person Krishnaa; 20.08.2019
comment
Это не очень хорошо работает. github.com/syrusakbary/validate_email/issues/93 github.com/syrusakbary/validate_email/issues/109 - person Vladimir; 24.05.2020
comment
@Vladimir Я обновил ответ, включив в него новый пакет, который кажется более поддерживаемым pypi. org / project / py3-validate-email (спасибо @krishnaa) - person philshem; 25.05.2020
comment
возникли проблемы с pyDNS, пожалуйста, проверьте это сообщение stackoverflow.com/questions/41342551 / error-install-pydns / - person A.HEDDAR; 14.06.2020

Адреса электронной почты не так просты, как кажутся! Например, Bob_O'[email protected] - действительный адрес электронной почты.

Мне повезло с пакетом lepl (http://www.acooke.org/lepl/). Он может проверять адреса электронной почты, указанные в RFC 3696: http://www.faqs.org/rfcs/rfc3696.html

Нашел какой-то старый код:

import lepl.apps.rfc3696
email_validator = lepl.apps.rfc3696.Email()
if not email_validator("[email protected]"):
    print "Invalid email"
person bigendian    schedule 05.11.2011
comment
lepl был снят с производства. - person ; 22.01.2013
comment
Для такого простого случая использования, как это, если текущая версия работает, факт ее прекращения не очень важен. - person Vinko Vrsalovic; 04.07.2013
comment
этот метод не работает, когда вы указываете адрес электронной почты "[email protected]". Он также возвращает значение true для этого имени пользователя. - person Awesome; 29.12.2017
comment
Кажется, что он возвращает False для всего, что я пробовал, независимо от того, действительно ли это. - person Acumenus; 14.03.2019

Я нашел отличный (и проверенный) способ проверить действующий адрес электронной почты. Я вставляю сюда свой код:

# here i import the module that implements regular expressions
import re
# here is my function to check for valid email address
def test_email(your_pattern):
pattern = re.compile(your_pattern)
# here is an example list of email to check it at the end
emails = ["[email protected]", "[email protected]", "wha.t.`1an?ug{}[email protected]"]
for email in emails:
    if not re.match(pattern, email):
        print "You failed to match %s" % (email)
    elif not your_pattern:
        print "Forgot to enter a pattern!"
    else:
        print "Pass"
# my pattern that is passed as argument in my function is here!
pattern = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?"   
# here i test my function passing my pattern
test_email(pattern)
person James The Beard    schedule 06.12.2016
comment
Единственный ответ здесь я вижу здесь. Это проверяет наличие символов, разрешенных в стандартах электронной почты RFC 6531. - person edlee; 29.06.2017
comment
также знак плюса разрешен в части имени пользователя электронной почты - person Mobigital; 25.12.2018
comment
Скопируйте веб-страницу learnpython.org/en/Regular_Expressions .. только проблема 3-е электронное письмо неверно, его недопустимый не может специальный символ. - person KingRider; 18.02.2020
comment
Этот шаблон не допускает использования символа подчеркивания в адресах электронной почты. - person Alex Lach; 10.03.2020

Я вижу здесь много сложных ответов. Некоторые из них не знают простой, истинный адрес электронной почты или имеют ложные срабатывания. Ниже приведен простейший способ проверить, является ли строка действительным адресом электронной почты. Он проверяет двух- и трехбуквенные TLD. Теперь, когда вы технически можете иметь более крупные, вы можете увеличить их с 3 до 4, 5 или даже 10.

import re
def valid_email(email):
  return bool(re.search(r"^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$", email))
person PyTis    schedule 12.05.2017
comment
однако re.match лучше, чем bool(re.search) - person Gahan; 19.06.2017
comment
Это не сработает для электронных писем из Великобритании для записи, они заканчиваются на .co.uk. - person Peter; 01.10.2017
comment
Это не сработает для любых TLD, состоящих более чем из 3 символов. - person kbuilds; 19.03.2018
comment
будет ли это проверять электронные письма, такие как [email protected] (потому что в части имени домена есть 2 точки)? - person Mobigital; 25.12.2018
comment
@Peter Теперь он может справиться с вашим вариантом использования. - person Krissh; 16.09.2019

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

См. Эту страницу для справки: http://www.regular-expressions.info/email.html

person Gaute Løken    schedule 05.11.2011

from validate_email import validate_email
is_valid = validate_email('[email protected]',verify=True)
print(bool(is_valid))

См. документы validate_email.

person ali.etemadi77    schedule 25.03.2018

Адреса электронной почты невероятно сложны. Вот пример регулярного выражения, которое будет соответствовать каждому допустимому адресу RFC822: http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html

Вы заметите, что это, вероятно, длиннее, чем остальная часть вашей программы. Существуют даже целые модули для Perl с целью проверки адресов электронной почты. Таким образом, вы, вероятно, не получите ничего, что было бы на 100% идеальным в качестве регулярного выражения, но при этом было бы читабельным. Вот пример парсера рекурсивного спуска: http://cpansearch.perl.org/src/ABIGAIL/RFC-RFC822-Address-2009110702/lib/RFC/RFC822/Address.pm

но вам нужно решить, нужен ли вам идеальный синтаксический анализ или простой код.

person Dan    schedule 05.11.2011

Если вы хотите извлечь почту из длинной строки или файла, попробуйте это.

([^@|\s]+@[^@]+\.[^@|\s]+)

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

Рабочий пример:

string="Hello ABCD, here is my mail id [email protected] "
res = re.search("([^@|\s]+@[^@]+\.[^@|\s]+)",string,re.I)
res.group(1)

Это уберет [email protected] из этой строки.

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

person Raj Chinna    schedule 05.11.2014
comment
´re.match (([^ @ | \ s] + @ [^ @] + \. [^ @ | \ S] +), электронная почта) ´ отлично работает - person palsch; 14.12.2014

Для проверки электронной почты используйте email_validator.

from email_validator import validate_email, EmailNotValidError

def check_email(email):
    try:
        v = validate_email(email)  # validate and get info
        email = v["email"]  # replace with normalized form
        print("True")
    except EmailNotValidError as e:
        # email is not valid, exception message is human-readable
        print(str(e))

check_email("test@gmailcom")
person Vladislav Koshenevskiy    schedule 10.01.2018
comment
Может быть полезно понять практическое предназначение этого пакета: эта библиотека проверяет, имеет ли строка форму [email protected]. Это тот вид проверки, который вам нужен для формы входа на веб-сайт на основе электронной почты. - person dat; 13.02.2021

Используйте эту маску фильтра при вводе электронной почты: emailMask: /[\w.\-@'"!#$%&'*+/=?^_ {|} ~] / i`

person Dilip Paudel    schedule 12.02.2019

Поиск идентификатора электронной почты: поиск снимка экрана IP

import re 
a=open("aa.txt","r")
#c=a.readlines() 
b=a.read()
c=b.split("\n")
print(c)
  for d in c: 
    obj=re.search(r'[\w.]+\@[\w.]+',d)
    if obj:
      print(obj.group())  
#for more calcification click on image above..
person Mani    schedule 09.08.2017
comment
Измените код, чтобы отступ был правильным, удалите номера строк и нажмите ctrl + K с кодом, выбранным для его форматирования. - person Athena; 09.08.2017

Нашел, что это практическая реализация:

[^@\s]+@[^@\s]+\.[^@\s]+
person juan Isaza    schedule 12.09.2018
comment
[^@\s]+@[^@\s]+\.[^@\s]+ Это неверно, потому что это позволит использовать пробелы в части расширения .c om, а пробелы в электронных письмах не допускаются. - person WayBehind; 17.04.2020
comment
нет, он не допускает этих пробелов, поэтому последняя часть имеет \ s. пример: re.findall (r '[^ @ \ s] + @ [^ @ \ s] + \. [^ @ \ s] +','john@smith. в этом есть пробелы ') = [' john @ smith .это'] - person juan Isaza; 20.04.2020
comment
РЕДАКТИРОВАТЬ: Я использовал r.match и re.compile для тестирования, а не re.findall, поэтому, возможно, мы оба правы, если используются по назначению. К сожалению, вы не предоставили никаких подробностей в своем ответе, и поэтому он был открыт для недопонимания. Если вы отредактируете свой ответ, я смогу убрать голос против. К сожалению, без редактирования вашего ответа система не позволит мне изменить свой голос. - person WayBehind; 20.04.2020

проверка электронной почты

import re
def validate(email): 
    match=re.search(r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9]+\.[a-zA-Z0-9.]*\.*[com|org|edu]{3}$)",email)
    if match:
        return 'Valid email.'
    else:
        return 'Invalid email.'
person Gaurav Nagpure    schedule 21.10.2016

Единственный действительно точный способ отличить действительные действительные адреса электронной почты от недействительных - это отправить на него почту. То, что считается электронной почтой, на удивление запутано ("John Doe" <[email protected]>" на самом деле является действительным адресом электронной почты), и вы, скорее всего, захотите, чтобы адрес электронной почты действительно отправлял на него почту позже. После того, как он пройдет некоторые базовые проверки работоспособности (например, в ответе Томаса есть @ и хотя бы один . после @), вам, вероятно, следует просто отправить письмо с подтверждением по электронной почте на адрес и дождаться, пока пользователь перейдет по встроенной ссылке в сообщении, чтобы подтвердить, что адрес электронной почты действителен.

person SingleNegationElimination    schedule 05.11.2011

person    schedule
comment
Хороший, но я думаю, что файл. перед тем, как TLD нужно будет экранировать как \. - person Simon Steinberger; 24.11.2014

person    schedule
comment
Как правило, ответы, особенно на вопросы, связанные с регулярными выражениями, гораздо более полезны, если они включают довольно подробное объяснение того, для чего предназначен код или регулярное выражение, и почему это решает проблему, не вводя других. Это еще более важно для того, что откровенно подвержено ошибкам и неудобно, как проверка адреса электронной почты; Я видел по крайней мере одно регулярное выражение, которое для этой цели было длиной на всю страницу и было без незначительных пробелов. - person Nathan Tuggy; 11.02.2015
comment
Это кажется полезным: return re.search("^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$", email) != None - person Vladimir; 24.05.2020