Sendmail зависает, когда домен MX не существует

Я использую библиотеку PHP SwiftMailer для массовой отправки электронных писем (после CANSPAM и RFC).

Все работает нормально, пока я не натыкаюсь на домен, у которого нет соответствующей записи MX в DNS. В этот момент мой скрипт просто зависает - я предполагаю, что это из-за того, что sendmail не вернулся. Это может длиться всего несколько минут, а может длиться много часов.

Я подтвердил, что адреса, на которых висит мой скрипт (slash sendmail), не имеют записи DNS MX. Все остальное отправляет нормально.

Есть ли способ проверить, существует ли DNS MX внутри PHP, прежде чем я попытаюсь отправить сообщение? Является ли это масштабируемым (то есть, действительно ли этот дополнительный поиск в DNS замедлит меня, или это будет нормально, потому что MX кэшируется локально для использования sendmail при доставке сообщения)?

Спасибо за вашу помощь

--- ОБНОВЛЕНИЕ --- Я попробовал приведенные ниже решения, которые помогли мне сузить круг проблем. Кажется, дело не в том, существует ли запись MX. Проблема в том, что поиск DNS занимает вечность, чтобы вернуться. Есть ли простой способ установить время ожидания, чтобы, если DNS не вернется в течение ‹ 5 с, я мог двигаться дальше?


person Travis Leleu    schedule 10.11.2010    source источник


Ответы (3)


getmxrr(substr($email,strrpos($email,'@')+1),$hosts);
if (!$hosts)
    echo 'No MX record found';

Вы также можете попробовать это, чтобы предотвратить блокировку (нет параметров для настройки тайм-аута getmxrr):

if (!@fsockopen(substr($email,strrpos($email,'@')+1),25,$errno,$errstr,5))
    echo 'No MX record found';
person bcosca    schedule 10.11.2010
comment
Благодарность! это помогло; теперь кажется, что проблема не в том, существует ли он или нет, а в задержке в возврате этого значения. Обновлен вопрос выше, какие-либо предложения о том, как сделать этот запрос тайм-аутом через 5 секунд? - person Travis Leleu; 10.11.2010
comment
Так не будет ли это пытаться просто открыть сокетное соединение с доменом электронной почты? Моя проблема в том, что (часто) я отправляю на onedomain.com (который может иметь или не иметь запись A), но MX предназначен для two.onedomain.com. Поэтому, когда я открываю сокет, он по-прежнему (точно) не говорит мне, следует ли отправлять это электронное письмо (он говорит мне, что есть запись A для onedomain.com, где я действительно хочу знать [с коротким тайм-аутом, установленным на поиск MX], если для этого домена есть запись MX). Я правильно понимаю, что это не одно и то же? - person Travis Leleu; 11.11.2010
comment
если у домена есть запись MX, должен быть хост, который получит сокетное соединение через порт 25. если этот хост не отвечает в течение 5 секунд, fsockopen() сдается. не имеет значения, отвечает ли one.onedomain.com или two.onedomain.com. вот для чего нужны несколько записей MX: избыточность/отказоустойчивость. - person bcosca; 11.11.2010
comment
Верно, но только потому, что onedomain.com вовремя отвечает на запрос сокета, не обязательно означает, что запись MX существует. Верно? Я начинаю ходить по кругу здесь. Я очень ценю ваш вклад, большое спасибо. - person Travis Leleu; 11.11.2010

Вы можете использовать getmxrr:

if (getmxrr($hostname, $mxhosts)) {
   // MX record exists
   var_dump($mxhosts);
}
person netcoder    schedule 10.11.2010
comment
fsockopen сделает свое дело. См. отвечающий вопрос выше. - person netcoder; 10.11.2010

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

Если я правильно помню RFC, хосты с записью A также должны быть действительными адресатами электронной почты. Однако домены только с записью A могут не иметь почтового сервера по этому адресу. (То же самое относится к целям MX, но это должно происходить гораздо реже и обычно временно.)

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

person BillThor    schedule 10.11.2010