PHP - 检测电子邮件是否发送

14

我正在构建一个自动化的新闻简报,目前遇到了一些问题。我需要知道邮件是否已发送。以下是我的代码:

 @$send = mail($emailRecipient, $subject, $message, $headers);

我尝试将它添加到if语句中,但它在这里无效,以下是代码。

if( @$send = mail($emailRecipient, $subject, $message, $headers)){
   //do something
}else{
  //do something
}

1
在发送邮件时,在邮件函数前加上@符号,例如:$send = @mail(....) - Bhavik Shah
3
mail 文档中可以得知:如果邮件成功被接收并且准备发送,则返回TRUE,否则返回FALSE。需要注意的是,即使成功接收邮件并准备发送,也不意味着邮件一定会到达目的地。换句话说,你无法使用PHP检测电子邮件是否已经发送。 - Gordon
-1 表示“它给了我一个错误”,但没有说明是哪个。 - Gordon
edited sorry for that! :) - Kiel
我认为问题在于您正在检查$send是否被设置为邮件的输出,而无论邮件是否成功发送,这都将始终为真。需要做的是要么只将mail()语句放在条件中,要么在if语句之前设置$send = mail();并将$send放在条件中。 - EM-Creations
7个回答

33
if(@mail($emailRecipient, $subject, $message, $headers))
{
  echo "Mail Sent Successfully";
}else{
  echo "Mail Not Sent";
}

还需要等待4分钟 :) - Kiel
22
接受这个答案的事实恰好说明了为什么PHP有如此糟糕的声誉。 - jmkeyes
3
这只是检查本地邮件服务器(或在php.ini中配置的SMTP)是否接受了发送的电子邮件。然后,邮件服务器将尝试将电子邮件发送到收件人的邮件服务器,但这是在PHP的mail()返回之后完成的,如其他答案所解释的那样。 - Guillaume Boudreau

13
首先,我建议使用第三方邮件库(SwiftMailerPHPMailerZend_Mail等)发送电子邮件,而不是使用内置的mail功能。撰写电子邮件比大多数人意识到的要复杂得多,特别是如果您想要进行多部分和/或HTML格式的电子邮件。
其次,在检查消息是否成功传递到第一个(通常是本地)电子邮件服务之外,几乎不可能确定是否已发送电子邮件。这是由于电子邮件固有的工作方式所致,对此无法做出太多改变。
唯一能做的事情是(并且真正应该做的事情),确保您的系统以明智的方式处理退回的电子邮件。例如,如果一个电子邮件地址不断反弹,请考虑取消订阅该地址。

感谢Brenton的建议,我会在以后使用它。现在我只需要知道是否已经发送了电子邮件,无论用户是否收到。谢谢大家! - Kiel

5

事实是:不幸的是,您无法可靠地检测电子邮件是否已发送或接收:电子邮件不是一种可靠的通信方式。

调用mail()函数的结果只表明PHP是否能够将邮件发送到MTA,但这并不能说明电子邮件是否真正发送或接收者是否真正接收到电子邮件。

如果您想要更可靠的结果,您需要使用mail()以外的其他方法。尽管我从未使用过,但PHPMailer或其他SMTP库可能会向您返回MTA发送的信息,这将告诉您更多关于排队等待交付的情况,但是如果没有轮询反弹消息(可能无法传递到发件人的收件箱),则无法确定收件人是否已收到电子邮件。


2
仅为了完整性而提及,通过`PHP`发送电子邮件并知道是否被接收的方法是存在的(这并不意味着它已被交付给用户或在SMTP握手后被静默丢弃)。
理论上,可以纯粹使用内置的流功能(例如stream_socket_client)编写SMTP客户端,以便通过SMTP协议请求和响应中形成的直接原始TCP连接与接收MTA通信。
发出SMTP命令的一般逻辑如下:
<?php
$fp = stream_socket_client("tcp://fqdn-of-receiving-mta:25", $errno, $errstr, 90);
fwrite($fp, "EHLO LOCALHOST\r\n");
fwrite($fp, "MAIL FROM: youremailaddress@something.tld\r\n");
fwrite($fp, "RCPT TO: recipient@remotedomain.com\r\n");
fwrite($fp, "DATA\r\n");
fwrite(
    $fp,
    "Subject: your subject text\r\n" . 
    "First line of message body\r\n" .
    "At the end of the message body one single period char should be placed before and after EOL character\r\n" .
    "Like this: \r\n" .
    ".\r\n" 
);

当然,这显然是不完整的(有经验的开发人员会注意到我既没有侦听也没有解析我收到的SMTP响应)。为了使用这种方法,必须在PHP语言中进行严格的重新发明轮子。
这将如何用于检测电子邮件是否已发送?
嗯,您至少会有3种类型的信息:
1. 接收主机是否存活并能够接收电子邮件消息 2. 在握手期间是否避免了反弹(SMTP 5xx响应类) 3. 在提交消息文本后是否收到SMTP 250 2.0.0 Ok 再次强调,这仅用于教育目的,除非您准备开发符合标准的SMTP客户端项目,否则请勿在家中尝试。

0

你也可以尝试这个

$send = mail($to,$subject,$msg);
if($send)
{
    echo "Your Account is Successfully Created. You must Activate your account.";
}
else
    echo "Failed to send";

4
这个答案是被接受的答案的复制,只是不太准确(缺少@符号)。 - physicalattraction

0
我想在@Daya的答案中添加更多信息,并对他的答案进行一些修改,具体如下:
如果电子邮件发送成功,则没有问题,但如果邮件功能出现错误,开发人员将如何获得错误信息?为此,他/她可以使用error_get_last()函数获取最后一个错误,修改如下:
if(!$mail) {
  print_r( 'Mailer error: ' . error_get_last());
} else {
  echo 'Message has been sent.';
}

-3

$send = mail($emailRecipient, $subject, $message, $headers);

检查 $sent 的返回值,例如:如果 ($send['error_code'] == 0) { echo "发送成功"; } else { echo "发送失败"; }


PHP的mail函数不会返回一个数组。 - Nico Haase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接