我使用 Postfix 发送电子邮件,并且我有大量电子邮件列表要发送新闻稿。因此,我更喜欢将我的 SMTP 请求打包成一个,方法是将其中一个电子邮件设置为,To
将其他电子邮件设置为Bcc
(在 PHP 中)。
我的问题是,如果其中一个电子邮件无效,Postfix 将拒绝整个请求并提示以下错误:
5.1.1 : Recipient address rejected: User unknown in local recipient table
如果我能以某种方式配置 Postfix,使其转储无效地址并发送其余地址,那就太好了。我知道在电子邮件中使用地址之前,我可以自己验证地址,但我更喜欢由 Postfix 来验证。
[更新]
以下是邮件日志的内容:
Nov 18 16:20:28 mail postfix/smtpd[12922]: 14A5FB812E1: client=localhost[127.0.0.1]
Nov 18 16:20:28 mail postfix/smtpd[12922]: 14A5FB812E1: reject: RCPT from localhost[127.0.0.1]: 550 5.1.1 <mehran_hotmail.com>: Recipient address rejected: User unknown in local recipient table; from=<mehran@localhost> to=<mehran_hotmail.com> proto=ESMTP helo=<localhost>
[email protected]
当我尝试以作为主要收件人和mehran_hotmail.com
的身份发送电子邮件时,会产生此错误Bcc
。
[更新]
以下是与该请求相关的完整日志:
Nov 19 09:47:01 mail postfix/smtpd[20947]: connect from localhost[127.0.0.1]
Nov 19 09:47:01 mail postfix/smtpd[20947]: EC281B81BCE: client=localhost[127.0.0.1]
Nov 19 09:47:01 mail postfix/smtpd[20947]: warning: Illegal address syntax from localhost[127.0.0.1] in RCPT command: <mehran@?????.com>
Nov 19 09:47:01 mail postfix/smtpd[20947]: disconnect from localhost[127.0.0.1]
这是一个新的场景(导致同样的问题),我使用了正确的电子邮件地址(和都To
持有Bcc
正确的电子邮件地址,但地址不同),但这次电子邮件地址被拒绝,因为 Postfix 无法识别它。我使用非 ASCII 字符作为域名(mehran@مهران.com)。我不在乎 Postfix 是否支持非 ASCII 地址,只是当它拒绝一个地址时,整个请求都会被拒绝!!并且不会发送电子邮件到[电子邮件保护](在 中被命名To
)!
现在返回到我的代码(PHP 制作的 MUA)的错误消息是:
5.1.3 Bad recipient address syntax
至于与SMTP
服务器交互的 PHP 代码:
$mail = new \Zend_Mail('utf-8');
$mail->setMessageId($mail->createMessageId());
foreach ($array_to as $to) {
$mail->addTo($to['email'], $to['name']);
}
foreach ($array_cc as $to) {
$mail->addCc($to['email'], $to['name']);
}
foreach ($array_bcc as $to) {
$mail->addBcc($to['email'], $to['name']);
}
$mail->setSubject($subject);
$mail->setBodyHtml($body);
$mail->setFrom($current_user_email, $current_user_name);
$mail->setDate(new \Zend_Date());
$smtp = createSmtpConnection();
$smtp->send($mail);
如您所见,我使用了 Zend Framework (v1),并且我的代码相当简单。$array_*
变量是保存电子邮件地址的简单数组。在我的测试场景中,只有两个电子邮件地址,一个用于To
,一个用于Bcc
。
答案1
总结:您的案例是邮件客户端在正确的 SMTP 事务中出现异常行为。可能是您的 PHP 代码出了问题。请参阅此主题Postfix 邮件列表. 引自该主题中的 Postfix 作者
你错了。你没有任何证据表明 Postfix 拒绝了整条消息。
众所周知,当一个收件人不被接受时,某些 SMTP 客户端程序将放弃传递消息,即使其他收件人都很好。
SMTP 拒绝是如何运作的
首先,我们将介绍 SMTP 事务。下面是 SMTP 在底层的工作方式。您可以随时通过 telnet/netcat 尝试。
情况1这是只有一个收件人时的交易。
S: 220 smtp.example.net Simple Mail Transfer Service Ready
C: HELO client.example.com
S: 250 Hello client.example.com
C: MAIL FROM:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 250 OK
C: DATA
S: 354 Send message content; end with <CRLF>.<CRLF>
C: The message data (body text, subject, e-mail header, attachments etc) is sent
C: .
S: 250 2.0.0 Ok: queued as D7D3E84403
C: QUIT
S: 221 Bye
因此,SMTP 是一种聊天协议,每次客户端发出命令(HELO/MAIL/RCPT/DATA/QUIT)时,服务器都必须在交易继续之前对其进行应答。在这种情况下,所有答案都有代码 250,或者用人类语言来说我接受了。
案例 2多个收件人的 SMTP 事务
S: 220 smtp.example.net Simple Mail Transfer Service Ready
C: HELO client.example.com
S: 250 Hello client.example.com
C: MAIL FROM:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 250 OK
C: DATA
S: 354 Send message content; end with <CRLF>.<CRLF>
C: The message data (body text, subject, e-mail header, attachments etc) is sent
C: .
S: 250 2.0.0 Ok: queued as D7D3E84403
C: QUIT
S: 221 Bye
在此示例中,有三个收件人。我们在单个事务中使用多个 RCPT 命令。RCPT 命令是特殊命令。此命令可以针对给定的电子邮件消息重复多次,以便将单个电子邮件消息传递给多个收件人。
案例 3如果部分收件人拒绝(但不是全部),则交易将继续。以下是示例交易。
S: 220 smtp.example.net Simple Mail Transfer Service Ready
C: HELO client.example.com
S: 250 Hello client.example.com
C: MAIL FROM:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 250 OK
C: RCPT TO:<[email protected]>
S: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in local recipient table
C: RCPT TO:<[email protected]>
S: 250 OK
C: DATA
S: 354 Send message content; end with <CRLF>.<CRLF>
C: The message data (body text, subject, e-mail header, attachments etc) is sent
C: .
S: 250 2.0.0 Ok: queued as D7D3E84403
C: QUIT
S: 221 Bye
为什么服务器仍然接受该电子邮件?因为除了一个无效收件人外,还有两个有效收件人。
免责声明:以上资源取自从这里。
(未成功)尝试重现问题
好的,我尝试在我的机器上重现你的问题。这是我的 PHP 代码和库phpmailer 插件. (我不熟悉 Zend 框架)
<?php
require '../PHPMailerAutoload.php';
$internaldomain = 'in.example.com';
$externaldomain = 'ex.example.com';
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPDebug = 2;
$mail->Host = "smtp6.example.com";
$mail->Port = 25;
$mail->SMTPAuth = false;
$mail->setFrom('from@' . $internaldomain, 'First Last');
$mail->addAddress('valid@' . $externaldomain, 'valid 1');
$mail->AddBCC('bounce@' . $internaldomain, 'valid 3');
$mail->AddBCC('invaliduser@' . $internaldomain, 'invalid user');
$mail->AddBCC('root@' . $internaldomain, 'valid 4');
$mail->Subject = 'PHPMailer SMTP test';
$mail->IsHTML(false);
$mail->Body = "This is test";
if (!$mail->send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
由于SMTPDebug
已启用,输出包含完整的 SMTP 事务。此输出与上面的例子类似。
SERVER -> CLIENT: 220 smtp6.example.net ESMTP at your service
CLIENT -> SERVER: EHLO web.example.net
SERVER -> CLIENT: 250-smtp6.example.net
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
CLIENT -> SERVER: MAIL FROM:<[email protected]>
SERVER -> CLIENT: 250 2.1.0 Ok
CLIENT -> SERVER: RCPT TO:<[email protected]>
SERVER -> CLIENT: 250 2.1.5 Ok
CLIENT -> SERVER: RCPT TO:<[email protected]>
SERVER -> CLIENT: 250 2.1.5 Ok
CLIENT -> SERVER: RCPT TO:<[email protected]>
SERVER -> CLIENT: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in local recipient table
SMTP ERROR: RCPT TO command failed: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in local recipient table
CLIENT -> SERVER: RCPT TO:<[email protected]>
SERVER -> CLIENT: 250 2.1.5 Ok
CLIENT -> SERVER: DATA
SERVER -> CLIENT: 354 End data with <CR><LF>.<CR><LF>
CLIENT -> SERVER: Date: Wed, 19 Nov 2014 09:28:16 +0700
CLIENT -> SERVER: To: valid 1 <[email protected]>
CLIENT -> SERVER: From: First Last <[email protected]>
CLIENT -> SERVER: Subject: PHPMailer SMTP test
CLIENT -> SERVER: Message-ID: <[email protected]>
CLIENT -> SERVER: X-Priority: 3
CLIENT -> SERVER: X-Mailer: PHPMailer 5.2.9 (https://github.com/PHPMailer/PHPMailer/)
CLIENT -> SERVER: MIME-Version: 1.0
CLIENT -> SERVER: Content-Type: text/plain; charset=iso-8859-1
CLIENT -> SERVER: Content-Transfer-Encoding: 8bit
CLIENT -> SERVER:
CLIENT -> SERVER: This is test
CLIENT -> SERVER:
CLIENT -> SERVER: .
SERVER -> CLIENT: 250 2.0.0 Ok: queued as D7D3E84403
CLIENT -> SERVER: QUIT
SERVER -> CLIENT: 221 2.0.0 Bye
和邮件日志条目
Nov 19 09:28:16 cache postfix/smtpd[14865]: D7D3E84403: client=unknown[192.168.192.100]
Nov 19 09:28:16 cache postfix/smtpd[14865]: D7D3E84403: reject: RCPT from unknown[192.168.192.100]: 550 5.1.1 <[email protected]>: Recipient address rejected: User unknown in local recipient table; from=<[email protected]> to=<[email protected]> proto=ESMTP helo=<web.example.net>
Nov 19 09:28:16 cache postfix/cleanup[14867]: D7D3E84403: message-id=<[email protected]>
Nov 19 09:28:17 cache postfix/qmgr[1200]: D7D3E84403: from=<[email protected]>, size=617, nrcpt=3 (queue active)
Nov 19 09:28:17 cache postfix/local[14870]: D7D3E84403: to=<[email protected]>, relay=local, delay=0.21, delays=0.21/0/0/0, dsn=2.0.0, status=sent (delivered to mailbox)
Nov 19 09:28:17 cache postfix/smtp[14869]: D7D3E84403: to=<[email protected]>, relay=example.org[192.168.3.3]:25, delay=0.22, delays=0.21/0/0/0.01, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 3jj7Hj0pM3z5Twh)
Nov 19 09:28:17 cache postfix/local[14868]: D7D3E84403: to=<[email protected]>, relay=local, delay=0.23, delays=0.21/0/0/0.02, dsn=2.0.0, status=sent (forwarded as 165E084404)
Nov 19 09:28:17 cache postfix/qmgr[1200]: D7D3E84403: removed
看起来在我的盒子里,postfix 和 PHPMailer 表现正常。你可以用它与你盒子里的邮件日志进行比较 :)
答案2
邮件服务器的工作方式并非如此。它们被设计为要么发送邮件,要么在出现问题时向最终用户返回错误/失败原因。更改该行为会改变 SMTP 的运行方式。
作为维基页面关于 NDR 的说法:
NDRs are a basic SMTP function. As soon as an MTA has accepted a mail for forwarding or delivery it cannot silently delete ("drop") it; it has to create and send a bounce message to the originator if forwarding or delivery failed.
答案3
修改 Postfix/main.cf 文件,取消注释文件中的以下条目。重新启动 postfix 并再次尝试发送。
本地收件人映射
电子邮件应用程序客户端尝试发送电子邮件时发生的情况与您通过命令行执行测试不同,因为命令行中允许电子邮件流继续,但检测到错误的本地地址后立即失败。