如何查看有效的电子邮件地址?

Bob*_*bby 179 python regex email-address email-validation

是否有一种很好的方法来检查表单输入使用正则表达式,以确保它是一个正确的样式电子邮件地址?自昨晚以来一直在搜索,如果这是一个子网站的电子邮件地址,那么回答人们关于这个主题的问题的每个人似乎都有问题.

Tho*_*mas 255

无关紧要.即使您可以验证电子邮件地址在语法上是否有效,您仍然需要检查它是否输入错误,并且它实际上是发送给您认为它的人.唯一的方法是向他们发送电子邮件,让他们点击链接进行验证.

因此,最基本的检查(例如,他们没有意外地输入他们的街道地址)通常就足够了.类似的东西:它只有一个@符号,并且在.后面的部分中至少有一个符号@:

[^@]+@[^@]+\.[^@]+
Run Code Online (Sandbox Code Playgroud)

您可能也想要禁止空格 - 可能有效的电子邮件地址中包含空格,但我从未见过它,因此这是用户错误的可能性就在您身边.

如果您想要全面检查,请查看此问题.


更新:以下是如何使用任何此类正则表达式:

import re

if not re.match(r"... regex here ...", email):
  # whatever
Run Code Online (Sandbox Code Playgroud)

注意re.fullmatch字符串前面; 这样,你就不需要两次逃避.

如果要检查大量的正则表达式,首先编译正则表达式可能会更快:

import re

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

if not EMAIL_REGEX.match(email):
  # whatever
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用re.match实际联系SMTP服务器的包来验证该地址是否存在.但这并不能保证它属于合适的人选.

  • @Bobby:*请*放松一下.我不得不处理过滤掉的电子邮件地址(例如,在大学的地址中看到`/`).您完全阻止的另一个完整类是国际化域名.实际上,没有充分理由阻止有效的电子邮件地址.我会不情愿地原谅那些不允许电子邮件地址的人,比如'100%.'foo b @ r"(这是一个很酷的电子邮件地址!)@(只是一个tld)com(ok)`,但我觉得这个检查对于一个`@`符号来说,你真的应该拥有(顶级域名作为域名部分是有效的,但这是不可能的). (21认同)
  • 我最后做了`如果不是re.match(r"^ [A-Za-z0-9 \.\ + _-] + @ [A-Za-z0-9\._-] + \.[a- zA-Z]*$",电子邮件):"因为这似乎是最合理的情况,然后向给定地址发送验证电子邮件. (15认同)
  • 让它更紧一点。现在将 TLD 限制为字母数字似乎是安全的(仍然没有看到具有非 ASCII 字符的 TLD)。现在使用:`re.compile(r"[^@\s]+@[^@\s]+\.[a-zA-Z0-9]+$")` (2认同)
  • @Snowirbis,我不了解 RFC,但我从未见过包含多个“@”的电子邮件地址的_实用_示例。如果确实发生这种情况,则更有可能是用户错误(例如,用户意外按了 Ctrl+V 两次),而不是某人的实际电子邮件地址。 (2认同)

Leo*_*ael 114

Python标准库附带了一个电子邮件解析功能:email.utils.parseaddr().

它返回一个包含真实姓名和电子邮件实际地址部分的两元组:

>>> from email.utils import parseaddr
>>> parseaddr('foo@example.com')
('', 'foo@example.com')

>>> parseaddr('Full Name <full@example.com>')
('Full Name', 'full@example.com')

>>> parseaddr('"Full Name with quotes and <weird@chars.com>" <weird@example.com>')
('Full Name with quotes and <weird@chars.com>', 'weird@example.com')
Run Code Online (Sandbox Code Playgroud)

如果解析不成功,它将返回一个两元组的空字符串:

>>> parseaddr('[invalid!email]')
('', '')
Run Code Online (Sandbox Code Playgroud)

这个解析器的一个问题是它接受任何被认为是RFC-822和朋友的有效电子邮件地址的东西,包括许多在广泛的互联网上无法解决的东西:

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

>>> parseaddr('invalid-email')
('', 'invalid-email')
Run Code Online (Sandbox Code Playgroud)

因此,正如@TokenMacGuy所说,检查电子邮件地址的唯一确定方法是将电子邮件发送到预期地址,并等待用户对邮件内的信息进行操作.

但是,您可能想要检查,至少在第二个元组元素上是否存在@ -sign,正如@bvukelic建议的那样:

>>> '@' in parseaddr("invalid-email")[1]
False
Run Code Online (Sandbox Code Playgroud)

如果您想更进一步,可以安装dnspython项目并解析电子邮件域的邮件服务器("@"之后的部分),只有在有实际MX服务器时才尝试发送电子邮件:

>>> from dns.resolver import query
>>> domain = 'foo@bar@google.com'.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
Run Code Online (Sandbox Code Playgroud)

你可以抓住两者NoAnswerNXDOMAIN抓住dns.exception.DNSException.

是的,foo@bar@google.com是一个语法上有效的地址.只@应考虑最后一个来检测域部分的起始位置.

  • @PeterLada:你可以在使用这个函数后检查地址中是否有`@`. (5认同)
  • email.utils.parseaddr解析电子邮件地址但不验证它`email.utils.parseaddr('user @@ host')`产生`('','user @')` (4认同)
  • @Yajo,"打破这个"怎么样?`evil @ addr`就像`nonxistinglogin @ valid-domain.com`一样有效的电子邮件地址,并被`parseaddr()`视为有效.最后,您始终需要尝试向提供的地址发送电子邮件以进行验证. (3认同)

phi*_*hem 62

我还没有在自定义正则表达式的答案中找到答案,但......

Python有一个名为validate_email的模块,它有3个级别的电子邮件验证,包括询问有效的SMTP服务器,如果电子邮件地址有效(不发送电子邮件).

检查邮件字符串是否有效格式:

from validate_email import validate_email
is_valid = validate_email('example@example.com')
Run Code Online (Sandbox Code Playgroud)

检查主机是否具有SMTP服务器:

is_valid = validate_email('example@example.com',check_mx=True)
Run Code Online (Sandbox Code Playgroud)

检查主机是否有SMTP服务器并且电子邮件确实存在:

is_valid = validate_email('example@example.com',verify=True)
Run Code Online (Sandbox Code Playgroud)

对于那些对脏细节感兴趣的人,validate_email.py(source)旨在忠实于RFC 2822.

我们所做的只是将输入字符串与一个巨大的正则表达式进行比较.但是,通过从RFC定义的"标记"中组装它,可以更容易地构建该正则表达式并确保其正确性.这些令牌中的每一个都在随附的单元测试文件中进行测试.


用pip安装

pip install validate_email
Run Code Online (Sandbox Code Playgroud)

你需要pyDNS模块来检查SMTP服务器

pip install pyDNS
Run Code Online (Sandbox Code Playgroud)

或者来自Ubuntu

apt-get python3-dns
Run Code Online (Sandbox Code Playgroud)

  • 对于我扔给它的任何东西,该东西都会返回“ True”。 (4认同)
  • @philshem,嗯,应该发送到邮件服务器的两个更深入的测试都始终返回“ None”。不知道为什么,我将尝试排除我对所使用的网络有某种限制。简单的测试,有效的语法,我几乎可以抛出任何东西,它将说这是很好的语法。我在Python 2中使用了pip模块。 (4认同)
  • 与@ Prof.Falken相同的结果 (2认同)
  • 这是一个非常糟糕的验证器。`email@examplecom` 失败。请参阅已知[问题](https://github.com/syrusakbary/validate_email/issues)的大列表。 (2认同)

big*_*ian 21

电子邮件地址并不像看起来那么简单!例如,Bob_O'Reilly+tag@example.com是有效的电子邮件地址.

我在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@example.com"):
    print "Invalid email"
Run Code Online (Sandbox Code Playgroud)

  • `lepl`现已停止使用. (13认同)
  • 对于这样一个简单的用例,如果当前版本工作,它停止的事实并不是很相关. (2认同)

小智 11

我发现了一种检查有效电子邮件地址的优秀(且经过测试)方法.我在这里粘贴代码:

# 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 = ["john@example.com", "python-list@python.org", "wha.t.`1an?ug{}ly@email.com"]
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)
Run Code Online (Sandbox Code Playgroud)

  • 此模式不允许在电子邮件地址中使用下划线字符。 (4认同)
  • 我在这里看到唯一的答案.检查[RFC 6531](https://tools.ietf.org/html/rfc6531)电子邮件标准中允许的字符. (3认同)

PyT*_*Tis 10

我在这看到很多复杂的答案.他们中的一些人,不了解简单,真实的电子邮件地址,或有误报.下面是测试字符串是否是有效电子邮件的最简单方法.它测试2和3个字母TLD.既然你在技术上可以有更大的那个,你可能希望增加3到4,5或甚至10.

import re
def valid_email(email):
  return bool(re.search(r"^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$", email))
Run Code Online (Sandbox Code Playgroud)

  • 这不适用于英国电子邮件的记录,它们以`.co.uk`结尾. (3认同)
  • 但是`re.match`优于`bool(re.search)` (2认同)
  • 这不适用于任何超过3个字符的TLD (2认同)

Mit*_*hon 5

这通常使用正则表达式解决。然而,解决方案有很多种。取决于您需要的严格程度,以及您是否对验证有自定义要求,或者是否接受任何有效的电子邮件地址。

请参阅此页面以供参考:http : //www.regular-expressions.info/email.html


Dan*_*Dan 5

电子邮件地址非常复杂。以下是一个示例正则表达式,它将匹配每个 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

但您需要决定是否需要完美的解析或简单的代码。


小智 5

from validate_email import validate_email
is_valid = validate_email('example@example.com',verify=True)
print(bool(is_valid))
Run Code Online (Sandbox Code Playgroud)

请参阅validate_email 文档