Назад | Перейти на главную страницу

Postfix отклоняет исходящее письмо с несколькими получателями из-за одного неверного адреса

Я отправляю свои электронные письма с помощью 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>

Эта ошибка возникает, когда я пытался отправить электронное письмо с mehran@hotmail.com в качестве основного получателя и 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 адреса или нет, просто когда он отклоняет один адрес, весь запрос отклоняется !! И на адрес mehran@hotmail.com (который указан в To)!

Теперь в мой код возвращается сообщение об ошибке (PHP, созданный MUA):

5.1.3 Bad recipient address syntax

Что касается моего PHP-кода, который взаимодействует с SMTP сервер:

$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.

TL; DR: Ваш случай - ненормальное поведение почтового клиента при правильной транзакции 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:<mail@example.com>
S: 250 OK
C: RCPT TO:<john@example.net>
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:<mail@example.com>
S: 250 OK
C: RCPT TO:<john@example.net>
S: 250 OK
C: RCPT TO:<doe@example.net>
S: 250 OK
C: RCPT TO:<alice@example.net>
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:<mail@example.com>
S: 250 OK
C: RCPT TO:<john@example.net>
S: 250 OK
C: RCPT TO:<invaliduser@example.net>
S: 550 5.1.1 <invaliduser@example.net>: Recipient address rejected: User unknown in local recipient table
C: RCPT TO:<alice@example.net>
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 Framework)

<?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:<from@example.net>
SERVER -> CLIENT: 250 2.1.0 Ok
CLIENT -> SERVER: RCPT TO:<valid@example.org>
SERVER -> CLIENT: 250 2.1.5 Ok
CLIENT -> SERVER: RCPT TO:<bounce@example.net>
SERVER -> CLIENT: 250 2.1.5 Ok
CLIENT -> SERVER: RCPT TO:<invaliduser@example.net>
SERVER -> CLIENT: 550 5.1.1 <invaliduser@example.net>: Recipient address rejected: User unknown in local recipient table
SMTP ERROR: RCPT TO command failed: 550 5.1.1 <invaliduser@example.net>: Recipient address rejected: User unknown in local recipient table
CLIENT -> SERVER: RCPT TO:<root@example.net>
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 <valid@example.org>
CLIENT -> SERVER: From: First Last <from@example.net>
CLIENT -> SERVER: Subject: PHPMailer SMTP test
CLIENT -> SERVER: Message-ID: <b67f817cacdff282e92dc17f9c4f406b@web.example.net>
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 <invaliduser@example.net>: Recipient address rejected: User unknown in local recipient table; from=<from@example.net> to=<invaliduser@example.net> proto=ESMTP helo=<web.example.net>
Nov 19 09:28:16 cache postfix/cleanup[14867]: D7D3E84403: message-id=<b67f817cacdff282e92dc17f9c4f406b@web.example.net>
Nov 19 09:28:17 cache postfix/qmgr[1200]: D7D3E84403: from=<from@example.net>, size=617, nrcpt=3 (queue active)
Nov 19 09:28:17 cache postfix/local[14870]: D7D3E84403: to=<root@example.net>, 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=<valid@example.org>, 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=<zbounce@example.net>, 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 работают в нормальных условиях. Вы можете использовать это для сравнения с почтовым журналом в вашем ящике :)

На самом деле почтовые серверы работают не так. Они предназначены либо для отправки почты, либо для возврата конечному пользователю ошибки / причины сбоя, если что-то не работает. Изменение этого поведения меняет способ работы SMTP.

Как Вики-страница в отчетах о недоставке говорится:

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.

Измените файл Postfix / main.cf, раскомментировав следующую запись в файле. Перезапустите postfix и попробуйте отправить еще раз.

local_recipient_maps

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