135

我遇到了这个PHP 代码来使用 SMTP 检查电子邮件地址而不发送电子邮件

有没有人尝试过类似的东西或者它对你有用吗?您能判断电子邮件客户/用户输入是否正确且存在吗?

4

14 回答 14

102

您有时可以使用两种方法来确定收件人是否实际存在:

  1. 您可以连接到服务器,并发出VRFY命令。很少有服务器支持此命令,但它正是为此而设计的。如果服务器以 2.0.0 DSN 响应,则用户存在。

    VRFY user
    
  2. 您可以发出RCPT, 并查看邮件是否被拒绝。

    MAIL FROM:<>
    RCPT TO:<user@domain>
    

如果用户不存在,您将获得 5.1.1 DSN。但是,仅仅因为电子邮件没有被拒绝,并不意味着用户存在。一些服务器会默默地丢弃这样的请求,以防止枚举其用户。其他服务器无法验证用户,并且无论如何都必须接受该消息。

还有一种称为灰名单的反垃圾邮件技术,它会导致服务器最初拒绝该地址,预计真正的 SMTP 服务器会在一段时间后尝试重新发送。这会打乱验证地址的尝试。

老实说,如果您尝试验证地址,最好的方法是使用简单的正则表达式来阻止明显无效的地址,然后将带有链接的实际电子邮件发送回您的系统,以验证电子邮件是否已收到。这也确保了他们的用户输入了他们的实际电子邮件,而不是碰巧属于其他人的轻微错字。

于 2009-02-19T16:33:27.683 回答
53

此处的其他答案讨论了尝试执行此操作的各种问题。我想我会展示你如何尝试这个,以防你想自己学习。

您可以通过 telnet 连接到邮件服务器以询问是否存在电子邮件地址。下面是一个测试电子邮件地址的示例stackoverflow.com

C:\>nslookup -q=mx stackoverflow.com
非权威答案:
stackoverflow.com MX 偏好 = 40,邮件交换器 = STACKOVERFLOW.COM.S9B2.PSMTP.com
stackoverflow.com MX 首选项 = 10,邮件交换器 = STACKOVERFLOW.COM.S9A1.PSMTP.com
stackoverflow.com MX 首选项 = 20,邮件交换器 = STACKOVERFLOW.COM.S9A2.PSMTP.com
stackoverflow.com MX 首选项 = 30,邮件交换器 = STACKOVERFLOW.COM.S9B1.PSMTP.com

C:\>telnet STACKOVERFLOW.COM.S9A1.PSMTP.com 25
220 Postini ESMTP 213 y6_35_0c4 准备就绪。CA Business and Professions Code Section 17538.45 禁止将此系统用于未经请求的电子邮件广告。

你好你好
250 Postini 回击打招呼

来自:<me@myhost.com> 的邮件
250 好的

转至:<fake@stackoverflow.com>
550-5.1.1 您尝试访问的电子邮件帐户不存在。请试试
550-5.1.1 仔细检查收件人的电子邮件地址是否有错别字或
550-5.1.1 不必要的空格。了解更多信息
550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596 w41si3198459wfd.71

以数字代码为前缀的行是来自 SMTP 服务器的响应。我添加了一些空白行以使其更具可读性。

许多邮件服务器不会返回此信息以防止垃圾邮件发送者收集电子邮件地址,因此您不能依赖此技术。但是,您可能会通过检测无效邮件服务器或如上所述拒绝收件人地址来清除一些明显不良的电子邮件地址。

另请注意,如果您向邮件服务器发出过多请求,邮件服务器可能会将您列入黑名单。


在 PHP 中,我相信您可以使用fsockopen,fwritefread以编程方式执行上述步骤:

$smtp_server = fsockopen("STACKOVERFLOW.COM.S9A1.PSMTP.com", 25, $errno, $errstr, 30);
fwrite($smtp_server, "helo hi\r\n");
fwrite($smtp_server, "mail from: <me@myhost.com>\r\n");
fwrite($smtp_server, "rcpt to: <fake@stackoverflow.com>\r\n");
于 2010-12-18T16:09:38.087 回答
10

一般的答案是,如果您向其发送电子邮件,则无法检查电子邮件地址是否存在事件:它可能会进入黑洞。

话虽如此,那里描述的方法非常有效。它在ZoneCheck的生产代码中使用,但它使用 RSET 而不是 QUIT。

在用户与其邮箱的交互成本不高的情况下,许多站点实际上通过发送一个必须发送回发送器的秘密号码来测试邮件是否到达某处(通过转到秘密 URL 或通过电子邮件发送回这个秘密号码)。大多数邮件列表都是这样工作的。

于 2009-02-19T14:27:08.463 回答
8

当目标邮件服务器使用灰名单时,这将失败(在其他情况下)。

灰名单:SMTP 服务器在以前未知的客户端第一次连接时拒绝传递,允许下次连接;这可以阻止一定比例的垃圾邮件程序,同时允许合法使用 -因为预计合法的邮件发件人会重试,这是普通邮件传输代理会做的事情。

但是,如果您的代码只在服务器上检查一次,带有灰名单的服务器将拒绝交付(因为您的客户端是第一次连接);除非您稍后再次检查,否则您可能会错误地拒绝有效的电子邮件地址。

于 2011-05-20T17:38:33.473 回答
6

不是真的.....有些服务器可能不会检查“rcpt to:”

http://www.freesoft.org/CIE/RFC/1123/92.htm

这样做有安全风险......

如果服务器这样做,您可以编写一个机器人来发现服务器上的每个地址......

于 2009-02-19T14:26:19.527 回答
5

一些问题:

  1. 我敢肯定,如果您提供的地址不存在,某些 SMTP 服务器会立即通知您,但有些不会作为隐私措施。他们只会接受你给他们的任何地址,并默默地忽略那些不存在的地址。
  2. 正如文章所说,如果您经常对某些服务器执行此操作,他们会将您列入黑名单。
  3. 对于某些 SMTP 服务器(如 gmail),您需要使用 SSL 才能执行任何操作。 仅当使用 gmail 的 SMTP 服务器发送电子邮件时才适用。
于 2009-02-19T14:27:38.637 回答
4

我可以确认 Joseph 和 Drew 的使用答案RCPT TO: <address_to_check>。我想在这些答案之上添加一些小附录。

包罗万象的供应商

一些邮件提供商实施包罗万象的策略,这意味着*@mydomain.com将对RCPT TO:命令返回肯定的结果。但这并不一定意味着邮箱“存在”,如“属于人类”。这里没有什么可以做的,只是要注意。

IP灰名单/黑名单

灰名单:来自未知 IP 的第一个连接被阻止。解决方法:至少重试2次。

黑名单:如果您从同一 IP 发送的请求过多,则该 IP 被阻止。解决方案:使用IP轮换。

注册表单上的 HTTP 请求

这是非常特定于提供商的,但您有时可以使用精心设计的 HTTP 请求,并解析这些请求的响应,以查看用户名是否已在此提供商处注册。

*@yahoo.com这是我为使用 HTTP 请求检查地址而编写的开源库中的相关函数: check-if-email-exists。我知道我的代码是 Rust 并且这个线程被标记为 PHP,但同样的想法也适用。

完整收件箱

这可能是一种极端情况,但是当用户的收件箱已满时,RCTP TO:将返回一条5.1.1 DSN错误消息,说明收件箱已满。这意味着该帐户确实存在!

披露

我运行 [Reacher][1],一个实时电子邮件验证 API。我的代码是用 Rust 编写的,并且是 100% 开源的。如果您想要更强大的解决方案,请查看它:

Github:https ://github.com/reacherhq/check-if-email-exists

通过结合各种技术来跳过障碍,我设法验证了大约 80% 的客户检查的电子邮件。

于 2020-06-14T11:45:28.953 回答
3

您所能做的就是搜索 DNS 并确保电子邮件地址中的域具有 MX 记录,除此之外没有可靠的处理方法。

某些服务器可能使用 rcpt-to 方法与 SMTP 服务器通信,但这完全取决于服务器的配置。另一个问题可能是过载的服务器可能返回一个 550 代码说用户未知,但这是一个临时错误,有一个可以返回的永久错误(我认为是 451?)。这完全取决于服务器的配置。

我个人会检查 DNS MX 记录,如果 MX 记录存在,则发送电子邮件验证。

于 2009-02-19T15:47:58.330 回答
3
function EmailValidation($email)
{
    $email = htmlspecialchars(stripslashes(strip_tags($email))); //parse unnecessary characters to prevent exploits
    if (eregi('[a-z||0-9]@[a-z||0-9].[a-z]', $email)) {
        //checks to make sure the email address is in a valid format
        $domain = explode( "@", $email ); //get the domain name
        if (@fsockopen ($domain[1],80,$errno,$errstr,3)) {
            //if the connection can be established, the email address is probably valid
            echo "Domain Name is valid ";
            return true;
        } else {
            echo "Con not a email domian";
            return false; //if a connection cannot be established return false
        }
        return false; //if email address is an invalid format return false
    }
}
于 2014-02-11T07:02:57.787 回答
3

虽然这个问题有点老了,但这个服务提示可能会帮助用户搜索类似的解决方案,在发送之前检查超出语法验证的电子邮件地址。

我一直在使用这个开源服务来更深入地验证电子邮件(检查电子邮件地址域上的 mx 记录等),并为一些项目取得了良好的效果。它还检查常见的拼写错误,这非常有用。演示在这里

于 2016-06-16T07:25:41.630 回答
2

“您能判断电子邮件客户/用户输入是否正确且存在吗?”

其实这是两个不同的东西。它可能存在,但可能不正确。

有时您必须以表面价值接受用户输入。否则有很多方法可以击败系统。

于 2009-02-19T14:41:17.650 回答
2

假设它是用户的地址,一些邮件服务器确实允许 SMTP VRFY 命令根据其邮箱实际验证电子邮件地址。大多数主要网站不会为您提供太多信息;gmail 的回复是“如果您尝试邮寄,我们会尝试发送”或类似的巧妙内容。

于 2009-02-19T15:02:59.470 回答
1

我认为您不能,在很多情况下,即使发送电子邮件也会失败。例如。用户端的邮件服务器暂时宕机、邮箱存在但已满无法投递等。

这可能就是为什么这么多网站在用户确认他们收到确认电子邮件后验证注册的原因。

于 2009-02-19T15:07:10.960 回答
-11
<?php

   $email = "someone@exa mple.com";

   if(!filter_var($email, FILTER_VALIDATE_EMAIL))
      echo "E-mail is not valid";
   else
      echo "E-mail is valid";

?>
于 2014-12-02T05:33:02.857 回答